ld r1 @10 r2 M[10+R[r2]] = R[r2]
displacement
st r1 @2 r2
M[10+R[r2]] = R[r2] displacement
ld r1 @10 r2 M[10+R[r2]] = R[r2]
load displacement
st r1 @2 r2
M[10+R[r2]] = R[r2] store displacement
s = 0use r1 as s, r2 as i, r3 as flag
i = 0
while i <= 10
s = s + i
i = i + 1
mov r1 #0 ; s = 02. Sum all elements in an array. Assume the array is at 100, size of array is n.
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
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
mov r1 #0 ; s = 03. Write "pointer chasing" program in assembly language.
mov r2 #0 ; i = 0
mov r3 #100 ; set base address
:while
lt r5 r2 #n ; 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
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 +r0 r2
ld r4 +r1 r2
; member of list
.symbol
.code 0
:member2
mov r1 #1 ; constant 1
mov r2 #100 ; base address L
mov r3 #22 ; x = 22
:loop
jf r2 no ; while L != 0
ld r4 +r0 r2 ; head(L)
eq r5 r4 r3 ; head(L) == x ?
jt r5 yes
ld r2 +r1 r2 ; L = tail(L)
jmp loop
:yes
mov r5 #1
jmp exit
:no
mov r5 #0
:exit
trap r0 #0
.data 100
11 102 22 104 33 0 ; list L at 100
.end
There are three sections which must be present in this sequence:
define symbols, code section, data section. Each section starts with
a meta command: .symbol, .code, .data. The end of assembly file denotes by
.end.
.symbol
...
.code 100
...
.data 200
...
.end
The ';'
starts the comment to the end of the current
line. Comments are not interpreted by the assembler.
In symbol definition section, symbols are defined with their associated
values.
.symbol
print 1
base 100
...
Code section is the main assembly instruction. Labels can be defined in code section and they can be referred to by assembly instructions. Labels are used for destination of jump or as symbolic names in data section. A label is prefix with ":". An assembly instruction is written as shown in the instruction set definition.
For each instruction the operands are written in such a way to simplify
the assembler using prefix to identify the addressing mode.
ld r1 @10 r2 displacement
M[10+R[r2]]
ld r1 +r2 r3 index
M[R[r2]+R[r3]]
st r1 @2 r2
st r1 +r2 r3
add r1 r2 r3
add r1 r2 #20 constant value is prefix by #
The assembler does not check for all possible illegal combination of
opcode, addressing mode and operands. Here is an example
.code 0
mov r1 #0
mov r2 #1
:loop le r3 r2 #10 ; while i
<= 10
jf r3 exit
add r1 r1
r2 ; s = s + i
add r2 r2
#1 ; i++
jmp loop
:exit trap r0 #0
The data section defined constant values.
.data 100
11 22 33 44 0
s2 version 2 has three instruction formats. This version (3)
simplified the format using flat encoding (no extended op). It
limits the range of address a bit but makes it easier to understand
instruction encoding.
op:6 r1:5 r2:5 d:16
where d can store {r3,ads,disp}
disp is sign extended to 32-bit.
The assembler works in one pass (read source only once) using two phases:
phase1
input scanning, collect symbols
phase2
resolve forward references
generate object code from the token list
There are a number of predefined symbols such as opcode mnenomics (add...), register names (r0..r31). The assembler generates an output file as an object file to be loaded by the S23 simulator (one is written in Javascript). Here is the format
223001,
; magic cookie s2 ver 3.1
ads, len, ; code segment
op, a1, a2, a3, ; each instruction
...
ads, len, ; data segment
num,
; each 32-bit data
num,
0
; end of object
; a simple example of assembly language programming
; add one to ten
.symbol
print 1
.code 0
mov r1 #0
mov r2 #1
:loop
le r3 r2 #10 ; while i <= 10
jf r3 exit
add r1 r1 r2 ; s = s + i
add r2 r2 #1 ; i = i + 1
jmp loop
:exit
trap r1 #print ; print s
trap r0 #0
.data 100
0 ; dummy
.end
c:> as23 add10-s.txt
223001,
0, 9,
15, 1, 0, 0,
15, 2, 0, 1,
20, 3, 2, 10,
9, 3, 0, 7,
32, 1, 1, 2,
10, 2, 2, 1,
9, 0, 0, 2,
51, 1, 0, 1,
51, 0, 0, 0,
100, 1,
0,
0
The
simulator s23.exe takes an object file and run it.
c:>
s23 add10-s.obj
Using
the command "t" (single step), you will see:
D:\prabhas\bag\s23\test>s23
add10-s.obj
load add10-s.obj
>t
PC 0 ori 1 0
0 r1:0 r2:0 r3:0 r4:0
r5:0 r28:0 r29:0 r31:0
>t
PC 1 ori 2 0
1 r1:0 r2:1 r3:0 r4:0
r5:0 r28:0 r29:0 r31:0
>t
PC 2 lei 3 2
10 r1:0 r2:1 r3:1 r4:0 r5:0
r28:0 r29:0 r31:0
>t
PC 3 jf 3 0
7 r1:0 r2:1 r3:1
r4:0 r5:0 r28:0 r29:0 r31:0
>t
PC 4 add 1 1
2 r1:1 r2:1 r3:1 r4:0
r5:0 r28:0 r29:0 r31:0
>t
PC 5 addi 2 2
1 r1:1 r2:2 r3:1 r4:0 r5:0
r28:0 r29:0 r31:0
>t
PC 6 jf 0 0
2 r1:1 r2:2 r3:1
r4:0 r5:0 r28:0 r29:0 r31:0
>t
PC 2 lei 3 2
10 r1:1 r2:2 r3:1 r4:0 r5:0
r28:0 r29:0 r31:0
>t
PC 3 jf 3 0
7 r1:1 r2:2 r3:1
r4:0 r5:0 r28:0 r29:0 r31:0
>t
PC 4 add 1 1
2 r1:3 r2:2 r3:1 r4:0
r5:0 r28:0 r29:0 r31:0
You
can run it until stop using 'g' command.
The 'o' command shows the "output". 'h' shows the available commands.
>g
stop, execute 57 inst. 266 clocks
>o
55
>h
g - go
t - single step
b ads - set breakpoint
c - clear breakpoint
s [rn,mn,pc] v - set
d ads n - dump
r - show register
z [1,0] - display
o - show output
q - quit
h - help
>r
r0 :0 r1 :55 r2 :11 r3
:0 r4 :0 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:55
r31:0
>
we
list registers by "r", to see the result in r1 = 55.
>q
D:\prabhas\bag\s23\test>
A
dual core version of s2.3. Two cores share main memory. To
simplify simulation, each core will record its own number of
cycles. Only when "sync" instruction is executed that two cores
will be synced. There will be no simulation of memory conflict.
The simulation will execute each core, one instruction, alternately.
the compiler rz37 generates a header that
1) store the link address to the starting code to M[20]
2) starting code call to main2() and stop the simulation
In the main() a system call to "start core 2" must be present.
syscall(15,0)
Example
// dual core demo
core1()
i = 10
while( i < 100)
print(i," ")
i = i + 1
core2()
i = 1010
while( i < 1100)
print(i," ")
i = i + 1
main2()
core2()
main()
syscall(15,0)
core1()
The size of assembly file is limited to 5,000 instructions (change
MAXCODE in the header file). The maximum size of defined data is 1,000
integers (change MAXDAT in the header file). The maximum number of
symbol in the table is 900 (change TSIZE in hash.c).
The maximum size of the memory in the simulator is 20,000 integers
(change MAXMEM in the header file). The interrupt vector is at
M[1000]. The interrupt timer has two constants: divn,
timer1. Both are set to 1,000 on default (effectively interrupt
every 1,000,000 instructions). The interrupt routine uses R[31]
to store the return address (modify s23.c). The trap services are: