Special instructions - CodeAbbey/intel4004-emu GitHub Wiki
There remain few instructions still not discussed, but quite useful in certain cases.
###Loading data from code memory
FIN
loads a byte into register pair specified from the code memory pointed byR0:R1
DB
- not an instruction, but a directive used to store arbitrary bytes in the code rather than compiled instructions
This instruction is useful for long constant data, i.e. text strings. As you know, instructions
after compilation are stored in code memory (ROM) taking one or two bytes each. It is possible to
use part of this memory not for commands but for storing arbitrary bytes with special directive db
.
Let us see how this may work:
jun start
something:
db $41
start:
fim r0 something ; load address of data byte to r0:r1
fin r2 ; load byte from code pointed by r0:r1 into r2:r3
jms $3e0 ; print a character
Run this in emulator to see letter A
printed (ASCII code is $41) as a result (don't forget to clear input before running).
How this works?
First two bytes of code memory are taken by jun
instruction, then follows byte $41
which we mark
with something
to refer to it later, and then remaining code follows (from address 3).
We load the address of label something
(which is 2
) into the pair r0:r1
with fim
instruction
and then execute fin
which fetches the byte from code and places it where we want it (into r2:r3
).
So now we call magic print character subroutine and see A
at console.
The DB
directive could be followed by decimal or hexadecimal values - each meaning a separate byte, or
character strings (in single quotes) - and any mix of them, for example:
hw_str: db 'Hello, World!' 13 $a 0 ; zero-terminated sequence of bytes with line-end characters
Note that usually we place our data at beginning of the program (and jump over it) for several reasons:
- we do not want CPU to try to execute them as code if they are placed after some meaningful instructions;
- we want data addresses be small so that they fit into one byte (real CPU loads data from specific page of code memory but emulator does not follow this queer behavior).
Check hellow.asm
from examples folder to see how longer string could be printed.
###Decimal correction
To work with decimal numbers there are two handy instructions, which allow storing numbers as decimal values in a series of registers (or memory cells):
DAA
performs decimal adjust for addition on Accumulator - it means, if accumulator is10
or greater, then10
is subtracted from it and Carry is setTCS
(transfer carry subtract) - Accumulator is loaded either with10
if Carry was set, or with9
if was not - and Carry itself is cleared
The first of them allows us perform decimal addition easily. For example let us sum 6+7
:
fim r0 $67 ; r0 = 6, r1 = 7
ld r0 ; acc = 6
clc
add r1 ; acc += 7, now it is 13
daa ; acc -= 10, carry = 1
You see, after this Accumulator gets the lower decimal digit (3) and Carry is raised so it could be added to next digit.
The second could be used in the similar manner for subtraction. I hope to add comprehensive example later.
Next: Debugging and working with Console - read about emulator's special features