Computing Machinery Intel x86 - Assembly Language x86 Intel Series Microprocessor Registers Registers AX = AH,AL - accumulator BX = BH,BL - base register CX = CH,CL - counter DX = DH,DL - data register EAX - 32 bit version of the accumulator EBX - 32 bit version of the base register ECX - 32 bit version of the counter EDX - 32 bit version of the data register SI - source index register DI - destination index register BP SP IP ZF CF OF SF IF - base pointer (used to access the stack) stack pointer instruction pointer (points to next instruction) zero flag carry flag overflow flag sign flag (0 = non-negative, 1 = negative) interrupt flag (0 = reset, 1 = set) The EFLAGS register holds the operating state of the processor. These values are changed by the execution of machine language instruction. Each bit gives the state of a specific parameter relative to the last instruction executed. Bit Label 0 CF 2 PF 4 AF 6 ZF 7 SF 8 TF 9 IF 10 DF 11 OF 12-13 IOPL 14 NT 16 RF 17 VM 18 AC 19 VIF 20 VIP 21 ID Desciption . Carry flag Parity flag Auxiliary carry flag Zero flag Sign flag Trap flag Interrupt enable flag Direction flag Overflow flag I/O Priviledge level Nested task flag Resume flag Virtual 8086 mode flag Alignment check flag (486+) Virtual interrupt flag Virtual interrupt pending flag ID flag "Secret" Registers Some of the registers provided on the x86 (since the 386) by Intel are not well documented. These registers include control registers, debug registers, test registers and protected mode segmentation registers. The Control Registers are labeled CR0 through CR4. The Debug Registers are DR0 through DR7. The Test Registers (removed from the Pentium) are labeled TR3 through TR7. There are also protected mode segmentation registers, called the Global Descriptior Table Register (GDTR), the Interrupt Descriptor Table Register (IDTR), the Local DTR (LDTR) and the Table Register (TR). Running a Simple Assembly Language Program Step 1: Open an MS-DOS prompt window, go to the directory containing the DEBUG program (this could be C:\windows\command). For those of you reared on Microsoft Windows Look in the Programs directory under Startf ro MS-DOS Prompt. If you are using an old version of Windows you should find the DEBUG utility in the c:\windows\command directory. From a DOS prompt, enter, cd c:\windows\command For Windows 2000 you may need to go to the c:\winnt\system32 directory. You can obtain a command console on a Windows XP machine by running CMD from the RUN utility under START. 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. or whereever the DEBUG utility is found. Step 2: You should see a dash on the screen. Now enter -A100 (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) MOV DL, 24 MOV AH, 2 INT 21 INT 20 Now press an extra carriage return to return to the dash prompt. Step 4: Now enter G106 This will run the program and through address ...106 and then display the contents of the CPU registers. Step 5: Run the program again but this time just enter -G. The program runs and then terminates normally. In order to see the contents of the registers, we need to use the -R command. However, since the program was permitted to complete the registers are automatically cleared. To see the program stored in memory, enter -d100 which will display the contents of memory starting at address ...100. To quit DEBUG, enter Q. Viewing Assembly Code 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 You can also specify a range of addresses by included the starting and ending address separated by commas. -U 1000, 1010 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. 100 102 105 107 109 MOV AH,9 MOV DX,109 INT 21 INT 20 DB 'This is a sample 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, 100 MOV AH,9 102 MOV DX,109 105 INT 21 107 INT 20 109 DB 'This is',A,D,'a sample string.$' 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. MOV MOV MOV INT BX, 200 AL, 09 [BX], AL 20 We can check to see if the value 9 was placed at offset address 200 by calling the command -D200. Saving Programs to Disk The DEBUG program can be saved to disk 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 disk. 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. 100 102 104 106 MOV MOV INT JMP AH,2 DL,24 21 104 Before restarting the program you may want to reset the instruction pointer register (program counter) 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. MOV Instruction 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 MOV MOV MOV AL,13 AX,BX DL,CL BL,[BX] copies copies copies copies 13 to AL BX to AX CL to DL the contents of the memory at address BX to BL INT Instruction Transfers program to a procedure specified by the interrupt number. processing to the address after the INT instruction. INT INT INT INT 21h 20h 16h 10h executes executes executes executes interrupt interrupt interrupt interrupt 21 20 16 10 hex hex hex hex The interrupt returns (DOS interrupt) (.COM exit interrupt) (keyboard interrupt) (screen interrupt) JMP Instruction Transfers program to address JMP 1234 JMP 12:34 jumps to offset address 1234 jumps to segment 12, offset 34 LOOP Instruction Decements CX, and then transfers program to address if CX>0. If CX=0 transfers program to next instruction LOOP 1234 loops to offset address 1234 INC Instruction Increments a register by 1. MOV CL, 42 INC CL CL now equals 43 DEC Instruction Decrements a register by 1. MOV CL, 42 INC CL CL now equals 41 IN Instruction 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 IN AX, B3 MOV DX,FB00 IN AL,DX sends contents of 8-bit port 13 to AL sends contents of 16-bit port B3 to AX sends contents of 8-bit port FB00 to AL OUT Instruction 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 OUT MOV OUT 13, AL B3, AX DX,FB00 DX, AL sends contents of AL to 8-bit port 13 sends contents of AX to 16-bit port B3 sends contents of AL to 8-bit port FB00 XCHG Instruction Exchanges the contents of two 8 or 16-bit registers. XCHG AL, DH XCHG AX,BX CMP Instruction 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 CMP AX, BX zero flag set if AL=13 zero flag set if AX=BX TEST Instruction 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 TEST AX, BX zero flag set if AL=13 zero flag set if AX=BX 'JUMP' Instructions Jumps to an address if a CMP instruction produced a destination equal to a source. CMP AX, 13 JG 1234 JE 1234 JNE 1234 JL 1234 JGE 1234 JLE 1234 jumps jumps jumps jumps jumps jumps to to to to to to address address address address address address 1234 1234 1234 1234 1234 1234 if if if if if if AX>13 AX=13 AX/=13 AX<13 AX>=13 AX<=13 ROR Instruction 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 ROR AX,1 this is 0000 0000 1000 0011 now AX= 1000 0000 0100 0001 MOV AL,83 MOV CL,2 ROR AL,CL this is 1000 0011 now AL= 1110 0000 ROL Instruction 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 ROL AX,1 sets AX = 0000 0000 1000 0011 now AX = 0000 0001 0000 0110 MOV AX,0083 MOV CL,2 ROL AX,CL sets AX = 0000 0000 1000 0011 now AX = 0000 0010 0000 1100 SHR Instruction Shifts the register right by 1 bit. The LSB is lost, the MSB is loaded with a 0 bit. MOV AX,F002 SHR AX,1 sets AX = 1111 0000 0000 0010 sets AX = 0111 1000 0000 0001 MOV AX,F002 MOV CL,2 SHR AX,CL sets AX = 1111 0000 0000 0010 sets AX = 0011 1100 0000 0000 SHL Instruction Shifts the register left by 1 bit. The MSB is lost, the LSB is loaded with a 0 bit. MOV AX,0083 SHL AX,1 sets AX = 0000 0000 1000 0011 sets AX = 0000 0001 0000 0110 MOV AX,0083 MOV CL,2 SHL AL,CL sets AX = 0000 0000 1000 0011 sets AX = 0000 0000 0000 1100 AND Instruction Performs a Boolean AND operation. The result is stored in the destination register. MOV AX,1234 MOV BX,ABCD AND AX,BX sets AX = 0001 0010 0011 0100 sets BX = 1010 1011 1100 1101 sets AX = 0000 0010 0000 0100 OR Instruction Perfoms a Boolean OR operation. The result is stored in the destination register. MOV AX,1234 MOV BX,ABCD OR BX,AX sets AX = 0001 0010 0011 0100 sets BX = 1010 1011 1100 1101 sets BX = 1011 1011 1111 1101 XOR Instruction Performs a Boolean Exclusive OR operation. The result is stored in the destination register. MOV AX,1234 MOV BX,ABCD XOR AX,BX sets AX = 0001 0010 0011 0100 sets BX = 1010 1011 1100 1101 sets AX = 1011 1001 1111 1001 NOT Instruction Performs a Boolean NOT operation on the specified register (one's complement) MOV AX,1234 NOT AX sets AX = 0001 0010 0011 0100 sets BX = 1110 1101 1100 1011 ADD Instruction Adds a source to a destination. The results is stored in the destination register ADD AX,13 ADD AL,DL replaces AX with 13 added to AX replaces AL with AL added to DL SUB Instruction Subtracts a source from a destination. The result is stored in the destination register. SUB AX,13 SUB AL,DL replaces AX with AX minus 13 replaces AL with AL minus DL MUL Instruction (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 MUL BX multiplies AX by DL result is in AX multiplies AX by BX result is in DX,AX DIV Instruction (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 DIV BX divides AX by DL quotient is in AL, remainder is in AH divides AX by BX quotient is in AX, remainder is in DX I/O Ports A port that is common to all Intel based PCs is the parallel (printer) port. Many PC's have more than one printer port, labeled LPT1, LPT2 and LPT3 for example. The address for these ports is not the same for all computers, but we can determine these addresses for a particular computer by checking the values at memory segment 40hex, beginning at offset 8. From the DEBUG utility enter the command, D40:8 The address for LPT1 is therefore 378hex (high byte follows low byte) the next 4 bytes are 00 00 00 00 so there is only one printer port on this system. We can check to see of the printer (dot-matrix only) is working and ready to print. We can test the ACK pin for a value of 1 to verify that the printer is on and there are no errors. The pin will equal 0 if the printer is off or if there is an error. The ACK is bit 5 of port 2. 100 103 104 MOV DX, 378 IN AL,DX INT 20 Since AL=04hex (0000 0100 binary) we see that bit 5 is zero. Let's look at a short assembly program to display the contents of a register DL to the screen in hexidecimal symbols (i.e. ASCII characters). MOV MOV MOV SHR ADD CMP DL,A9 DH,DL CL,4 DL,CL DL,30 DL,39 JLE ADD MOV INT MOV AND ADD CMP JLE ADD MOV INT INT 113 DL,7 AH,02 21 DL,DH DL,0F DL,30 DL,39 127 DL,7 AH,02 21 20 ;loads DL with the value A9 (1010 1001) ;copies DL into DH ;will be used to shift DL 4 bits to the right ;DL now contains the upper nibble (0000 1010) ;adds 30hex to DL (ASCII value) (0011 1010) ;if symbol is >9 we need to add 7 this skips over ;the symbols between 0..9 and A..Z in ASCII table ;this is offset address 113 ;DOS interrupt to print to screen ;recover original value in DL ;leaves lower nibble of DL ;converts to ASCII value ;same test as on previous symbol ;this is offset address 127 ;DOS interrupt to print to screen ;terminates program Whew! All this to display two characters to the screen. It doesn't get any more exciting than this...unfortunately. "I could sit in an insurance seminar for days with a big smile on my face.. and they would ask me, 'How can you stand it?' I would say, 'Because I've programmed in assembly, I can take anything!' " -- bonus point for original context of this paraphrase.