80386 Real mode Programming 80386 is a faster 8086 in real mode, which can not only perform 32-bit operations, but also 32-bit addressing, but also use 80386 extended instructions. However, since it is in real mold, the maximum space of addressing is 1m. In a segment, the maximum length of the segment does not exceed 64K, otherwise an exception will occur. Define a full format of a segment under 8086 is: Duan [Positioning Type] [Combination Type] ['Category'] 80386 Defines a full format of a segment is: Duan [Positioning Type] [Combination Type] ['Category' ] [Property Type] Description: There are two types of attribute types: USE 32 and USE16, and use32 represents a 32-bit segment, and the USE 16 represents a 16-bit segment. If you use the directive in the program. 386, then the default attribute type is the use32 (32-bit), if you do not use the directive to specify the type of CPU, the default attribute type is use6, which can only be used in real mode 16-digit, ready to use USE16. EG: CSEG Para public USE32; Define a 32-bit segment AA DW?
BB DD? CC DB? DD DW? EE DW 0, 0, 0 ..... CSEG ENDS Since the 66H operation prefix is used in 80386 and the 67h address prefix, although in formula mode, as long as the set CPU The type is 80386, still 32-bit operation, 32-bit addressing, 66h, 67h, these two prefixes do not need to be written in the program, the assembler will automatically add. Just access the 32-bit operands in the program, or 32-bit addressing, then the operand prefix 66h and address prefix are added 67h. Conversely, these two prefixes will also be added to the assembler if the 16-bit or 8-bit access is accessed in the 32-bit segment.
One will give an example program, demonstrate how to program the method and skills in the real mode of 80386 (this is a program from the online Down, not what I wrote, but I will do a detailed anatomy, and the program under 8086 Design comparison): Double-word storage unit F000: 1234 in three forms | -------------------------------- Main Proc- ----------- | | .386 | | Code Segment Para Public 'Code' Use16 | | Assume CS: CODE | | Begin: | | MOV AX, 0F000H | | MOV FS, AX | | MOV Eax, FS: [1234H] | | CALL TODEC | | Call newline | | Call tohex | | MOV Al, 'h' | | Call echo | | Call newline | | Call Tobin | | MOV Al, 'B' | | Call Echo | | Call newline | | MOV AH, 4CH | | INT 21H | | --------------------------------------- |; Sub-function Todec Todec Proc Near Pushad Mov EBX, 10 XOR CX, CX Dec1: xor Edx, Edx Div EBX PUSH DX INC CX or EAX, EAX JNZ DEC1 DEC2: POP AX CALL TOASC CALL Echo loop Dec2 Popad Ret Todec Endp; Sub-Function Tobin Tobin Proc Near Push EAX PUSH ECX PUSH EDX BSR EDX, EAX JNZ BIN1 XOR DX, DX BIN1: MOV CL, 31 SUB CL, DL SHL EAX, CL MOV CX, DX INC CX MOV EDX, EAX BIN2: ROL EDX, 1 MOV Al, '0 '
ADC Al, 0 Call Echo loop Eax Ret Tobin Endp; Sub-function tohex tohex Proc Near CountB = 8 Enter Countb, 0 Movzx EBP, BP MOV ECX, Countb Mov Edx, EAX HEX1: MOV Al, DL And Al, 0FH MOV [EBP-COUNTB ECX-1], Al ROR EDX, 4 LOOP HEX1 MOV CX, Countb xor EBX, EBX HEX2: CMP BYTE PTR [EBP-COUNTB EBX], 0 JNZ HEX3 Inc EBX LOOP HEX2 DEC EBX MOV CX, 1 HEX3: MOV Al, [EBP-Countb EBX] Inc EBX CALL TOASC CALL Echo loop; Sub-Function TOASC TOASC PROC Near and Al, 0FH CMP Al, '0' CMP Al , '9' Seta DL MOVZX DX, DL Imul DX, 7 Add Al, DL TOASC1: RET TOASC ENDP
Sub-function newline newline proc Near Push DX Push Ax Mov DL, 0DH MOV AH, 2 INT 21 MOV DL, 0AH INT 21 POP AX POP DX RET NEWLINE ENDP
Echo Proc Near Push AX Push DX MOV DL, Al Mov AH, 2 INT 21H POP DX POP AX Echo EndP Analysis: First Look at the main program framework, below main proc: | ------------ ------ Main Proc ------------------------------- | | .386; Define the type of processor is 386 Indicates all 80386 instructions | | code segment para public 'code' use6 | | assume cs: code | | begin: | | MOV FS, AX; F000H loading segment register fs | | MOV Eax, FS: [1234H]; Double-word delivery to the register EAX | | Call Todec; Todec | | CALL NEWLINE; Call NewLine; Call NEWLINE CONSTROL | | 1234H]; | | Call tohex; call sub-process tohex | | MOV Al, 'h' | | Call echo; Display Character H | | Call newline; | | MOV EAX, FS: [1234H] | | Call Tobin; Toner Process Tobin | | MOV Al, 'B' | | CALL Echo
Call newline | | MOV AH, 4CH | | INT 21h | | ----------------------------------- ----------------------- | The content in the main program is very simple. The only difference in 8086 is that the type of CPU is to define the type of CPU with the directive, and the definition of the segment register is more than one attribute type USE16, and then the 32-bit operation is used, using 80386 instructions, other and 8086 there is no difference. The focus is to analyze a few processes. When DOWN is down, the process newline and toasc do not implement code, because this is simple, so the above TOASC, NewLine, Echo process is written by I write, these two processes code Not much and very simple, it will not be introduced. Focus on Todec, Tobin, Tohex.
a. Sub-process Todec, the main function of this sub-process is to display the content of the f000: 1234 double word unit, and then see each line of code: | --------------- -------------------------------------------- | | Todec Proc Near | | Pushad | | MOV EBX, 10 | | XOR CX, CX | | DEC1: | | XOR EDX, EDX | | DIV EBX | | PUSH DX | | INC CX | | OR Eax, Eax | | JNZ DEC1 | | DEC2: | | POP AX | | CALL TOASC | | Call echo | | Loop Dec2 | | POPAD | | RET | | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------- Operate, get the merchant and the remainder. Then, the commercialization is 10, so that the business is 0, and a series of modes (remaining numbers) obtained in this process are the decimal number series. In the main program, the contents of the F000: 1234 double word unit have been put into the EAX register. Since the number of sixteen-induced numbers are later displayed, the contents of the EAX register are not allowed, so in the sub-process Start, to put EAX's content first into the stack, so starting with Pushad in the beginning of the sub-process to enter the contents of 8 32-bit general registers.
In the label DEC1 continuously divided by 10 operation, all the remaining number is all incorporated, and the count is performed with CX. In the label DEC2, the remainder obtained in the label DEC1 is populated one by one, then it is displayed, so that the contents of the storage unit can be represented by a decimal representation, and the functions of each instruction are explained below: A1.Pushad; All 8 32-bit general registers are all in the stack A2.XOR CX, CX; CX Qing 0 A3.MOV EBX, 10; 10 => EBX A4.XOR EDX, EDX; EDX Qing 0 A5.DIV EBX; EDX storage is 32 Bit, but 0, Eax is low in 32 bits, ie FFFF: [1234] double word content; division acquisition is discharged in Eax, the remainder is placed in EDX A6.Push DX; puts the low 16-bit DX of EDX A7.INC CX; CX 1 => CX A8.OR EAX, EAX; for Eax or action, mainly used to determine whether Eax is 0, that is, whether the judgment is 0, thus determining whether it should end the label DEC1 cycle. A9.jnz Dec1 A10.POP AX; popped up in the remaining number of stacks to AX in AX in AX in AX, displaying AX's content A12.Call echo a13.loop Dec2; all the remainder is displayed A14.Popad; 8 32-bit universal registers all out of the stack A15.RET
b. Sub-process tohex push bp sp => bp sp <= SP-CNT1 | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- | | | | | = 8 | | ENTER Countb, 0 | | Movzx EBP, BP | | MOV ECX, Countb | | MOV EDX, EAX | | HEX1: | | MOV Al, DL | | And Al, 0FH | | MOV [EBP-COUNTB ECX-1], Al | | ROR EDX, 4 | | Loop HEX1 | | MOV CX, Countb | | XOR EBX, EBX | | HEX2: | | CMP BYTE PTR [EBP-COUNTB EBX], 0 | | JNZ HEX3 | | Inc EBX | | Loop Hex2 | | DEC EBX | | MOV CX, 1 | | HEX3: | | MOV Al, [ EBP-COUNTB
EBX] | | INC EBX | | CALL TOASC | | Call Echo | | Loop HEX3 | | Leave | | RET | | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------- | Analysis: The function of the sub-process is F000: 1234 The content of the double word unit is displayed in a 16-based number. First consider the algorithm that will be expressed in a 16-based number. In fact, the operand in the assembly language has been in hexadecimal Representation. Therefore, in this process, it is not possible to obtain a result of the continuous division by the continuous division. In fact, we only need to display 32-bit operations, you can display the content of every half byte (four digits). With this programming idea, it is easy to understand the subsection of the above. Of course, you will ask, why do you want to display only half bytes each time without displaying a byte? Oh, the sixteen number of hexadecimal is from 0000-11111, not half bytes. Therefore, it is necessary to circulate 8 times to display 32-bit EAX, so use ROR instructions to be looped with ROR instructions, and the 4 bits are placed in the lower 4 bits of DL each time. These eight semi-bytes are placed in the storage unit of [EBP-1] to [EBP-8]. However, the order in which the storage is low to the high, if so, the display result is definitely shown. The main feature of the label HEX2, HEX3 is to determine if the content of the F000: 1234 double word unit is 0. If it is 0, it only needs to display one of the last results, otherwise, 8-bit content is displayed.
The following is the function of each instruction: b1.countb = 8; the directive defines a local variable countb, which is 8 b2.enter countb, 0; establishing a stack frame instruction B3.Movzx EBP, BP; zero-extended BP .MOV ECX, Countb; 8 => ECX B5.MOV EDX, EAX; Eax => EDX B6.MOV Al, DL B7.And Al, 0FH; Take low 4 b8.mov [EBP-COUNTB ECX-1 ], Al; send 8 semi-byte content from [EBP-1] to [EBP-8] memory cells B9.ror EDX, 4; looped to EDX, 3 5 digits B10 .loop Hex1 B11.MOV CX, Countb B12.xOR EBX, EBX; EBX Clear 0 b13.cmp Byte Ptr [EBP-COUNTB EBX], 0; The following statement is primarily used to determine whether the source operand f000: 1234 is 0, if it is 0, only one 0 b14.jnz hex3 b15.inc EBX B16.LOOP HEX2 B17.DEC EBX B18.MOV CX, 1 B19.MOV Al, [EBP-COUNTB EBX]; Display [EBP-8] to [EBP-1] one by one. B20.inc EBX B21.CALL TOASC B22.CALL Echo B23.Loop Hex3 B24.Let; Release Stack Frame B25.Ret C. Sub - Process Tobin | -------------------------------------------------------------------------------------- ----------------------- | | Tobin Proc Near | | Push EX | | Push ECX | | BSR EDX, Eax | | JNZ bin1 | XOR DX, DX | | BIN1: | | MOV CL, 31 | | SUB CL, DL | | SHL EAX, CL || MOV CX, DX | | Inc CX | MOV EDX, EAX | | BIN2: