The PowerPoint
Let’s take a look at addressing modes at slide 105.
The MIPS instruction set
The sometimes missing multiply
You won’t find the mul
instruction
in Wikipedia page on the MIPS instruction set.
In the original MIPS instruction set there was an instruction called
mult
which stored the result of adding two 32-bit integers
into a special register pair, HI
and LO
.
If you wanted to multiply the registers $t4
and $t5
and store the result in $t6
, you used the following
two instruction sequence:
mult $t3,$t4
mflo $t6
There was also a restriction in the architecture that no multiply
or divide instruction could be issued in the two instructions following
the mflo
.
Assembly idioms
Assembly idioms, or pseudo instructions, looks like assembly language instructions, but are actually translated into sequences of one or more machine instructions.
Many of the assembly idioms provided the MIPS assembly
language with “machine
instructions” that were common on other computers.
For example
move $t8,$t9
is translated to
addu $t8,$t9,$0
Also, for load immediate,
li $t3,1000
is translated to
addi $t3,$0,1000
A few assembly idioms translate to multiple machine instructions.
For example
mul $t8,$t9,3
is translated to
addi $at,$0,3
mul $t8,$t9,$at
To provide a 32-bit load immediate,
li $t3,10000000
is translated to
lui $t3,$0,15
ori $t3,16960
This works because 15
is
(1000000 >> 16) & 0xFFFF
and
16960
is
1000000 & 0xFFFF
.
Big vs little endian
Take a look at the following references to see how the big vs little endian divide impacts network programming.
Size of integer data types
The careful programmer includes stidin.h
and uses types with names like intN_t
and uintN_t
.
The integer data types of the XC32 compiler are found
on page 144 of the
MPLAB® XC32 C/C++ Compiler User’s Guide.
Note that both the int
and long
are 32 bits.
This was not the case with the Arduino.
Arrays and structures
The textbook covers array in Section 6.4.5, after the discussion of control structures; but CSCI 255 will do arrays first!
Finding the location of an array element
Start with an array declaration.
cType X[] ;
The address of X[i]
can be computed as
Base(X
) + i
×Size(cType
).
Because the sizes of most C data types are a multiple of two, shifts are
usually used in place of multiplication.
Try to determine the appropriate code for implemented the following C program sequence.
int V[15], i ; V[3] = 17 ; V[i] = V[i+3] ;
C stores arrays in row-major order. This significantly complicates determining the address
of elements in multi-dimensional arrays.
This time start with the declaration of a two-dimensional array:
cType M[R][C] ;
The address of M[i][j]
can be computed as
Base(M
) + i
×R×Size(cType
) + j
×Size(cType
).
By the way, once these formulas were taught in the second programming course. However, Java does things a different way.
Here’s a harder one. Figure out the assembly code to implement the following C code.
int I[100][100], r ; I[17][20] = 5 ; I[r][r] = 1 ;
Finding the location of a structure member
This should be easier. Just find the offset of the member from the beginning of a structure, which should be a constant number, and then add it to the base.
In practice, this can be harder. Although members must be stored in the order they are listed in the structure definition, the padding between elements is implementation-defined. Consider the following structure definition.
struct noteInfo { int frequency ; long duration ; } ;
If long
variables must be aligned on addresses divisible by
8, the offset to duration
would be 8. Otherwise, it would
be 4.
You’d need to write a section of C code similar to the following
to figure how this works on your favorite compiler.
struct noteInfo sillyNote ; long offset = (void *) &sillyNote - (void *)&sillyNote.duration ; printf("Offset to duration is %ld\n", offset) ;
Pointers
Pointers are easy because the pointer already contains the base
address. Just add in the appropriate offset.
Remember: V[i]
is the same as *(V+i)
.
Getting down the details
It can be challenging for inexperienced assembler programmers to implement
arrays operations correctly.
The first thing you have to do is get the address of V[i]
which
is V+i
.
Assume register
that $tv
already contains V
,
the address of the V[0]
and $ti
already contains i
.
In the case, if V
is an array of integers,
the code to store the address of V[i]
into
$tx
would be something like the following:
sll $tx,$ti,2 # multiply i by 4 to obtain offset add $tx,$tv,$tx # add offset to base
Once you have the address, you can use lw
to read from
the array and sw
to write to the array. An assignment
state such as U[i] = V[j]
could be implemented
with something like the following:
la $t0,V lw $t1,j sll $t1,$t1,2 add $t1,$t1,$t0 # $t1 is &V[j] lw $t2,0($t1) # $t2 is V[j] la $t0,U lw $t1,i sll $t1,$t1,2 add $t1,$t1,$t0 # $t1 is &U[i] sw $t2,0($t1) # U[i] set to V[j]
Control flow
First follow the rules of the Translating C to
C: Control Structures page.
The unconditional goto
can be implemented with a single
j
(jump) instruction.
A conditional goto
such as
if ($ti) goto λ
where $ti
is a MIPS register containing the value
of a C expression,
can be implemented as:
bne $ti,$0,λ
Comparison and relational operators
However, the translation of the C comparison and relational operators remain.
The MIPS slt
instructions combined with the bitwise instructions
would be sufficient for doing all of this.
That is left as an exercise for the reader.
However, be careful!
Is x <= y
if and only if
x < y+1
?
Is x < y
if and only if
x-y < 0
?
Logical operators
The !
operator is easy, but the &&
and ||
binary operators and the ? :
ternary conditional
can
short
circuit and must be implemented with some form of the
if
as shown in the following table.
τ = exp1 && exp2 ; |
|
τ = exp1 || exp2 ; |
if (exp1) τ = 1 ; else if (exp2) τ = 1 ; else τ = 0 ; |
τ = exp1 ? exp2 : exp3 ; |
|
The real world
However, both compilers and humans can do much better than these inflexible rules.
Calling functions
- Translating C to PIC: Functions
- Translating !
- Largely the result of xc32 – uses
$fp
and allocates space on the stack for four save arguments - textbook’s implementation
- CSCI 255 instructor’s implementation – follows Chapter 11 and 14 of MPLAB® XC32 C/C++ Compiler User’s Guide.
- Largely the result of xc32 – uses
Those other architectures....
- x86-64 Machine Language Programming by Randy Bryant and David O’Hallaron
- Digital Design and Computer Architecture, ARM Edition by Harris and Harris