look at this Adobe Acrobat file.

advertisement
80x86 Assembly Language Programming
J.K. Hardy, Sept '95
This short paper introduces 8086 assembly language programming using the DOS debug
program.
Note that, even with the latest version of DOS and '486 and Pentium processors, debug works
only with the original 8086 microprocessor instructions and so is limited to 16-bit registers.
For initial learning this approach is good enough, but for advanced learning you will need to
work with a proper assembler such as Borland's TASM.EXE.
8086 registers
A simple model of the 8086 registers available to the programmer is shown below...
All 8086 registers are 16 bits in size although some - AX, BX, CX and DX, can also be used
as two individual 8-bit registers. In that case the lower half of, for example, register AX would
be called AL and the upper half would be AH.
Each register tends to have a special use; these aren't general purpose registers. Part of the fun
in understanding 8086 assembler is in learning which register, or which pair of registers, to use
with which instruction.
The Status bits (or Flags) change as numbers change in the individual registers. Often these
changes are ignored but they are important when decisions must be made. For example, if a
register happens to hold all zeros as the result of some operation then the Z bit in the status
register will become "1".
8086 Addresses
In DOS Mode (also called Real Mode) the 8086 can only handle 1 MByte of memory. But
this requires 20 address bits which is more than any one register can hold.
For addresses in main memory, one of the Segment:Offset register pairs is therefore needed
to handle 20 bits. Four different pairs are available and the normal pair association is shown in
the right side of the previous diagram.
When operating as a pair the two 16-bit values are added together, with a 4-bit offset, to yield
the 20-bit address - enough to identify one byte out of 1,048,000 bytes.
Some basic 8086 instructions:
The following list is just a brief introduction to some common 8086 instruction mnemonics.
You will have to look elsewhere for a full description of all instructions and the intricies of
their operation and different addressing mode options.
Intel instructions tend to read backwards. Note how the first instruction below adds from the
last register (BX) into the first register (AX). The answer is left in AX.
ADD AX,BX - add the value held in BX to the value in AX
MOV AX,05 - move a specific value into a register
MOV AX,[200] - move a value from a memory location into AX
AND AX,BX - logically AND BX into AX
OR AX,BX - logically OR BX into AX
XOR AX,BX - logically Exclusive-OR BX into AX
NEG AX
- form the 2's complement negative value
NOT AX
- form the 1's complement of AX
INC AX
- add one to AX
DEC AX
- reduce AX by one
DIV BX
- divide AX by BX. AX = quotient, DX = remainder
MUL BX
- multiply the value in BX with the value in AX. Result in DX+AX.
Caution - When experimenting, don't mess with registers other than AX, BX, CX and DX.
While it is unlikely, you could damage files or even format your hard disk.
Examples
1 - This machine language program simply adds two numbers ( 5 + 7 = ?? ) It is written here
as a debug script. You type all the material into a text editor and then run it in one shot. To
create the source file you need a text editor. We will assume the MS-DOS EDIT.COM editor.
Start the editor by typing EDIT C:\MATH.SRC Type in each of the 10 lines exactly as shown
below. Finish each line by pressing the Enter key. Notice the blank line after ADD and the
extra press of the Enter key after the last Q. The cursor should be sitting below the Q when
you exit the editor.
After this works correctly try changing the two values 05 and 07 to something different - but
remember that you are working in hexadecimal.
This assembly language program contains only three instructions - MOV, MOV and ADD.
The remaining lines are debug commands needed to assemble (A) , trace (T) and quit (Q) the
program. For learning try to mentally separate the program from the extra debug commands.
----------------------------------------A 100
MOV AX,05
MOV BX,07
ADD AX,BX
T=100
T
T
Q
----------------------------------------Now run your program by typing..
DEBUG < C:\MATH.SRC
The "trace" command T runs each line of your program one step at a time so you can see the
registers change.
2 - Here is another. You could call it MATH2.SRC The program calculates ( 5 + 3 ) * 7 =
??? The result of the multiplication will be 32 bits. The lower 16 bits will be left in AX. The
upper 16 bits, if needed, will use the DX register. The program itself consists of five 8086
instructions. The rest are debug commands.
---------------------------------------------A 100
MOV AX,05
MOV BX,03
ADD AX,BX
MOV BX,07
MUL BX
T=100 5
Q
--------------------------------------------If you can't see all of this program on the screen when it runs, try this...
DEBUG < MATH2.SRC > RESULTS.TXT
Then use the text editor to look at the results.txt file.
3 - The third example adds four numbers together. You could call it ADD4.SRC. What is new
in this case, is that the numbers are already in memory, starting at location 200, when the first
instruction starts. They were placed there with the examine (E) command in debug.
The [200] addresses in memory are called Offset values. The exact memory location is
controlled by a segment register that is under debug's control. We don't modify that value in
this example.
--------------------------------------------E 200 05 06 07 08
A 100
MOV AL,[200]
ADD AL,[201]
ADD AL,[202]
ADD AL,[203]
T=100 4
Q
---------------------------------------------
4 - The fourth example moves to full segment offset addressing.
It places a flashing letter 'A' someplace on the screen. The exact memory location is
B800:0950 - as defined by the DI and DS registers. The 41 value is the ASCII character 'A'
and the BF value is the colour and flashing attribute for the screen. Notice that the DS register
could not be loaded directly. We have to load the AX register and then copy that into the DS
register.
------------------------------------------------A 100
MOV AX,B800
MOV DS,AX
MOV DI,0950
MOV AX,BF41
MOV [DI],AX
T=100 5
Q
-------------------------------------------------
5 - This next program is different. Debug will create an executable file which will then be able
to run on its own. Debug will no longer be needed.
Use your editor to type this file up as MESSAGE.SRC. Type in each line as shown. Don't
leave any extra spaces at the beginning of each line - no indents. Be sure to leave one blank
line after DB "Hello There" and also to include an extra [Enter] after the final "Q". Check
your typing carefully and then save the file.
------------------------------------------------------------N MESSAGE.COM
A
MOV DX,10B
MOV AH,9 ; Request DOS to
INT 21 ; display message.
MOV AH,4C ; Request DOS to
INT 21 ; terminate program.
DB "Hello There ! $"
RCX
3F
W
Q
------------------------------------------------------------Then type the following command...
DEBUG < MESSAGE.SRC
Your program will be assembled and turned into MESSAGE.COM
Run your program by typing MESSAGE.
This program uses two features built into DOS itself:
- a request to display the message. Code inside DOS does the actual displaying.
- a request to terminate the program. Again, DOS code handles this.
The request mechanism is a "DOS function call" which involves:
MOV AH,??
and
INT 21
5 - Ten Second Time delay
------------------------------------------------N TEN_SEC.COM
A 100
PUSH ES
PUSH BX
PUSH AX
MOV AX,0000
MOV ES,AX
MOV BX,46C
ES: MOV AX,[BX]
ADD AX,00A0 ; This is the time value.
JB 11B
ES: CMP AX,[BX]
JNZ 113
JMP 126
NOP
ES: TEST BYTE PTR [BX],00
JNZ 11B
ES: CMP AX,[BX]
JNZ 121
POP AX
POP BX
POP ES
MOV AH,4C
INT 21
RCX 30
W
Q
DEBUG
Can be used to:
- Display and change memory locations.
- Read and write to I/O port locations.
- Assemble mnemonic instructions for the 8088.
- Unassemble instructions.
- Run and single step through programs.
- Read and write from/to disk files.
Debug is started with:
DEBUG
- if you don't need a specific file.
DEBUG Junk.abc - to work with a specific file.
All commands begin with a single letter:
A [address]
- assemble from 8088 mnemonics.
C range address
- compare two ranges.
C100,1FF 300
D [range]
- display memory.
E address [list]
- examine/enter memory values.
F range list
- fill a range of memory with some values.
G [=address [address]]
- execute a program with optional breakpoints.
H value value
- perform Hexadecimal addition and subtraction.
I port
- input a byte from an IO port.
L [address [drive:logical_sector]]
- load information from disk sectors.
M range address
- move a block of memory.
N filename
- provide a file name for L or W commands.
O port byte
- output a byte to an IO port.
Q
- quit debug.
R [register_name]
- display or alter registers.
T [=address] [step]
- trace several instruction steps.
U [range]
- unassemble code.
W [address [drive:logical_record]] - write information to disk.
Download