using S2 processor: assembler, simulator
An assembler performs conversion from
assembly language (mnemonic) to machine code (object)
register to register
mov r1 #11
mov r2 #0
mov r2 r1
register to/from memory
ld r1 100 ; R[1] = M[100]
add r2 r1 #2 ; R[2] = R[1] + 2
st r2 100
a = b + c
local variables are stored in registers
let r1 - a, r2 -b, r3 - c
add r1 r2 r3
global variables are stored in memory
let M[100] - a, M[101] - b, M[102] - c
let r1 - a, r2 - b, r3 - c
must move data from memory to register before perform addition
ld r2 101 ; get b
ld r3 102 ; get c
add r1 r2 r3
st r1 100 ; store to a
using index addressing, base address points to the beginning of the
array
ax[10] ax starts at 100 base address
to get an element at ax[1]
let r2 - index, r1 - base, r3 - value
mov r2 #1
mov r1 #100
ld r3 +r1 r2 ; R[3] = M[ R[1] + R[2] ]
while condition
body
:loop
test condition
jump if false to exit
body
jump loop
:exit
i = 0
while i < 10
i = i + 1
let r1 - i, r2 - flag
mov r1 #0
:loop
lt r2 r1 #10
jf r2 exit
add r2 r2 #1
jmp loop
:exit
sum all elements of an array
ax[10]
s = 0
i = 0
while i < 10
s = s + ax[i]
i = i + 1
let r1 - s, r2 - i, r3 - base, r4 - ax[i], r5 - flag
mov r1 #0
mov r2 #0
mov r3 #100
:loop
lt r5 r2 #10 ; i < 10
jf r5 exit
ld r4 +r3 r2 ; get ax[i]
add r1 r1 r4 ; s = s + ax[i]
add r2 r2 #1 ; i = i + 1
jmp loop
:exit
get and unzip the package s21-3.zip (see Tools section at the main
page)
what is inside the package
assembler, simulator
how to use assembler
console
> as21 asm.txt
the outputs are two files: listing and object. listing shows human
readable, use to check program. object is the machine code.
run with simulator
minimum
.code 0
....
.end
<show working assembler>
commands:
help - h
single step - t (trace)
see registers - r (register)
see memory - d (dump)
set memory - s (set)
quit - q
<show running examples>
show simple programs
summarise what we learn of the instruction set, up to now
mov
add
ld/st, index
logic: comparison, lt
jf, jmp
stop: trap r0 #0
--------------------------------
if then else
call a subroutine
a complete assembly language file consists of three sections. what we have
seen is "code section"
symbol section
code section
data section
.symbol
ax 100
.code 0
add r1 r2 r3
.data 100
0 1 2 3 4 5
.end
so that you can use 'name' instead of values
a = b + c
.symbol
a 1 ; r1
b 2 ; r2
c 3 ; r3
.code 0
mov b #3
mov c #4
add a b c
trap a #1 ; print
trap r0 #0 ; stop
.end
.data 100
1 2 3 4 5
.end
let's start to write a program
test condition and use jump and jump condition
to choose which action to take
if a == 0 then b = 1 else b = 2
let r1 - a, r2 - b, r3 - flag
.symbol
a 1
b 2
flag 3
.code 0
mov a #1
mov b #0
eq flag a #0
jf flag else
; true
mov b #1
jmp exit
:else
mov b #2
:exit
trap r0 #0
.end
to perform a "jump" to subroutine, we need a way to "come back" to where
we call.
use a register to store "return address"
jump to a subroutine use
jal r1 address
jal - jump and link, store return address in r, and jump to
address
.code 0
:main
mov r1 #3
jal r2 double ; r2 store return address
trap r0 #0 ; stop
:double
add r1 r1 r1 ; double r1 value
ret r2
.end
we use a stack. stack is a data structure with two operations: push, pop
push r1 r2
; pushing value of
r2 to stack points by r1
r1 is called a stack pointer (sp)
pop r1 r2
; poping a value from
stack to r2
a stack pointer will be increment/decrement according to operations
let r3 - sp
.code 0
mov r3 #100
mov r1 #11
push r3 r1
mov r1 #0
pop r3 r1
.end
to pass a parameter to a subroutine, you push the value. then in the
subroutine, you know that parameter is at the top of stack. when you want
to use the value, just pop it.
rewrite the above program to pass value in stack. as a convention, we
return a value from a function via a register called "retv".
main()
print(double(2))
double(x)
return x + x
let r3 - link, r2 - x, r1 - temp, r4 - sp, r27 - retv
.symbol
link 3
x 2
tmp 1
sp 4
retv 27
.code 0
:main
mov sp #100
mov tmp #2
push sp tmp
jal link double
trap retv #1 ; print retv
trap r0 #0 ; stop
:double
pop sp x
add retv x x ; double x
ret link
.end
ascii code of 'a' is 97, 'z' is 122. to print a character we use
trap r1 #2
; print value in r1 as a character
print character a..z
a = 97
while a < 123
printc(a)
a = a + 1
.code 0
mov r1 #97
:while
lt r2 r1 #123
jf r2 exit
trap r1 #2
add r1 r1 #1
jmp while
:exit
trap r0 #0
.end
modify this program to
string is stored in a buffer, an array of character, ends with 0
print string (1)
get a character from memory and print it
until found 0
str[10]
i = 0
a = str[i]
while a != 0
printc(a)
i = i + 1
a = str[i]
.code 0
mov r1 #0
mov r3 #100
ld r2 +r3 r1
:while
ne r4 r2 #0
jf r4 exit
trap r2 #2
add r1 r1 #1
ld r2 +r3 r1
jmp while
:exit
trap r0 #0
.data 100
97 98 99 100 101 102 0 ; "abcdef"
.end
x = *v
ld r1 @disp r2
; r2 stores an address, disp is an offset from that address ld r1 @0
r2 ; x = *v
print string (2)
get a character from memory and print it
until found 0
str[10]
a = *str
while a != 0
printc(a)
a = *str
.code 0
mov r3 #100 ; start at 100
ld r2 +0 r3 ; *str
:while
ne r4 r2 #0
jf r4 exit
trap r2 #2
add r3 r3 #1 ; str++
ld r2 +0 r3
jmp while
:exit
trap r0 #0
.data 100
97 98 99 100 101 102 0 ; "abcdef"
.end