x86 Assembly Language

Compared with the VSC the x86 family of microprocessors have an extensive set of registers.  They have a minimum of 14 internal 16-bit registers, some of which can be accessed as two different 8-bit registers.  For example AX, BX, CX and DX are word (16-bit) registers.  AL, AH, BL, BH, CL, CH, DL and DH are byte (8-bit) registers.  The L means low byte and and H means high byte.  Actually AX through DX are each made up of the register pairs (AL,AH) through (DL,DH). There are 10 more registers that are each 16 bits.


A Few Assembly Language Instructions

Assembly language uses mnemonics which are short strings representing machine language instructions.  Assembly programs are made of lists of mnemonics and operands as shown in the examples below:

Common Assembly Instructions

MOV
Transfers a byte or word from source to destination.  The source can be a register, an immediate number, or an address.  The destination can be a register or an address.
    MOV AL,13    copies 13 to AL
    MOV AX,BX    copies BX to AX
    MOV DL,CL    copies CL to DL
    MOV BL,[BX]  copies the contents of the memory at
                 address BX to BL
  INT Transfers program to a procedure specified by the interrupt number.  The interrupt returns processing to the address after the INT instruction.
    INT 21h   executes interrupt 21 hex (DOS interrupt)
    INT 20h   executes interrupt 20 hex (.COM exit interrupt)
    INT 16h   executes interrupt 16 hex (keyboard interrupt)
    INT 10h   executes interrupt 10 hex (screen interrupt)
 JMP Transfers program to address
    JMP 1234     jumps to offset address 1234
    JMP 12:34    jumps to segment 12, offset 34
LOOP Decrements CX transfers program to address if CX>0,  if CX=0 transfers program to next instruction
    LOOP 1234    loops to offset address 1234
 INC Increments a register by 1.
    MOV CL, 42
    INC CL       CL now equals 43
 DEC Decrements a register by 1.
    MOV CL, 42
    INC CL       CL now equals 41

Running a Simple Assembly Language Program

We will investigate the CPU using a simple version of machine lanugage programs called .COM files.  These files are created using the utility program DEBUG.  This program allows you to write, edit, trace, load and save 80x86 assembly programs.

Step 1: Open an MS-DOS prompt window, go to the directory containing the DEBUG program (this could be C:\windows\command).  From the command console (once you are in the correct directory), run the DEBUG utility by typing its name at the prompt and pressing the <Enter> key.

Step 2:  You should see a dash on the screen.  Now enter

(the dash - is already on the screen, so you don't have to enter it).  This tells your program to begin at address 100 hex.  All .COM files are loaded at address 100 hex.  You should see two groups of four digits (hex) separated by a colon.  This is the actual address at which you will be entering your assembly program.

Step 3:  Enter the following program (press enter at the end of each line)

Now press an extra carriage return to return to the dash prompt.

Step 4: Now enter

You should see a $ printed to the screen.

Step 5:  Type Q and press <Enter> to quit DEBUG.

Let's take a closer look at what this program is doing. The program loads the DL register with 24 hex.  All numbers in DEBUG are hex by default.  The ASCII value of the symbol $ is 24 hex.  Then the program places the value 2 in the AH register.  The DOS operating system and its legacy as provided in the Win32 OS family supports the DOS interrupt INT 21.  This interrupt checks the value in AH to see what action is to be performed.  The 2 instructs the processor to run a section of code to print a character to the screen memory.  Finally the INT 20 causes an exit (ends the .COM program)

Viewing Register Contents and Listing .COM programs

From the DEBUG utility you can check the values of the registers using the R command. Run DEBUG and enter -R at the dash. You should see a list of register names and hex values for each.

You can view any portion of memory using the U command.  To view a page of the contents of memory at a particular location simply enter the command followed by the starting address

-U100

Notice that the upper 16 bits of the address is assumed to be the current address.  We can specify any other location in memory by including the complete address

-U 1234:1234

You can also specify a range of addresses by including the starting and ending address separated by commas.

-U 1000, 1010

When using the U command every word is interpreted as an assembly language instruction.  When the contents of a memory address cannot be interpreted as an instruction the U command displays questions marks ???.  Alternatively we can view the contents of memory as data (in hex) by using the D command.

-D100

Each pair of hexadecimal digits is one byte, and each line shows 16 bytes. Note that the address changes by 10 hex or 16 decimal.  The block on the right-hand side shows the equivalent ASCII symbol for each byte in the range 0..127 decimal.
 

Printing Messages to the Screen

If you wanted to print messages to the screen it would be rather cumbersome to print one character at a time. Instead we can Set AH=9 to instruct the DOS interrupt INT 21 to print an entire string.

Enter and run this program.  If we view the source code using the U command the string is interpreted as a sequence of assembly lanauge instructions.  It is sometimes preferred to use the D command and view the code as data.

You can invoke a carriage return using the ASCII value 10 (A hex) and a linefeed using the ASCII value 13 (D) as shown below,


Indirect Addressing Mode

To place the number 9 hex into offset address 200 hex, we load the address 200h into BX, load the value 9 into AL and the transfer the value AL into the memory location pointed to by BX.

We can check to see if the value 9 was placed at offset address 200 by calling the command -D200.

Now try this.

Saving Programs

The DEBUG program can be saved to the hard drive by following the procedure outlined below:
 

1. Set the BX register to 0.

2. Set the CX register to the number of bytes contained in the program.

3. Use the N command to name the program.

4. Use the W command to write the program to the hard drive.


The BX and CX registers can be set to any value by using the R command.  Typing the command

RBX

causes the DEBUG utility to display the contents of this register and wait for you to enter a new value.  To keep the present value just press the <Enter> key.  Otherwise enter the new value.  In this case you will want to enter a 0 value.

Next set the CX register to the number of bytes contained in the program being saved.  You can set this register to a value that is larger than the program size but this is not recommended.

Now set the name of the program to be saved using the N command

-Ntest.com

You can save .COM files to the A: drive by including the drive letter as part of the file name.

-NA:test.com

Finally you can write the file to the designated drive by using the W command.  To retrieve the saved program set the name and then enter L (load command).
 

Interacting with the .COM Program During Execution

Write and run the mystery .COM program below and then use the <Cntrl><Break> command to interrupt it.  For Windows 2000 you can stop the program with a <Cntrl> C.  If you touch any other key you may have to close the console window to interrupt this program.

Before restarting the program you may want to reset the instruction pointer register to 100 using the command,

-RIP
100

You can specify a breakpoint to stop the program by including the breakpoint address following the G command.

-G 102

When the breakpoint is reached the values of the registers are displayed to support diagnostics.   Setting breakpoints is a good way to view the contents of the registers before they are reset on exit.

More Assembly Instructions

IN 
Transfers a byte or word from an external port to AX.  If the port value is greater than FF hex, then it must be placed in register DX.
    IN AL, 13      sends contents of 8-bit port 13 to AL
    IN AX, B3      sends contents of 16-bit port B3 to AX
    MOV DX,FB00 
    IN AL,DX       sends contents of 8-bit port FB00 to AL
 OUT
Transfers a byte or work from AL or AX to an external port.  If the port value is greater than FF hex, then it must first be placed in register DX.
    OUT 13, AL     sends contents of AL to 8-bit port 13
    OUT B3, AX     sends contents of AX to 16-bit port B3
    MOV DX,FB00
    OUT DX, AL     sends contents of AL to 8-bit port FB00
XCHG Exchanges the contents of two 8 or 16-bit registers.
    XCHG AL, DH
    XCHG AX,BX
 CMP Compares a register or an immediate byte or word with a register by performing a SUB operation.  The flag register is set based on the result.  The result is discarded.
    CMP AL, 13     zero flag set if AL=13
    CMP AX, BX     zero flag set if AX=BX
 TEST Tests a register or an immediate byte or word with a register by performing an AND opera;tion.  The flag register is set based on the result.  The result is discarded.
    TEST AL, 13    zero flag set if AL=13
    TEST AX, BX    zero flag set if AX=BX
JG
JE
JNE
JL
JGE
JLE
Jumps to an address if a CMP insruction produced a destination equal to a source.
    CMP AX, 13 
    JG 1234       jumps to address 1234 if AX>13
    JE 1234       jumps to address 1234 if AX=13
    JNE 1234      jumps to address 1234 if AX/=13
    JL 1234       jumps to address 1234 if AX<13
    JGE 1234      jumps to address 1234 if AX>=13
    JLE 1234      jumps to address 1234 if AX<=13
 ROR
Rotates the register right by 1 bit.  The LSB wraps over to the MSB.  If more than 1 bit needs to be rotated, set the number of bits to rotate in the CL register first
MOV AX,0083  this is 0000 0000 1000 0011
ROR AX,1     now AX= 1000 0000 0100 0001

MOV AL,83    this is 1000 0011
MOV CL,2
ROR AL,CL    now AL= 1110 0000

ROL
Rotates the register left by 1 bit.  The MSB wraps over to the LSB.  If more than 1 bit needs to be rotated, set the number of bits to rotate in the CL register first.
MOV AL,83     sets AX = 0000 0000 1000 0011
ROL AX,1      now  AX = 0000 0001 0000 0110

MOV AX,0083   sets AX = 0000 0000 1000 0011
MOV CL,2
ROL AX,CL     now  AX = 0000 0010 0000 1100

SHR
Shifts the register right by 1 bit.  The LSB is lost, the MSB is loaded with a 0 bit.
MOV AX,F002   sets AX = 1111 0000 0000 0010
SHR AX,1      sets AX = 0111 1000 0000 0001

MOV AX,F002   sets AX = 1111 0000 0000 0010
MOV CL,2
SHR AX,CL     sets AX = 0011 1100 0000 0000

SHL
Shifts the register left by 1 bit.  The MSB is lost, the LSB is loaded with a 0 bit.
MOV AX,0083   sets AX = 0000 0000 1000 0011
SHL AX,1      sets AX = 0000 0001 0000 0110

MOV AX,0083   sets AX = 0000 0000 1000 0011
MOV CL,2
SHL AL,CL     sets AX = 0000 0000 0000 1100

AND
Performs a Boolean AND operation.  The result is stored in the destination register.
MOV AX,1234   sets AX = 0001 0010 0011 0100
MOV BX,ABCD   sets BX = 1010 1011 1100 1101
AND AX,BX     sets AX = 0000 0010 0000 0100
OR
Perfoms a Boolean OR operation.  The result is stored in the destination register.
MOV AX,1234   sets AX = 0001 0010 0011 0100
MOV BX,ABCD   sets BX = 1010 1011 1100 1101
OR  BX,AX     sets BX = 1011 1011 1111 1101
XOR
Performs a Boolean Exclusive OR operation.  The result is stored in the destination register.
MOV AX,1234   sets AX = 0001 0010 0011 0100
MOV BX,ABCD   sets BX = 1010 1011 1100 1101
XOR AX,BX     sets AX = 1011 1001 1111 1001
NOT
Performs a Boolean NOT operation on the specified register (one's complement)
MOV AX,1234   sets AX = 0001 0010 0011 0100
NOT AX        sets BX = 1110 1101 1100 1011
ADD
Adds a source to a destination.  The results is stored in the destination register
ADD AX,13     replaces AX with 13 added to AX
ADD AL,DL     replaces AL with AL added to DL
SUB Subtracts a source from a destination.  The result is stored in the destination register.
SUB AX,13    replaces AX with AX minus 13
SUB AL,DL    replaces AL with AL minus DL
MUL
(byte version) Multiplies AL by a source value.  The source can be a register or an address The result will be stored in AX.

(word version) Multiplis AX by a source value.  The source can be a register or an address.  The high 16-bit result is stored in DX, the low 16-bit result is stored in AX.

MUL DL      multiplies AX by DL result is in AX
MUL BX      multiplies AX by BX result is in DX,AX
DIV
(byte version) Divides AX by an 8-bit source value.  The source can be a register or an address.  The result is stored in AX.  The quotient is in AL, and the remainder is in AH.

(word version) Divides AX by a 16-bit source value.  The source can be a register or an address.  The quotient is placed in AX, and the remainder is placed in DX.

DIV DL     divides AX by DL quotient is in AL,
                            remainder is in AH
DIV BX     divides AX by BX quotient is in AX,
                            remainder is in DX