A few Details about A86
- Eric's A86 is case insensitive. I prefer to use all lower case.
- Anywhere a single space is used: tabs or any number of spaces are OK.
- I prefer line things up at tab stops, but you don't have to.
- Hexadecimal numbers begin with the digit zero. Decimal numbers
don't.
- Labels end with a colon.
- Anything on a line following a semicolon is ignored.
- Blank lines are ignored.
- If A86 finds an error, it inserts a note in the source. It
automatically takes the note lines out the next time it assembles.
Eric is great about knowing what an assembler should do!
- Other assemblers, MASM and TASM use somewhat different conventions,
and these programs may need some "fixing" to be assembled with anything
except Eric's A86 or A386.
- Unfortunately, all assemblers for Intel processors have a LONG
list of reserved words, and Eric's is no exception. I have spoke
with Eric about this. He does not realize what a problem it is because
he knows all the reserved words and never see's the problem.
Eric, like other implementers are deprived of the "learning
experience".
Details about each line of code
main: mov dx,datas ;DX=output start
mov ah,9 ;output to $
int 021
ret
datas: db "Hello World!$"
|
The label "main" is probably not necessary
Software Interrupt hexadecimal 21 has many variations specified in
AH. 9 is an old one that outputs everything up to a $. (Except for this
example I never use it, because you
can't output anything that has a $ in it.) But, it is supported and
makes this program very short.
The RET (return) instruction pops an address off the stack and goes
there. When a .COM program is started the operating system sets the
stack to the top of the segment the program is loaded into and pushes a
zero on the stack. Thus when the RET is executed (You will see this when
you trace the program with DEBUG.) control goes to location zero. But
the operating system has put there an int 020 instruction,
which is the normal way for a program to terminate. But I wanted to
illustrate that if nothing has been pushed on the stack, a RET
instruction is a fine way to terminate the program; and it takes one
byte instead of two.
I could not use the name: "data" because it is a reserved word!
Makes me want to say: "Oh, feces".
Now lets look at a couple variations of Hello
main: mov dx,datas ;DX=output start
mov bx,1 ;BX=StdOut
mov cx,dend
sub cx,dx ;CX= # of bytes
mov ah,040 ;DOS Write file
int 021
ret
datas: db "Hello World!"
dend:
|
This uses function Hex 40, and a count in CX. This is the general way
to write out to Standard Out, which defaults to the screen; and allows
redirection to a file, if that is wanted.
Oh, feces. "end" is also a reserved word!
The label "dend" is at the end of the message, so we can
calculate the length to put in CX. The length is calculated with the
subtract command when the program runs.
For this program it would have been better to replace the MOV and
SUB instruction with a single mov cx,dend-datas which would
have calculated the length at assembly time.Saving a couple cycles
every time the program is run. You might want to try this
program, and then shorten it and make it faster.
Good assembly programmers do as little as possible at run
time!
Now lets look at a variation of Hello that does something
main: cld ;start clean
mov dx,datas ;DX=output start
mov bx,1 ;BX=StdOut
mov di,dend ;DI=Free memory
mov cx,dend-dats ;CX= # of bytes
;Write it twice on two lines
mov si,dx ;SI=Start area
mov ax,0a0d ;AX has CR-LF
stosw ;plant AX
rep movsb ;repeat move byte
mov cx,di ;Calculate length
sub cx,dx
mov ah,040 ;DOS Write file
int 21h
ret
datas: db "Hello World!"
dend:
|
This uses CLD to make sure the MOVSB (Move String Bytes) goes from low
memory to higher. The 8086 can go either way! Usually, a program
starts this way with the direction flag clear. You can make it go the
other way with the STD instruction, which I have used to process decimal
numbers from right to left. Yes, there are some instructions to
do decimal arithmetic in the 8086!
This sets up the SI & DI registers to make a second copy using the
REP MOVSB, then calculates the length in CX. Hopefully, this is all
the explanation that you will need.
Note you could make more than
two copies by simply changing the value in CX before the move.
Don't forget to allow for the CR-LF.
It would have been smarter to have made the "datas" line
datas: db "Hello World!",0d,0a
and removing a couple instructions.
Doing less at run time! Have fun.
Using the DEBUG command to step through a
program.
There are several single letter commands in DEBUG I will give only a
short description of a few of the ones I consider most useful.
- You run DEBUG by typing something like: debug hello.com
The .COM must be included.
- DEBUG will prompt you with a dash. If you type a ? there you will
get a screen of help.
- DEBUG is case insensitive, you can use either upper or lower, I use
lower.
- The most frequently used command is "t" which steps one instruction
at a time, showing the contents of the registers, flags, and the next
instruction to be executed.
- The Q command is how you stop DEBUG.
- DEBUG is smart enough to start your program at location 100 hex.
- If you use the R instruction at the beginning you will see the
initial contents of the registers and the first instruction to be
executed.
- Many DEBUG instructions need two addresses, called "range" on the
help page. You specify this with two addresses separated by a space; or
a first address followed by an L followed by the number of byes you wish
to specify. An example is the D instruction which Displays memory in
Hex. You could use: d 100L20 to see the first 32 bytes of
your program. A use of DEBUG is to use the D command just to see a
hex dump of a file, but you must figure the length of the file in
Hexadecimal.
- The P command is very much like the T except that P goes to the
instruction following: A subroutine call, a rep string or loop, and a
software interrupt instruction. T will try to take you through each
instruction in each of these. Older DOS versions of DEBUG did not
have the P command, but I think it is in all Windows DEBUG versions.
- There is a U command that "unassembles" a string of instructions.
- The G command needs an address and will execute until that address
is reached. It is easy to "loose control" if the address points to
something other than an instruction or an instruction that is never
executed.
This can hang the computer, making a restart necessary.
Not a disaster, but a part of Assembly debugging that will make you want
to say a naughty word.
- The G, T, and P commands can be followed by an = when this is done
control goes to that location without execution the instructions in
between. I find I rarely use this.
- A number following the T or P commands tells it to execute that
number of following instructions, without any number it executes the
instructions one at a time which I use the most.
Our next sample program,
pan,
will take data from Standard In (normally the keyboard, but can be
redirected from a file) and use the Translate instruction.
The good news is: most of the description about the environment is
done. Future pages will be much shorter, and the programs will be
more useful.