ld
r1 ads R[r1] =
M[ads] absolute
ld r1 +r2 r3
R[r1] = M[R[r2]+R[r3]] index
ld r1 @d r2 R[r1] = M[d +
R[r2]] displacement
st r1 ads M[ads] =
R[r1] absolute
st r1 +r2 r3
M[R[r2]+R[r3]] = R[r1] index
st r1 @d r2 M[d + R[r2]] =
R[r1] displacement
Arithmetic: integer arithmetic operations, + - * / %. div and mod make it possible to get both quotient (div) and remainder (mod). Logic operators are bit-wise, and or xor shl shr. The exception is 'not' which returns True/False. To do conditional expression which returns True/False, and or xor not can be used in combination. For branching the comparison operators are: eq, ne, lt, le, gt, ge. They return True/False. Control operators are: jmp (uncondition), jt (jump if true), jf (jump if false), jal (jump and link), ret (return from call). Data operators: ld st. They also include push pop which operate on stack (with stack pointer). 'mov' moves data between registers.
jmp
ads
is pc = ads
jt r1 ads is if
R[r1] != 0 pc = ads jump if
r1 is true
jf r1
ads is if R[r1]
== 0 pc = ads jump if r1 is false
jal r1
ads is R[r1] = PC; PC
= ads jump and link
ret
r1
is PC = R[r1]
return
n is 17-bit sign extended
and r1 r2 r3 R[r1] = R[r2] bit-and R[r3]trap
"
instruction have two arguments. The second argument is the trap number
designated the operation.
trap r1 #n special instruction, n is
in r
2-field.jmp, jt, jf)
have 22-bit address.
no operation
14 X
shr r1 r2 r3
15 X mod r1 r2 r3
16 x mov r1 r2
17 X ld r1 +r2 r3
23 X
not r1 r2
24..4095
undefined
s = 0use r1 as s, r2 as i, r3 as flag
i = 0
while i <= 10
s = s + i
i = i + 1
.code 02. Sum all elements in an array. Assume the array is at 100, size of array is n.
mov r1 #0 ; s = 0
mov r2 #0 ; i = 0
:while
le r3 r2 #10 ; i <= 10
jf r3 exit
add r1 r1 r2 ; s = s + i
add r2 r2 #1 ; i = i + 1
jmp while
:exit
trap r0 #0 ; stop
.end
s = 0use r1 as s, r2 as i, r3 as base, r4 as ax[i], r5 as flag
i = 0
while i < n
s = s + ax[i]
i = i + 1
.code 03. Write "pointer chasing" program in assembly language.
mov r1 #0 ; s = 0
mov r2 #0 ; i = 0
mov r3 #100 ; set base address
:while
lt r5 r2 #5 ; i < n
jf r5 exit
ld r4 +r3 r2 ; ax[i]
add r1 r1 r4 ; s = s + ax[i]
add r2 r2 #1 ; i = i + 1
jmp while
:exit
trap 0 ; stop
.data 100
11 22 33 44 55 ; ax[] at 100
.end
address: 100 101 102 103
104 105 106
data: 11 102
22 104 33
0 ...
We can improve this program a bit.member(x, L)
if head(L) == x return yes
while tail(L) != 0
if head(L) == x return yes
L = tail(L)
return no
It can also be written in a recursive form.member2(x, L)
while L != 0
if head(L) == x return yes
L = tail(L)
return no
We write the second version of program in s21 assembly language. The program runs "member2(22,L)" where L = 100. That is, it checks whether 22 is in the list L.memberrec(x, L)
if head(L) == x return yes
if tail(L) == 0 return no
return memberrec(x, tail(L))
ld r4 @0 r2
ld r4 @1 r2
Put this code into a text file "mem2.txt". Assemble it using:; member of list
.code 0
:member2
mov r2 #100 ; base address L
mov r3 #22 ; x = 22
:loop
jf r2 no ; while L != 0
ld r4 @0 r2 ; head(L)
eq r5 r4 r3 ; head(L) == x ?
jt r5 yes
ld r2 @1 r2 ; L = tail(L)
jmp loop
:yes
mov r5 #1
jmp exit
:no
mov r5 #0
:exit
trap 0
.data 100
11 102 22 104 33 0 ;; list L at 100
.end
c:> as21 mem2.txt
sim21.exe
takes an object file and run it.c:> sim21 mem2.obj
c:> sim21 mem2.obj
load program, last address 106
>t
PC 0 mov r1 #1
r1:1 r2:0 r3:0 r4:0 r5:0 r28:0 r29:0 r31:0
>t
PC 1 mov r2 #100 r1:1
r2:100 r3:0 r4:0 r5:0 r28:0 r29:0 r31:0
>t
PC 2 mov r3 #22 r1:1
r2:100 r3:22 r4:0 r5:0 r28:0 r29:0 r31:0
>t
PC 3 jf r2
11 r1:1 r2:100 r3:22
r4:0 r5:0 r28:0 r29:0 r31:0
>t
PC 4 ld r4 @0 r2 r1:1 r2:100
r3:22 r4:11 r5:0 r28:0 r29:0 r31:0
>t
PC 5 eq r5 r4 r3 r1:1
r2:100 r3:22 r4:11 r5:0 r28:0 r29:0 r31:0
>t
PC 6 jt r5
9 r1:1 r2:100
r3:22 r4:11 r5:0 r28:0 r29:0 r31:0
>t
PC 7 ld r2 @1 r2 r1:1 r2:102 r3:22
r4:11 r5:0 r28:0 r29:0 r31:0
>t
PC 8 jmp
3
r1:1 r2:102 r3:22 r4:11 r5:0 r28:0 r29:0 r31:0
>t
PC 3 jf r2
11 r1:1 r2:102 r3:22
r4:11 r5:0 r28:0 r29:0 r31:0
>t
PC 4 ld r4 @0 r2 r1:1 r2:102 r3:22
r4:22 r5:0 r28:0 r29:0 r31:0
>t
PC 5 eq r5 r4 r3 r1:1
r2:102 r3:22 r4:22 r5:1 r28:0 r29:0 r31:0
>t
PC 6 jt r5
9 r1:1 r2:102
r3:22 r4:22 r5:1 r28:0 r29:0 r31:0
>t
PC 9 mov r5 #1
r1:1 r2:102 r3:22 r4:22 r5:1 r28:0 r29:0 r31:0
>t
PC 10 jmp
12 r1:1
r2:102 r3:22 r4:22 r5:1 r28:0 r29:0 r31:0
>t
stop, execute 16 instructions
PC 12 trap
0 r1:1
r2:102 r3:22 r4:22 r5:1 r28:0 r29:0 r31:0
>
c:> sim21 mem2.obj
load program, last address 106
>g
stop, execute 24 instructions
>r
r0 :0 r1 :1 r2 :0 r3
:44 r4 :33 r5 :0 r6
:0 r7 :0
r8 :0 r9 :0 r10:0
r11:0 r12:0 r13:0
r14:0 r15:0
r16:0 r17:0 r18:0
r19:0 r20:0 r21:0
r22:0 r23:0
r24:0 r25:0 r26:0
r27:0 r28:0 r29:0
r30:0 r31:0
>
jal r1 ads
" instruction.
Before jumping to the function, the return address of PC is saved in
r1. The return is done by "ret r1
", which restore PC from
r1. This register is called "link" register. push sp r1
pop sp r2
:fun
push fp r1 ; frame is at fp
push fp r2
; do fun body
; at the return
pop fp r2
pop fp r1
ret r27 ; assume r27
saved return PC
main
y = double(10)
print(y)
double x
ret x + x
:main
; y is r1
mov r1 #10
push sp r1
; pass #10
jal rads double
mov r1 retv ; y =
double(10)
trap r1 #1
; print y
trap r0 #0
:double
; use r1
push fp r1
; save r1
pop sp
r1 ; get x
add retv r1 r1 ; ret x + x
pop fp
r1 ; restore
r1
ret rads
.symbol
fp 27 ; r27
sp 28 ; r28
retv 29 ; r29
rads 30 ; r30
.main
mov fp #1000 ; frame at M[1000]
mov sp #2000 ; stack at M[2000]
....
The source code of assembler and simulator (in Python)
s2-python.zip update 28 Jan 2025