Scalar add
The first fragment adds one to a global variable and prints out the
new value. To allocate space for an initialized global variable, we must:
We want to be able to run our code fragment, so we will enclose it with
the goop needed to set-up the function, _main:
And to end the function _main:
Once we have all the surrounding goop, the code to read the current
value of _a, the global variable, is easy. We need to:
Finally, we want to print out the new value of _a. To
print _a's value using printf, we need to:
Now that we have been through all the pieces, here is the full code:
.seg "data"
.align 4
.global _a
_a: .word 10
.seg "text"
.global _main
.align 4
.proc 4
_main: save %sp, -96, %sp ! allocate stack space, advance register window
set _a, %l0
ld [%l0], %l1 ! load _a into %l1
add %l1, 1, %l1 ! _a = _a + 1
st %l1, [%l0] ! write value back into _a
set str, %o0
ld [%l0], %o1
call _printf; nop ! printf("%d\n", _a);
ret; restore
.global str
str: .byte 37 ! %
.byte 100 ! d
.byte 10 ! \n
.byte 0
Array add
The second fragment adds up the values in an initialized global array
and prints the final result. The directives needed to set up the
array are very similar those used to set up the global variable in the
previous example. The only difference is that we have one
.word directive for each element in the array.
.seg "data"
.align 4
.global _b
_b: .word 0
.word 1
.word 2
.word 3
.word 4
We need the same goop to set up _main.
.seg "text"
.global _main
.align 4
.proc 4
_main: save %sp, -96, %sp ! allocate stack space, advance register window
The main part of the function executes the equivalent of a "for" loop:
for (i=0; i < 5; i++)
total = total + b[i]
To do this, we need:
The following code initializes these registers:
set 0, %l0 ! i = 0
set _b, %l2 ! base address
set 0, %l3 ! total
The next sequence of code does the work of the loop. Notice that to calculate
the address of b[i], we add the base address (_b) to
i*4. Why times 4?
L1:
cmp %l0, 5 ! i < 5
bge L2
nop
sll %l0, 2, %l4
ld [%l4+%l2], %l4 ! %l4 = a[i]
add %l3, %l4, %l3 ! total = total + a[i]
add %l0, 1, %l0 ! i++
ba L1
nop
Another way to do this eliminates the need to multiply by four each
iteration, by storing the value i*4 in a register.
L1:
cmp %l0, 20 ! i*4 < 5*4
bge L2
nop
ld [%l4+%l2], %l4 ! %l4 = a[i]
add %l3, %l4, %l3 ! total = total + a[i]
add %l0, 4, %l0 ! %l0 = i*4
ba L1
nop
Here's the full text of the example. Notice that we
print out the value of total at the end of the
function using a code sequence that is very similar to
our earlier example.
.seg "text"
.global _main
.align 4
.proc 4
_main: save %sp, -96, %sp ! allocate stack space, advance register window
set 0, %l0 ! i = 0
set 5, %l1 ! upper bound
set _b, %l2 ! base address
set 0, %l3 ! total
L1:
cmp %l0, %l1 ! i < n
bge L2
nop
sll %l0, 2, %l4
ld [%l4+%l2], %l4 ! %l4 = a[i]
add %l3, %l4, %l3 ! total = total + a[i]
add %l0, 1, %l0 ! i++
ba L1
nop
L2:
set str, %o0
mov %l3, %o1
call _printf ! printf("%d\n", total)
nop
ret; restore ! return to caller.
Structure Print
Our third fragment prints out the values in an initialized structure,
called _c. The following contains the directives set up the
structure and the instructions to set up the function, _main.
.align 4
.global _c
_c: .word 25 ! first field is an integer
.ascii "d" ! second field is a character
.align 4 ! realign to a 4-byte boundary
.word 27 ! third field is an integer
.seg "text"
.global _main
.align 4
.proc 4
_main: save %sp, -96, %sp ! allocate stack space, advance register window
To print the three fields using printf, we need to:
and then call printf.
set _c, %l0
set str1, %o0
ld [%l0], %o1 ! first field of c
ldsb [%l0+4], %o2 ! second field of c
ld [%l0+8], %o3 ! third field of c
call _printf
nop
.global str1
str2: .asciz "%d \t %c \t %d\n"
Here's the full text:
.align 4
.global _c
_c: .word 25 ! first field is an integer
.ascii "d" ! second field is a character
.align 4 ! realign to a 4-byte boundary
.word 27 ! third field is an integer
.seg "text"
.global _main
.align 4
.proc 4
_main: save %sp, -96, %sp ! allocate stack space, advance register window
set _c, %l0
set str1, %o0
ld [%l0], %o1 ! first field of c
ldsb [%l0+4], %o2 ! second field of c
ld [%l0+8], %o3 ! third field of c
call _printf
nop
ret; restore ! return to caller.
.global str1
str2: .asciz "%d \t %c \t %d\n"
cat
Our final example implements a very simple version of the unix
command, cat. It reads one character at a time from
stdin and write ones character at a time to stdout. To implement
this, we need to
Here's the code:
.seg "data"
.global _buf ! allocate a buffer to hold a character
_buf: .byte 0
.seg "text"
.align 4
.proc 4
.global _main
_main: save %sp, -96, %sp
Loop:
set 0, %o0 ! read from stdin
set _buf, %o1 ! store char in _buf
set 1, %o2 ! read one character
call _read
nop
cmp %o0, %g0 ! have we hit the EOF?
be END
nop
set 1, %o0 ! write to stdout
set _buf, %o1 ! get char from _buf
set 1, %o2 ! write one character
call _write
nop
ba Loop
nop
END: ret
restore