Assembly Language Programming

using S2 processor: assembler, simulator

An assembler performs conversion from
  assembly language (mnemonic) to machine code (object)

Examples simple sequences of instructions

moving things around

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

assignment

  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

access to an array

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] ]

loop

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


put it all together

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

getting the tool

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

writing an assembly program

minimum
.code 0
  ....
.end

<show working assembler>

running the simulator

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


--------------------------------

writing program

  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

symbol section defines 'symbolic name' of values

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 section defines values in memory

.data 100
  1 2 3 4 5
.end

let's start to write a program

if then else

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

call a subroutine

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

to pass a parameter to a function

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

a more ambitious program

print a...z  

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

print a string

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]


 let r1 - i, r2 - a, r3 - base, r4 - flag

.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


--- end of lecture -------

Extra

in the print string above, you can use "pointer" style.  assembly language does not make distinction between data structure. we just used 'indirect addressing'. say you want to get value pointed to by v, in high level it is
    v is a pointer
    x = *v

    in assembly, use indirect address by
    ld r1 @disp r2      ;   r2 stores an address, disp is an offset from that address

    let r1 - x, r2 - v

     ld r1 @0 r2        ;  x = *v

and the above program will become

 print string (2)

 get a character from memory and print it
   until found 0

 str[10]

   a = *str 
   while a != 0   
       printc(a)
       str++
       a = *str


 let  r2 - a, r3 - pointer, r4 - flag

.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


   

last update 24 March 2020