Last issue we discussed Hexidecimal (Hex) numbers and I left you with a machine code (MC) hex loader. You should have noticed that these are very simple programs. That’s to allow you to enter and debug them easily, as well as make whatever changes you desire. Please feel free to change them.
We now need to explore the nature of MC. Since you are already familiar with BASIC, I will draw some comparisions. The first difference is that MC does not use program line numbers to tell the CPU (remember him?) in what order to perform tasks. MC instructions are executed in the order in which they occur in memory. Even after a jump (Goto or Gosub), MC continues to execute the instructions sequentially as they are found at the address jumped to.
Secondly, there are about 700 MC instructions for the Z80, as opposed to the 70 or so available in Sinclair BASIC. Don’t let this scare you off. All 700 instructions can be placed in about a dozen catagories and are, therefore, variations on a theme. We will confine each lesson to one of these catagories.
The biggest difference is in how MC “crashes”. Crash is a term used to describe the condition resulting from an involuntary exit of the program (i.e., stopping with a full screen error, undefined variable error, ect.). When MC crashes there are no error messages to aid us, due to the fact that we are not operating within the confines of the BASIC interpreter. Often, the only recovery is to pull the power plug and begin again. For this reason, I recommend you always Save your MC prior to execution. Saving it will not prevent a crash but, it does allow for easier recovery.
There are two things to remember that will help prevent MC crashes. First, you cannot use the Break key to stop your MC routine unless it is reading the keyboard and accepting a Break instruction. (Not likely in most cases.) Second, MC will not stop executing unless it is instructed to do so. MC will continue executing instructions (remember all numbers are instructions), as they are found. The easiest way to solve both problems is to end your routines with a “return to basic” instruction.
We need to determine where we will store our MC, as that is the first prompt in our MC Loader. MC can be stored almost anywhere, although above RAMTOP is best in the T/S 2068, as it can save bytes as Code. RAMTOP is a system variable which tells the BASIC operating system how much memory is available, and more specifically, what is the last available address in RAM. RAMTOP is not necessarily the very end of physical memory, however, for BASIC, it is the top of usable memory. Also, addresses above RAMTOP are unaffected by NEW. Therefore, your routine cannot be earsed.
The T/S 1000 presents some special challenges. The best place is still usually above RAMTOP, however, the 1000 cannot Save bytes from high memory. We will therefore store our MC in a REM statement. There are other ways, but this is the easiest to Save and execute for now. Later, we will find that MC can still be most anywhere.
The ease of execution from the first REM statement results from our knowing the exact address at which the MC starts. Looking in the Sinclair manual’s section on memory storage, reveals how a BASIC program line is stored:
high low low high
-----------------------------------------------------
! 2 bytes ! 2 bytes ! ! 1 byte !
!____!____!____!____!____________________!________!
Line no. Length of Text Enter
Text + 1
The first two bytes are the line number and note they are in direct opposite order of the normal storage of two byte numbers. The next two bytes are stored as the Z80 would normally store numbers and represent the length of the text in the line plus the Enter (which is used by the Basic Interpreter as an “end of line” marker). Next, follow the Basic text and finally the EOL marker. This makes the first byte after REM, the sixth byte in the line and in the program area if the line is the first line of the program. This address is 16514 in the T/S 1000, since the Basic program area begins at 16509. We will insure that we are working with the first line as follows. Type:
1 REM ENTER, POKE 16510,0 ENTER
We have also insured that our first line cannot be Edited even though it will still Save.
The next thing we need to do is make space in our REM statement to hold our MC. Refering to the chart above, the EOL marker is next after REM. We must never overwrite the EOL marker as we will cause an awful nasty crash. Type four lines of spaces after the REM (you can figure how to edit it) and Save your MC loader with your line 0 to avoid retyping it next time. This is very wasteful of memory, but will serve us well for now. Your REM statement need only contain the exact number of bytes you need, when working within a program.
We now need to know how to execute (Run) our MC. This is accomplished with the USR function. The Sinclair user’s manual is a little vague on its use. The proper syntax is:
Command USR X
Where: Command=most Basic commands
USR=USR function
X=address to begin executing from
Examples: RAND USR 16514
PRINT USR 16514
LET A=USR 16514
Boy, this is sure good stuff but, “I ain’t written no MC program yet!” Well hang in there, we will get to the actual instructions next issue. Right now though, how about a “sneak preview”?
You may have heard of such terms as opcodes, mnemonics, assembly and disassembly. Opcode is short for Operation Code, and is the Hex numbers we will be entering. They could just as easily be represented in decimal or binary, however, we have chosen Hex.
Mnemonics are another shorthand which has been designed especially for us humans. The CPU understands a long list of numbers (opcodes), however, I don’t. I do understand mnemonics as they are almost English (I did say “almost”). Look at the sample disassembly below to see what I mean.
Assembly is what we will be doing when we convert our MC programs to Hex. We will be “assembling” our MC. Assembly Language is another term for MC, and is usually used to refer to the Opcodes.
Disassembly is the opposite of assembly and is usually used to refer to a “listing” of MC instructions. You will probably want to disassemble someone elses MC after you understand what the Opcodes mean. That can help your understanding of MC, as you will already know what the program does. You will be able to see how the task at hand was accomplished. As in BASIC…there is no “single best way” to program in MC. We all develop our own style (or lack of it).
I will end this lesson with a sample disassembly (the one we previously refered to). May we soon know what it means.
Address Label Opcodes Mnemonics Comments
16514 start 3E0A Ld A,0Ah ;Put 0Ah in A register
16516 0610 Ld B,10h ;Put 10h in B register
16518 80 Add A,B ;Add 0Ah & 10h and place
16519 4F Ld C,A ;result in BC register
16520 0600 Ld B,0
16522 done C9 Ret ;Return to Basic