Machine Level Programming for Sx-chip
The machine language for Sx-chip is
S-code. S-code is the instruction set of Som-v2.
It is a simplified assembly language suitable to be a platform
independent machine language (similar to Java byte-code and Java
virtual machine, JVM). S-code execution is stack-based. It
uses a stack to keep operands during excution of the operation
code. For example, to do "1+2", the sequence of operations is:
1) push 1
2) push 2
3) do add
the stack looks like after step 2:
top
2
1
bottom
and after step 3:
top
3
bottom
This stack (called "evaluation stack") is kept in the main
memory. The pointer to this stack stored in the register SP in
the Sx-chip.
The set of operation codes in S-code includes:
add
sub mul div
and or xor not
eq ne lt le ge gt
shl shr
The data-transfer codes include:
get.v
put.v get/put local variables
ld.a
st.a ld/st global variables
ldx
stx ld/st element of an array
lit.n
pushing a constant n
inc.v dec.v
increment/decrement local var
control-transfer codes are:
call.a
ret.n call/ret a function
fun.n
function header
jmp.a jt.a jf.a jump, jump
if true/false
special codes:
array
allocate free mem
sys.n
system function
For detail of S-code including the encoding please see here.
Machine code in Z-assembler
Z-assembler (Zas) is a tool to convert a program written in S-code to
an executable program (an object code). A Sx-chip simulator can
be used to "run" this object code. The source file for Zas
consists of two sections: symbol definition, and s-code.
;
comment
name value
...
#
:label
opcode[.operand]
..
#
name is the symbolic name denotes a value (for example a local variable
number, an address of a global variable). An operand can be a lable or
a name. Zas will resolve the value of labels and names. The
output of Zas is the object file. The format of object file
conforms to Som-v2
object format.
Example of programs in S-code
1 Calculate the sum from 1 to 10.
;
a b s are local variables
sum a b
s = 0
while a <= b
s = s + a
a = a + 1
ret s
main
print sum 1 10
in S-code
;
a program to sum 1..10
a
3 ; local vars,
reverse order
b
2 ; of their
appearance
s 1
#
:main
lit.1
lit.10
call.sum
; sum(1,10)
sys.1 ; print
sys.13 ; stop
:sum
fun.3
lit.0
put.s ; s = 0
jmp.in
:loop
get.s
get.a
add
put.s ; s = s + a
inc.a ; a = a + 1
:in
get.a
get.b
le
jt.loop ; loop if a <= b
get.s
ret.4
#
2 Double every elements in an array.
To access an element of an array, ldx/stx are used. ldx requires
{ads,index} in the stack. stx requires {ads,index,value} in the
stack. This is the example:
create an array ax with 10 elements
lit.10
array
st.ax ; ax = new 10
s = ax[i]
ld.ax
get.i
ldx
put.s
ax[k] = s
ld.ax
get.k
get.s
stx
Now we can write the program:
double x
ret 2 * x
main
ax = new N
i = 0
while i <= N
s = double( ax[i])
ax[i] = s
i = i + 1
;
double every elements of an array
N 10
ax 1000 ;
address of ax[.]
x 1
i 2
s 1
#
:main
lit.N
array
st.ax ; ax = new N
lit.0
put.i ; i = 0
jmp.in
:loop
ld.ax
get.i
ldx
call.double
put.s ; s = double ax[i]
ld.ax
get.i
get.s
stx ; ax[i] = s
inc.i
:in
get.i
lit.N
le
jt.loop ; loop
if i <= N
sys.13 ;
stop
:double
fun.1
get.x
lit.2
mul ; 2 * x
ret.2
#
How to calculate offset in "fun" and "ret"
The function header "fun"contains the offset to create a new
activation record. This offset is
fs - pv + 1
where fs is the size of the activation record, pv is the number of
passing paramters. The offset for "ret" is fs.
Look at the diagram of the activation record to understand the
calculation. The old activation record is at FP'. On top of it is
the evaluation stack. The passing parameters are on the stack at
SP'. Now the size of the new activation record is the number of
all variables (pv+lv) pluses a slot to store FP'.
hi
mem
..
PC' <- SP
FP' <- FP
..
lv
..
pv <- SP'
..
sp <- SP''
.. <- FP'
lo mem
Hand-on
Try to assemble the first program, "sum-s.txt". Use the
assembler, Zas.
c:> zas sum-s.txt >
sum-s.lst
The object file output is "a.obj". The screen output is the
listing file "sum-s.lst". This file is inspeced by humans to
detect and correct any error in the source file. The listing looks like
this:
1
lit 1 287
2 lit 10 2591
3 call 6 1568
4 sys 1 292
5 sys 13 3364
6 fun 2 550
7 lit 0 31
8 put 1 281
9 jmp 6 1564
10 get 1 280
11 get 3 792
12 add 0 1
13 put 1 281
14 inc 3 802
15 get 3 792
16 get 2 536
17 le 0 12
18 jt -8 -2019
19 get 1 280
20 ret 4 1044
The first column shows the address of the S-code in the memory.
The second column shows the S-code. The last column shows the
actual machine code (executable code). Please note that the defined
symbols and lables had resolved into proper values. The object code
with the format suitable for Sx-simulator is this:
5678920
1 20
287 2591 1568 292 3364 550 31 281
1564 280
792 1 281 802 792 536 12 -2019
280 1044
0 0
Use Sx-simulator to run the object file.
C:\prabhas\bag\sx0\test>sx0
a.obj
load program, last address 21
DP 1
1 2 3 7 8 9 15 16 17 18
10 11 12 13 14 15 16 17 18
10 11 12 13 14 15 16 17 18
...
10 11 12 13 14 15 16 17 18
19 20 4 <55>5
The screen shows the sequence of address of the code during execution.
You can match this with the listing to see how the program proceeds.
The "print" to screen (sys.1) from the program appears as "<55>".
last update 3 July 2011 (National election day)