This is a hypothetical machine.
It is used to illustrate a structure of processor.
We can define and program this machine on paper.
It has a minimal set of instructions that have simple form.
First, we define the machine itself.
Z0 has fixed width instructions. Its natural size is 32
bits. It has 16 registers.
<picture of architecture of Z0>
Z0 has what is called “single address” instruction
format. That is, an
instruction has only one argument. An instruction is 32-bit, with opcode 8
bits and operand 24 bits.
Opcode:8
Operand:24
We define the first group of instruction
<operator> or <op>
Assembly language:
op reg
r0..r15add, sub, inc, decThe result is mostly stored in a special register
called “accumulator”. Most
operators store results there.
add r1
means ac
= ac + r1sub r1
ac = ac – r1inc r1
r1 = r1 + 1dec r1
r1 = r1 – 1 Another group of instructions perform data movement
between registers.
mov r1
ac = r1mvi n
ac = n
where n is a 24-bit constant, called immediateput r1
r1 = ac
that is a compliment operation of mov r1The next group of instructions is the logic group. They
are used for comparison of two values.
They affect “flag” in the machine.
This flag is one bit storage (True/False) and it is used in the
transfer of control instruction (explain next).
<logic op>
eq ne
lt le
gt ge
z
equal, not equal, less that, less than or equal …
zero
eq r1
flag = (ac == r1)ne r1
flag = (ac != r1)lt r1
flag = (ac < r1)… z r1 flag
= (r1 == 0)The next group of instructions affects the transfer of
control of program (or jump).
jmp ads
unconditional jump to ads, where ads is the location of the
instructionjt ads
jump to ads if flag is Truejf ads
jump to ads if flag is Falsestop
this is a pseudo instruction to tell us that the program has
ended.Please note that Z0 as defined right now, does not have
“external” memory (we will add that later).
All it has is the internal registers (16 of them).
Each can hold a 32-bit value.
Now we have enough instructions to perform some
computation. Let us try some
simple program in the assembly language of Z0.
We assign r1, r2, r3
to B, C and D.
mvi 0
; ac = 0 add r2
; ac = ac
+ r2 add r3
; ac = ac + r3 put r1
; r1 = ac stopEach instruction has a 8-bit code.
We assign them as follows:
1 add, 2 sub,
3 inc, 4 dec,
5 mov, 6 mvi,
7 --, 8 put,
9 eq, 10
ne, 11 lt, 12 le,
13 gt, 14 ge,
15 z, 16 jmp,
17 jt, 18 jf,
19 stopWe can write the above program in “machine code” as
follows. Assume we start the
program at location 0 and we write down each instruction as
opcode,operand.
Address
instruction
0
6,0
mvi 0
1
1,2
add r2
2
1,3
add r3
3
8,1
put r1
4
19,0
stopPseudo code
i = 1s = 0while i <= 10 s
= s + i i
= i + 1Z0 assembly language
Let r1 be i, r2 s, r3 10
mvi 10put r3mvi 1put r1mvi 0put r2 :loopmov r1le r3
; i <= 10jf exitmov r2add r1put r2
; s = s + iinc r1 ;
i = i + 1jmp loop :exitstopNotice that we use “label” such as “loop” and “exit” to
designate the location. We
use the prefix “:” to signify the labels but no prefix when they are used
in the instructions. They are used with jump instructions. Again
we write down machine code here:
Address Instruction
0
6,10
mvi 101
8,3
put r32
6,1
mvi 13
8,1
put r14
6,0
mvi 05
8,2
put r2 :loop6
5,1
mov r17
12,3
le r3
; i <= 108
18,14
jf exit9
5,2
mov r210
1,1
add r111
8,2
put r2
; s = s + i12
3,1
inc r1
; i = i + 113
16,6
jmp loop :exit14
19,0
stopNote that the labels become the real address.
“loop” is the address 6. “exit” is the address 14.
The “assembler” is the program that performs the translation of
“assembly” language into machine codes. The assembler can handle “label”
automatically.
Let numbers be B, C, D
B > C
Yes
No
B > D
C > D
Yes
No
Yes
No max is B
max is D
max is C
max is DLet r1 be B, r2 C, r3 D, r4 max
mov r1 gt r2
; B > C jf no1 mov r1 gt r3
; B > D jf no2 mov r1 put r4
; max = B jmp exit:no2 mov r3 put r4
; max = D jmp exit:no1 mov r2 gt r3
; C > D jf no3 mov r2 put r4
; max = C jmp exit:no3 mov r3 put r4
; max = D:exit stopYou will probably notice by now that programming in
machine language (assembly language) is simple but it is tedious.
In fact, machine language is the simplest computer language (you
opinion may be different from mine).
To extend the storage to main memory, we need
additional instructions to move data between registers and memory.
ld ads
; ac =
M[ads] st ads
; M[ads] =
acldd r1
;
ac = M[r1]std r1
; M[r1] = acwith these encoding
20 ld, 21 st,
22 ldd, 23 stdNow it is time to talk about “addressing space”.
The amount of memory that can be “directly” access by an
instruction depends on the number of bit of argument in the instruction.
In our machine, it is 24 bits. Therefore Z0 has 16 M words memory
(each word is 32 bits). This
is comparable to a 64 Mbytes of conventional RAM we have in our present
laptop machine. We have
“direct” addressing and “indirect” addressing.
In direct address, the argument is used to locate the “address”
directly, for example, ld 100 will access the memory at
location 100. The indirect
address, the value of a register is used as the address (this is called an
effective address). In fact,
a register has 32-bit value so theoretically we can use indirect address
of our machine to address the main memory as large as 16G bytes.
Now let us program with some data structure.
The most frequently used data structure is Array. Indirect
addressing is used to perform indexing of an array.
We can access to the value of an element as follows. Let
ax[.] be an array. An index
is in r1. The base address
(the first location where ax resides) is in r2.
C = ax[i]
can be written as
; let r2 be &ax, r1 be i, r3 be C
mov r2
; ac = iadd r1
; ac = &ax +
i, compute effective addressput r1
ldd r1
; get ax[i] into
acput r3
; C = ax[i]Using this access method, you can write a program to
sum all elements in an array. Let
us see one more example of storing a value to an array.
How to do this
ax[i] = C
Let r2 be &ax, r1 be i, r3 be C
mov r2
; ac = iadd r1
; ac = &ax +
i, compute effective addressput r1
mov r3
; get
Cstd r1
; ax[i] = C
Creating function
In a high level language, we can write a modular
program
that reuses its component. This is achieved by packaging the often use
part
into a “function” (or “procedure” or “method”).
In order for a function to return to its caller, we need to store
the
“return address” in a special data structure, usually implemented as a
“stack”. The Z0 has an
implicit stack
for this purpose (with the depth of 8). This stack is not accessible to
programmers. We need two more
instructions to do a function call:
call ads
; next pc ->
stack; jump to ads ret
;
stack -> pc
Example 4
Calling a function, passing parameters on
registers.
Let r2 x, r3 b, we pass a to x via r2 and keep return
value
in r0
:double
mov r2
add r2
;
result in r0
ret
:main
mvi 3
put r2
; pass 3 to x
call double
put r3
; store result in b
stop
Enjoy simple machine coding!