标 题: Jack对分支循环语句伪指令反汇编前后的比较
作 者: Jack Yang
时 间: 2007-04-05
知识准备:
1.
OR—Logical Inclusive OR
Opcode
|
Instruction
|
Description
|
0C ib
|
OR AL,imm8
|
AL OR imm8
|
0D iw
|
OR AX,imm16
|
AX OR imm16
|
0D id
|
OR EAX,imm32
|
EAX OR imm32
|
80 /1 ib
|
OR r/m8,imm8
|
r/m8 OR imm8
|
81 /1 iw
|
OR r/m16,imm16
|
r/m16 OR imm16
|
81 /1 id
|
OR r/m32,imm32
|
r/m32 OR imm32
|
83 /1 ib
|
OR r/m16,imm8
|
r/m16 OR imm8 (sign-extended)
|
83 /1 ib
|
OR r/m32,imm8
|
r/m32 OR imm8 (sign-extended)
|
08 /r
|
OR r/m8,r8
|
r/m8 OR r8
|
09 /r
|
OR r/m16,r16
|
r/m16 OR r16
|
09 /r
|
OR r/m32,r32
|
r/m32 OR r32
|
0A /r
|
OR r8,r/m8
|
r8 OR r/m8
|
0B /r
|
OR r16,r/m16
|
r16 OR r/m16
|
0B /r
|
OR r32,r/m32
|
r32 OR r/m32
|
Description
Performs a bitwise inclusive OR operation between the destination (first) and source (second) operands and stores the result in the destination operand location.
The source operand can be an immediate, a register, or a memory location; the destination operand can be a register or a memory location.
(However, two memory operands cannot be used in one instruction.)
Each bit of the result of the OR instruction is set to 0 if both corresponding bits of the first and second operands are 0; otherwise, each bit is set to 1.
This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
如果源操作数和目标操作数相对应的位都是0,那么OR指令结果的每一个位都设置为0;
否则,OR指令结果的每一个位都设置为1;
Operation
DEST ← DEST OR SRC;
Flags Affected
The OF and CF flags are cleared; the SF, ZF, and PF flags are set according to the result.
The state of the AF flag is undefined.
OR指令会清除OF和CF标志;SF、ZF和PF标志会根据结果来进行设置。AF标志的状态未定义。
Protected Mode Exceptions
#GP(0)
|
If the destination operand points to a nonwritable segment.
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
If the DS, ES, FS, or GS register contains a null segment selector.
|
#SS(0)
|
If a memory operand effective address is outside the SS segment limit.
|
#PF(fault-code)
|
If a page fault occurs.
|
#AC(0)
|
If alignment checking is enabled and an unaligned memory reference is made while the current privilege level is 3.
|
Real-Address Mode Exceptions
#GP
|
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
|
#SS
|
If a memory operand effective address is outside the SS segment limit.
|
Virtual-8086 Mode Exceptions
#GP(0)
|
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
|
#SS(0)
|
If a memory operand effective address is outside the SS segment limit.
|
#PF(fault-code)
|
If a page fault occurs.
|
#AC(0)
|
If alignment checking is enabled and an unaligned memory reference is made.
|
2.
CMP—Compare Two Operands
Opcode
|
Instruction
|
Description
|
3C ib
|
CMP AL, imm8
|
Compare imm8 with AL
|
3D iw
|
CMP AX, imm16
|
Compare imm16 with AX
|
3D id
|
CMP EAX, imm32
|
Compare imm32 with EAX
|
80 /7 ib
|
CMP r/m8, imm8
|
Compare imm8 with r/m8
|
81 /7 iw
|
CMP r/m16, imm16
|
Compare imm16 with r/m16
|
81 /7 id
|
CMP r/m32,imm32
|
Compare imm32 with r/m32
|
83 /7 ib
|
CMP r/m16,imm8
|
Compare imm8 with r/m16
|
83 /7 ib
|
CMP r/m32,imm8
|
Compare imm8 with r/m32
|
38 /r
|
CMP r/m8,r8
|
Compare r8 with r/m8
|
39 /r
|
CMP r/m16,r16
|
Compare r16 with r/m16
|
39 /r
|
CMP r/m32,r32
|
Compare r32 with r/m32
|
3A /r
|
CMP r8,r/m8
|
Compare r/m8 with r8
|
3B /r
|
CMP r16,r/m16
|
Compare r/m16 with r16
|
3B /r
|
CMP r32,r/m32
|
Compare r/m32 with r32
|
Description
Compares the first source operand with the second source operand and sets the status flags in the EFLAGS register according to the results.
The comparison is performed by subtracting the second operand from the first operand and then setting the status flags in the same manner as the SUB instruction.
When an immediate value is used as an operand, it is sign-extended to the length of the first operand.
The CMP instruction is typically used in conjunction with a conditional jump (Jcc), condition move (CMOVcc), or SETcc instruction.
The condition codes used by the Jcc, CMOVcc, and SETcc instructions are based on the results of a CMP instruction.
Appendix B, EFLAGS Condition Codes, in the IA-32 Intel Architecture Software Developer’s Manual, Volume 1, shows the relationship of the status flags and the condition codes.
Operation
temp ← SRC1 − SignExtend(SRC2);
ModifyStatusFlags; (* Modify status flags in the same manner as the SUB instruction*)
Flags Affected
The CF, OF, SF, ZF, AF, and PF flags are set according to the result.
Protected Mode Exceptions
#GP(0)
|
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
If the DS, ES, FS, or GS register contains a null segment selector.
|
#SS(0)
|
If a memory operand effective address is outside the SS segment limit.
|
#PF(fault-code)
|
If a page fault occurs.
|
#AC(0)
|
If alignment checking is enabled and an unaligned memory reference is made while the current privilege level is 3.
|
Real-Address Mode Exceptions
#GP
|
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
|
#SS
|
If a memory operand effective address is outside the SS segment limit.
|
Virtual-8086 Mode Exceptions
#GP(0)
|
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
|
#SS(0)
|
If a memory operand effective address is outside the SS segment limit.
|
#PF(fault-code)
|
If a page fault occurs.
|
#AC(0)
|
If alignment checking is enabled and an unaligned memory reference is made.
|
3.
SUB—Subtract
Opcode
|
Instruction
|
Description
|
2C ib
|
SUB AL,imm8
|
Subtract imm8 from AL
|
2D iw
|
SUB AX,imm16
|
Subtract imm16 from AX
|
2D id
|
SUB EAX,imm32
|
Subtract imm32 from EAX
|
80 /5 ib
|
SUB r/m8,imm8
|
Subtract imm8 from r/m8
|
81 /5 iw
|
SUB r/m16,imm16
|
Subtract imm16 from r/m16
|
81 /5 id
|
SUB r/m32,imm32
|
Subtract imm32 from r/m32
|
83 /5 ib
|
SUB r/m16,imm8
|
Subtract sign-extended imm8 from r/m16
|
83 /5 ib
|
SUB r/m32,imm8
|
Subtract sign-extended imm8 from r/m32
|
28 /r
|
SUB r/m8,r8
|
Subtract r8 from r/m8
|
29 /r
|
SUB r/m16,r16
|
Subtract r16 from r/m16
|
29 /r
|
SUB r/m32,r32
|
Subtract r32 from r/m32
|
2A /r
|
SUB r8,r/m8
|
Subtract r/m8 from r8
|
2B /r
|
SUB r16,r/m16
|
Subtract r/m16 from r16
|
2B /r
|
SUB r32,r/m32
|
Subtract r/m32 from r32
|
Description
Subtracts the second operand (source operand) from the first operand (destination operand) and stores the result in the destination operand.
The destination operand can be a register or a memory location; the source operand can be an immediate, register, or memory location.
(However, two memory operands cannot be used in one instruction.)
When an immediate value is used as an operand, it is sign-extended to the length of the destination operand format.
The SUB instruction performs integer subtraction.
It evaluates the result for both signed and unsigned integer operands and sets the OF and CF flags to indicate a borrow in the signed or unsigned result, respectively.
The SF flag indicates the sign of the signed result.
This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
Operation
DEST ← DEST – SRC;
Flags Affected
The OF, SF, ZF, AF, PF, and CF flags are set according to the result.
Protected Mode Exceptions
#GP(0)
|
If the destination is located in a nonwritable segment.
|
|
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
If the DS, ES, FS, or GS register contains a null segment selector.
|
#SS(0)
|
If a memory operand effective address is outside the SS segment limit.
|
#PF(fault-code)
|
If a page fault occurs.
|
#AC(0)
|
If alignment checking is enabled and an unaligned memory reference is made while the current privilege level is 3.
|
Real-Address Mode Exceptions
#GP
|
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
|
#SS
|
If a memory operand effective address is outside the SS segment limit.
|
Virtual-8086 Mode Exceptions
#GP(0)
|
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
|
#SS(0)
|
If a memory operand effective address is outside the SS segment limit.
|
#PF(fault-code)
|
If a page fault occurs.
|
#AC(0)
|
If alignment checking is enabled and an unaligned memory reference is made.
|
4.
Jcc—Jump if Condition Is Met
Opcode
|
Instruction
|
Description
|
77 cb
|
JA rel8
|
Jump short if above (CF=0 and ZF=0)
|
73 cb
|
JAE rel8
|
Jump short if above or equal (CF=0)
|
72 cb
|
JB rel8
|
Jump short if below (CF=1)
|
76 cb
|
JBE rel8
|
Jump short if below or equal (CF=1 or ZF=1)
|
72 cb
|
JC rel8
|
Jump short if carry (CF=1)
|
E3 cb
|
JCXZ rel8
|
Jump short if CX register is 0
|
E3 cb
|
JECXZ rel8
|
Jump short if ECX register is 0
|
74 cb
|
JE rel8
|
Jump short if equal (ZF=1)
|
7F cb
|
JG rel8
|
Jump short if greater (ZF=0 and SF=OF)
|
7D cb
|
JGE rel8
|
Jump short if greater or equal (SF=OF)
|
7C cb
|
JL rel8
|
Jump short if less (SF<>OF)
|
7E cb
|
JLE rel8
|
Jump short if less or equal (ZF=1 or SF<>OF)
|
76 cb
|
JNA rel8
|
Jump short if not above (CF=1 or ZF=1)
|
72 cb
|
JNAE rel8
|
Jump short if not above or equal (CF=1)
|
73 cb
|
JNB rel8
|
Jump short if not below (CF=0)
|
77 cb
|
JNBE rel8
|
Jump short if not below or equal (CF=0 and ZF=0)
|
73 cb
|
JNC rel8
|
Jump short if not carry (CF=0)
|
75 cb
|
JNE rel8
|
Jump short if not equal (ZF=0)
|
7E cb
|
JNG rel8
|
Jump short if not greater (ZF=1 or SF<>OF)
|
7C cb
|
JNGE rel8
|
Jump short if not greater or equal (SF<>OF)
|
7D cb
|
JNL rel8
|
Jump short if not less (SF=OF)
|
7F cb
|
JNLE rel8
|
Jump short if not less or equal (ZF=0 and SF=OF)
|
71 cb
|
JNO rel8
|
Jump short if not overflow (OF=0)
|
7B cb
|
JNP rel8
|
Jump short if not parity (PF=0)
|
79 cb
|
JNS rel8
|
Jump short if not sign (SF=0)
|
75 cb
|
JNZ rel8
|
Jump short if not zero (ZF=0)
|
70 cb
|
JO rel8
|
Jump short if overflow (OF=1)
|
7A cb
|
JP rel8
|
Jump short if parity (PF=1)
|
7A cb
|
JPE rel8
|
Jump short if parity even (PF=1)
|
7B cb
|
JPO rel8
|
Jump short if parity odd (PF=0)
|
78 cb
|
JS rel8
|
Jump short if sign (SF=1)
|
74 cb
|
JZ rel8
|
Jump short if zero (ZF = 1)
|
0F 87 cw/cd
|
JA rel16/32
|
Jump near if above (CF=0 and ZF=0)
|
0F 83 cw/cd
|
JAE rel16/32
|
Jump near if above or equal (CF=0)
|
0F 82 cw/cd
|
JB rel16/32
|
Jump near if below (CF=1)
|
0F 86 cw/cd
|
JBE rel16/32
|
Jump near if below or equal (CF=1 or ZF=1)
|
0F 82 cw/cd
|
JC rel16/32
|
Jump near if carry (CF=1)
|
0F 84 cw/cd
|
JE rel16/32
|
Jump near if equal (ZF=1)
|
0F 84 cw/cd
|
JZ rel16/32
|
Jump near if 0 (ZF=1)
|
0F 8F cw/cd
|
JG rel16/32
|
Jump near if greater (ZF=0 and SF=OF)
|
0F 8D cw/cd
|
JGE rel16/32
|
Jump near if greater or equal (SF=OF)
|
0F 8C cw/cd
|
JL rel16/32
|
Jump near if less (SF<>OF)
|
0F 8E cw/cd
|
JLE rel16/32
|
Jump near if less or equal (ZF=1 or SF<>OF)
|
0F 86 cw/cd
|
JNA rel16/32
|
Jump near if not above (CF=1 or ZF=1)
|
0F 82 cw/cd
|
JNAE rel16/32
|
Jump near if not above or equal (CF=1)
|
0F 83 cw/cd
|
JNB rel16/32
|
Jump near if not below (CF=0)
|
0F 87 cw/cd
|
JNBE rel16/32
|
Jump near if not below or equal (CF=0 and ZF=0)
|
0F 83 cw/cd
|
JNC rel16/32
|
Jump near if not carry (CF=0)
|
0F 85 cw/cd
|
JNE rel16/32
|
Jump near if not equal (ZF=0)
|
0F 8E cw/cd
|
JNG rel16/32
|
Jump near if not greater (ZF=1 or SF<>OF)
|
0F 8C cw/cd
|
JNGE rel16/32
|
Jump near if not greater or equal (SF<>OF)
|
0F 8D cw/cd
|
JNL rel16/32
|
Jump near if not less (SF=OF)
|
0F 8F cw/cd
|
JNLE rel16/32
|
Jump near if not less or equal (ZF=0 and SF=OF)
|
0F 81 cw/cd
|
JNO rel16/32
|
Jump near if not overflow (OF=0)
|
0F 8B cw/cd
|
JNP rel16/32
|
Jump near if not parity (PF=0)
|
0F 89 cw/cd
|
JNS rel16/32
|
Jump near if not sign (SF=0)
|
0F 85 cw/cd
|
JNZ rel16/32
|
Jump near if not zero (ZF=0)
|
0F 80 cw/cd
|
JO rel16/32
|
Jump near if overflow (OF=1)
|
0F 8A cw/cd
|
JP rel16/32
|
Jump near if parity (PF=1)
|
0F 8A cw/cd
|
JPE rel16/32
|
Jump near if parity even (PF=1)
|
0F 8B cw/cd
|
JPO rel16/32
|
Jump near if parity odd (PF=0)
|
0F 88 cw/cd
|
JS rel16/32
|
Jump near if sign (SF=1)
|
0F 84 cw/cd
|
JZ rel16/32
|
Jump near if 0 (ZF=1)
|
Description
Checks the state of one or more of the status flags in the EFLAGS register (CF, OF, PF, SF, and ZF) and, if the flags are in the specified state (condition), performs a jump to the target instruction specified by the destination operand.
A condition code (cc) is associated with each instruction to indicate the condition being tested for.
If the condition is not satisfied, the jump is not performed and execution continues with the instruction following the Jcc instruction.
The target instruction is specified with a relative offset (a signed offset relative to the current value of the instruction pointer in the EIP register).
A relative offset (rel8, rel16, or rel32) is generally specified as a label in assembly code, but at the machine code level, it is encoded as a signed, 8-bit or 32-bit immediate value, which is added to the instruction pointer.
Instruction coding is most efficient for offsets of –128 to +127.
If the operand-size attribute is 16, the upper two bytes of the EIP register are cleared to 0s, resulting in a maximum instruction pointer size of 16 bits.
The conditions for each Jcc mnemonic are given in the “Description” column of the table on the preceding page.
The terms “less” and “greater” are used for comparisons of signed integers and the terms “above” and “below” are used for unsigned integers.
Because a particular state of the status flags can sometimes be interpreted in two ways, two mnemonics are defined for some opcodes.
For example, the JA (jump if above) instruction and the JNBE (jump if not below or equal) instruction are alternate mnemonics for the opcode 77H.
The Jcc instruction does not support far jumps (jumps to other code segments).
When the target for the conditional jump is in a different segment, use the opposite condition from the condition being tested for the Jcc instruction, and then access the target with an unconditional far jump (JMP instruction) to the other segment.
For example, the following conditional far jump is
illegal:
JZ FARLABEL;
To accomplish this far jump, use the following two instructions:
JNZ BEYOND;
JMP FARLABEL;
BEYOND:
The
JECXZ and
JCXZ instructions differs from the other Jcc instructions because they do not check the status flags.
Instead they check the contents of the ECX and CX registers, respectively, for 0.
Either the CX or ECX register is chosen according to the address-size attribute.
These instructions are useful at the beginning of a conditional loop that terminates with a conditional loop instruction (such as LOOPNE).
They prevent entering the loop when the ECX or CX register is equal to 0, which would cause the loop to execute 232 or 64K times, respectively, instead of zero times.
All conditional jumps are converted to code fetches of one or two cache lines, regardless of jump address or cacheability.
Operation
IF condition
THEN
EIP <--- EIP + SignExtend(DEST);
IF OperandSize = 16
THEN
EIP <--- EIP AND 0000FFFFH;
FI;
ELSE(*OperandSize = 32*)
IF EIP < CS.Base OR EIP > CS.Limit
#GP
FI;
FI;
?Flags Affected
None.
Protected Mode Exceptions
#GP(0)
|
If the offset being jumped to is beyond the limits of the CS segment.
|
Real-Address Mode Exceptions
#GP
|
If the offset being jumped to is beyond the limits of the CS segment or is outside of the effective address space from 0 to FFFFH. This condition can occur if a 32-bit address size override prefix is used.
|
Virtual-8086 Mode Exceptions
Same exceptions as in Real Address Mode
5.
TEST—Logical Compare
Opcode
|
Instruction
|
Description
|
A8 ib
|
TEST AL,imm8
|
AND imm8 with AL; set SF, ZF, PF according to result
|
A9 iw
|
TEST AX,imm16
|
AND imm16 with AX; set SF, ZF, PF according to result
|
A9 id
|
TEST EAX,imm32
|
AND imm32 with EAX; set SF, ZF, PF according to result
|
F6 /0 ib
|
TEST r/m8,imm8
|
AND imm8 with r/m8; set SF, ZF, PF according to result
|
F7 /0 iw
|
TEST r/m16,imm16
|
AND imm16 with r/m16; set SF, ZF, PF according to result
|
F7 /0 id
|
TEST r/m32,imm32
|
AND imm32 with r/m32; set SF, ZF, PF according to result
|
84 /r
|
TEST r/m8,r8
|
AND r8 with r/m8; set SF, ZF, PF according to result
|
85 /r
|
TEST r/m16,r16
|
AND r16 with r/m16; set SF, ZF, PF according to result
|
85 /r
|
TEST r/m32,r32
|
AND r32 with r/m32; set SF, ZF, PF according to result
|
Description
Computes the bit-wise logical AND of first operand (source 1 operand) and the second operand (source 2 operand) and sets the SF, ZF, and PF status flags according to the result.
The result is then discarded.
Operation
TEMP ← SRC1 AND SRC2;
SF ← MSB(TEMP);
IF TEMP = 0
THEN ZF ← 1;
ELSE ZF ← 0;
FI:
PF ← BitwiseXNOR(TEMP[0:7]);
CF ← 0;
OF ← 0;
(*AF is Undefined*)
Flags Affected
The OF and CF flags are cleared to 0.
The SF, ZF, and PF flags are set according to the result (see the “Operation” section above).
The state of the AF flag is undefined.
Protected Mode Exceptions
|
#GP(0)
|
If a memory operand effective address is outside the CS, DS, ES, FS, o GS segment limit.
If the DS, ES, FS, or GS register contains a null segment selector.
|
|
#SS(0)
|
If a memory operand effective address is outside the SS segment limit.
|
|
#PF(fault-code)
|
If a page fault occurs.
|
#AC(0)
|
If alignment checking is enabled and an unaligned memory reference is made while the current privilege level is 3.
|
Real-Address Mode Exceptions
#GP
|
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
|
#SS
|
If a memory operand effective address is outside the SS segment limit.
|
Virtual-8086 Mode Exceptions
#GP(0)
|
If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
|
#SS(0)
|
If a memory operand effective address is outside the SS segment limit.
|
#PF(fault-code)
|
If a page fault occurs.
|
#AC(0)
|
If alignment checking is enabled and an unaligned memory reference is made.
|
6.
LOOP/LOOPcc—Loop According to ECX Counter
Opcode
|
Instruction
|
Description
|
E2 cb
|
LOOP rel8
|
Decrement count; jump short if count ≠ 0
|
E1 cb
|
LOOPE rel8
|
Decrement count; jump short if count ≠ 0 and ZF=1
|
E1 cb
|
LOOPZ rel8
|
Decrement count; jump short if count ≠ 0 and ZF=1
|
E0 cb
|
LOOPNE rel8
|
Decrement count; jump short if count ≠ 0 and ZF=0
|
E0 cb
|
LOOPNZ rel8
|
Decrement count; jump short if count ≠ 0 and ZF=0
|
Description
Performs a loop operation using the ECX or CX register as a counter.
Each time the LOOP instruction is executed, the count register is decremented, then checked for 0.
If the count is 0, the loop is terminated and program execution continues with the instruction following the LOOP instruction.
If the count is not zero, a near jump is performed to the destination (target) operand, which is presumably the instruction at the beginning of the loop.
If the address-size attribute is 32 bits, the ECX register is used as the count register; otherwise the CX register is used.
The target instruction is specified with a relative offset (a signed offset relative to the current value of the instruction pointer in the EIP register).
This offset is generally specified as a label in assembly code, but at the machine code level, it is encoded as a signed, 8-bit immediate value, which is added to the instruction pointer.
Offsets of –128 to +127 are allowed with this instruction.
Some forms of the loop instruction (LOOPcc) also accept the ZF flag as a condition for terminating the loop before the count reaches zero.
With these forms of the instruction, a condition code (cc) is associated with each instruction to indicate the condition being tested for.
Here, the LOOPcc instruction itself does not affect the state of the ZF flag; the ZF flag is changed by other instructions in the loop.
Operation
IF AddressSize = 32
THEN
Count is ECX;
ELSE (* AddressSize = 16 *)
Count is CX;
FI;
Count ← Count – 1;
IF instruction is not LOOP
THEN
IF (instruction ← LOOPE) OR (instruction ← LOOPZ)
THEN
IF (ZF =1) AND (Count ≠ 0)
THEN BranchCond ← 1;
ELSE BranchCond ← 0;
FI;
FI;
IF (instruction = LOOPNE) OR (instruction = LOOPNZ)
THEN
IF (ZF =0 ) AND (Count ≠ 0)
THEN BranchCond ← 1;
ELSE BranchCond ← 0;
FI;
FI;
ELSE (* instruction = LOOP *)
IF (Count ≠ 0)
THEN BranchCond ← 1;
ELSE BranchCond ← 0;
FI;
FI;
IF BranchCond = 1
THEN
EIP ← EIP + SignExtend(DEST);
IF OperandSize = 16
THEN
EIP ← EIP AND 0000FFFFH;
ELSE (* OperandSize = 32 *)
IF EIP < CS.Base OR EIP > CS.Limit
#GP
FI;
ELSE
Terminate loop and continue program execution at EIP;
FI;
Flags Affected
None.
Protected Mode Exceptions
#GP(0)
|
If the offset being jumped to is beyond the limits of the CS segment.
|
Virtual-8086 Mode Exceptions
#GP
|
If the offset being jumped to is beyond the limits of the CS segment or is outside of the effective address space from 0 to FFFFH. This condition can occur if a 32-bit address size override prefix is used.
|
Virtual-8086 Mode Exceptions
Same exceptions as in Real Address Mode
7.
STATUS FLAGS
The status flags (bits 0, 2, 4, 6, 7, and 11) of the EFLAGS register indicate the results of arithmetic instructions, such as the ADD, SUB, MUL, and DIV instructions.
The functions of the status flags are as follows:
CF (bit 0) Carry flag.
Set if an arithmetic operation generates a carry or a borrow out of the most-significant bit of the result;
cleared otherwise.
This flag indicates an overflow condition for unsigned-integer arithmetic.
It is also used in multiple-precision arithmetic.
PF (bit 2) Parity flag.
Set if the least-significant byte of the result contains an even number of 1 bits;
cleared otherwise.
AF (bit 4) Adjust flag.
Set if an arithmetic operation generates a carry or a borrow out of bit 3 of the result;
cleared otherwise.
This flag is used in binarycoded decimal (BCD) arithmetic.
ZF (bit 6) Zero flag.
Set if the result is zero; cleared otherwise.
SF (bit 7) Sign flag.
Set equal to the most-significant bit of the result, which is the sign bit of a signed integer.
(0 indicates a positive value and 1 indicates a negative value.)
OF (bit 11) Overflow flag.
Set if the integer result is too large a positive number or too small a negative number (excluding the sign-bit) to fit in the destination operand;
cleared otherwise.
This flag indicates an overflow condition for signed-integer (two’s complement) arithmetic.
Of these status flags, only the CF flag can be modified directly, using the STC, CLC, and CMC instructions. Also the bit instructions (BT, BTS, BTR, and BTC) copy a specified bit into the CF flag.
The status flags allow a single arithmetic operation to produce results for three different data types:
unsigned integers,
signed integers, and
BCD integers.
If the result of an arithmetic operation is treated as an unsigned integer, the
CF flag indicates an out-of-range condition (carry or a borrow);
if treated as a signed integer (two’s complement number), the
OF flag indicates a carry or borrow;
and if treated as a BCD digit, the
AF flag indicates a carry or borrow.
The
SF flag indicates the sign of a signed integer.
The
ZF flag indicates either a signed- or an unsignedinteger zero.
When performing multiple-precision arithmetic on integers, the
CF flag is used in conjunction with the add with carry (ADC) and subtract with borrow (SBB) instructions to propagate a carry or borrow from one computation to the next.
The condition instructions
Jcc (jump on condition code cc),
SETcc (byte set on condition code cc),
LOOPcc, and
CMOVcc (conditional move) use one or more of the status flags as condition codes and test them for branch, set-byte, or end-loop conditions.
分支语句伪指令反汇编前后的比较:
源代码如下:
.if
eax && (ebx >= dwX) || !(dwY != ecx) //
第
1
个条件分支的判断
mov esi,1 //
第
1
个条件分支的语句体
.elseif
edx //
第
2
个条件分支的判断
mov esi,2 //
第
2
个条件分支的语句体
.elseif
esi & 1 //
第
3
个条件分支的判断
mov esi,3 //
第
3
个条件分支的语句体
.elseif
ZERO? && CARRY? //
第
4
个条件分支的判断
mov esi,4 //
第
4
个条件分支的语句体
.endif
以上源代码反汇编后得到的汇编指令:
; if eax
第
1
个条件分支的判断的第
1
部分
;
判断
eax
是否为
0
;
;
如果
eax
为
0
,那么目标操作数
eax
的每个位都设置为
0
,
ZF
设置为
1
;
;
如果
eax
不为
0
,那么目标操作数
eax
的每个位都设置为
1
,
ZF
设置为
0
;
: 00401000 0BC0
or eax,eax
;
如果
eax
为
0
(即相等,
ZF==1)
,则短跳转到地址
0040100C
;
由于
eax
和
(ebx >= dwX)
之间是
&&
的逻辑运算,
;
所以如果
eax
为
0
,
eax && (ebx >= dwX)
的结果就肯定为
false
,
;
这样就不用再判断
(ebx >= dwX)
条件,而是直接判断后面的
!(dwY != ecx)
条件
: 00401002 7408
je 0040100C
; (ebx >= dwX)
第
1
个条件分支的判断的第
2
部分
;
执行到这里说明
eax
不为
0
,那么继续判断
(ebx >= dwX)
条件
; cmp ebx,dword ptr [00403000]
指令,就是把
ebx
内的值减去内存
[00403000]
中的
dword
值,
;
对运算的结果临时存放一下,并根据运算结果设置状态标志位
CF, OF, SF, ZF, AF
和
PF
;
如果
ebx
内的值大于等于内存
[00403000]
中的
dword
值,那么运算后
CF==0
;
;
如果
ebx
内的值小于内存
[00403000]
中的
dword
值,那么运算后
CF==1
: 00401004 3B1D00304000
cmp ebx,dword ptr [00403000]
;
执行了
cmp
指令之后,如果
CF==0
表示满足
(ebx >= dwX)
的条件,
;
那么
eax && (ebx >= dwX)
的结果就为
true
,从而
eax && (ebx >= dwX) || !(dwY != ecx)
的结果肯定也为
true
,
;
所以就没有必要再去判断
!(dwY != ecx)
条件,直接跳转到第
1
个条件分支的语句体就行;
: 0040100A 7308
jnb 00401014 ;
如果不低于
(CF==0)
,则短跳转到地址
00401014
; (dwY != ecx)
第
1
个条件分支的判断的第
3
部分
;
执行到这里说明
eax && (ebx >= dwX)
的结果为
false
,
;
那么是否是执行第
1
个条件分支的语句体就看
!(dwY != ecx)
条件的结果
: 0040100C 390D04304000
cmp dword ptr [00403004], ecx
; !(dwY != ecx)
的意思是,
dwY
和
ecx
相等结果为
true
;
dwY
和
ecx
不相等结果为
false
;
;
如果内存
[00403004]
中的
dword
值和
ecx
中的值不相等,即
!(dwY != ecx)
的结果为
false
,
; eax && (ebx >= dwX) || !(dwY != ecx)
的结果为
false
,
;
就不执行第
1
个条件分支的语句体,而是跳转到第
2
个条件分支的判断语句地址;
: 00401012 7507
jne 0040101B
;
eax && (ebx >= dwX) || !(dwY != ecx)
的结果为
true
的情况,
;
就执行第
1
个条件分支的语句体;
: 00401014 BE01000000
mov esi, 00000001 ;
第
1
个条件分支的语句体
: 00401019 EB23
jmp 0040103E ;
第
1
个条件分支处理结束,就无条件跳转到整个条件分支结构的结尾处
; elseif edx
第
2
个条件分支的判断
: 0040101B 0BD2
or edx, edx ;
判断
edx
的值是否为
0
: 0040101D 7407
je 00401026 ;
如果
edx
的值为
0
,就跳转到第
3
个条件分支的判断语句地址
;
如果
edx
的值不为
0
,就执行第
2
个条件分支的语句体
: 0040101F BE02000000
mov esi, 00000002 ;
第
2
个条件分支的语句体
: 00401024 EB18
jmp 0040103E ;
第
2
个条件分支处理结束,就无条件跳转到整个条件分支结构的结尾处
; elseif esi & 1
第
3
个条件分支的判断
; esi
与
1
进行位与操作,根据操作的结果对
SF
、
ZF
和
PF
标志位进行设置;
: 00401026 F7C601000000
test esi, 00000001
;
如果
esi
的最低位为
1
,那么
esi & 1
的结果为
true
,继续执行第
3
个条件分支的语句体;
;
如果
esi
的最低位为
0
,那么
esi & 1
的结果为
false
,直接跳转到第
4
个条件分支的判断的第
1
部分的语句地址;
: 0040102C 7407
je 00401035
: 0040102E BE03000000
mov esi, 00000003 ;
第
3
个条件分支的语句体
: 00401033 EB09
jmp 0040103E ;
第
3
个条件分支处理结束,跳转到整个条件分支结构的结尾处
; ZERO?
第
4
个条件分支的判断的第
1
部分
;
如果
ZF==1
,表示
ZERO?
的结果为
true
,那么继续判断
CARRY?
条件
;
如果
ZF==0
,表示
ZERO?
的结果为
false
,
ZERO? && CARRY?
的结果肯定为
false
,
;
那么无需判断
CARRY?
条件,直接跳转到整个条件分支结构的结尾处
: 00401035 7507
jne 0040103E ;
跳转到整个条件分支结构的结尾处
; CARRY?
第
4
个条件分支的判断的第
2
部分
;
如果
CF==1
,表示
CARRY?
的结果为
true
,
ZERO? && CARRY?
的结果为
true
,那么接着执行第
4
个条件分支的语句体;
;
如果
CF==0
,表示
CARRY?
的结果为
false
,
ZERO? && CARRY?
的结果为
false
,那么直接跳转到整个条件分支结果的结尾处;
: 00401037 7305
jnb 0040103E ;
跳转到整个条件分支结构的结尾处
: 00401039 BE04000000
mov esi, 00000004 ;
第
4
个条件分支的语句体
: 0040103E
... ;0040103E
地址对应整个条件分支结构的结尾
可以看出由.if/.elseif/.else/.endif条件分支伪指令构成的分支结构只能有一个条件被满足。
循环语句伪指令反汇编前后的比较:
源代码如下:
//
第
1
个
while
循环
.while
eax > 1 //
第
1
个
while
循环的判断条件
mov esi,1 //
第
1
个
while
循环的语句体
.break .if ebx
.continue
mov esi,2
.endw
//
第
2
个
repeat
循环
.repeat
mov esi,1 //
第
2
个
repeat
循环的语句体
.break .if !ebx
.continue
mov esi,2
.until eax > 1 //
第
2
个
repeat
循环的判断条件
//
第
3
个
repeat
循环
.repeat
mov esi,1 //
第
3
个
repeat
循环的语句体
.break
.untilcxz //
第
3
个
repeat
循环的判断条件
以上源代码反编译后得到的汇编指令:
; .while
第
1
个
while
循环的语句体开始
; while
循环体的第
1
条语句直接跳转到
while
循环条件的判断语句
(
地址为
00401012);
;
这里体现出
while
循环是先判断循环条件
,
然后再执行循环体语句
;
: 00401000 EB10
jmp 00401012
: 00401002 BE01000000
mov esi,00000001 ; while
循环体的第一条语句
;
判断
ebx
是否为
0,
;
如果
ebx
为
0,
那么就继续执行循环体接下来的语句
,
;
如果
ebx
为非
0,
那么就直接跳转到第
2
个
repeat
循环的开始处
(
地址为
00401017)
: 00401007 0BDB
or ebx,ebx
;
.break .if ebx
: 00401009 750C
jne 00401017
; .continue
;
无条件跳转到
while
循环条件的判断语句
(
地址为
00401012)
: 0040100B EB05
jmp 00401012
;
由于前面是一句
.continue
语句
,
所以这条
mov
语句不会被执行
: 0040100D BE02000000
mov esi,00000002
; .while eax>1
; while
循环条件的判断语句
,
;
如果
eax
的值大于
1,
那么跳转到
while
循环体的第一条语句
(
地址为
00401002)
继续执行循环体
,
;
如果
eax
的值不大于
1,
那么就退出
while
循环
,
继续执行第
2
个
repeat
循环
;
: 00401012 83F801
cmp eax,00000001
: 00401015 77EB
ja 00401002
; .repeat
第
2
个循环开始
; repeat
循环和
while
循环不同
,
是先执行循环体语句
,
然后再判断循环条件
: 00401017 BE01000000
mov esi,00000001 ;
第
2
个
repeat
循环体的第一条语句
; .break .if !ebx
;
判断
ebx
是否为
0,
;
如果
ebx
是
0,
就结束第
2
个
repeat
循环
,
跳转到第
3
个
repeat
循环的第一条语句
(
地址为
0040102C
),
;
如果
ebx
是非
0,
就继续执行第
2
个
repeat
循环的语句体
;
: 0040101C 0BDB
or ebx,ebx
: 0040101E 740C
je 0040102C
; .continue
;
无条件跳转到
repeat
循环条件的判断语句
(
地址为
00401027)
: 00401020 EB05
jmp 00401027
;
由于前面是一句
.continue
语句
,
所以这条
mov
语句不会被执行
: 00401022 BE02000000
mov esi,00000002
; .until eax>1
;
第
2
个
repeat
循环条件的判断语句
,
;
如果
eax
小于且等于
1,
就跳转到第
2
个
repeat
循环体的第一条语句
(
地址为
00401017),
继续执行循环体
,
;
如果
eax
大于
1,
就推出第
2
个
repeat
循环
,
继续执行第
3
个
repeat
循环
;
: 00401027 83F801
cmp eax,00000001
: 0040102A 76EB
jbe 00401017
; .repeat
第
3
个循环开始
: 0040102C BE01000000
mov esi,00000001 ;
第
3
个
repeat
循环体的第一条语句
; .break
;
未带判断条件的
.break
语句
,
无条件跳转出第
3
个
repeat
循环体
;
: 00401031 EB02
jmp 00401035
; .untilcxz
;
如果
ecx
寄存器的值递减到
0,
就退出第
3
个
repeat
循环
,
;
如果
ecx
寄存器的值没有递减到
0,
就跳转到第
3
个
repeat
循环体的第一条语句
(
地址为
0040102C
),
继续执行
.
: 00401033 E2F7
loop 0040102C ;
注意这里是
loop
指令
从上面的代码比较中可以看出:
.break翻译成一个跳转指令跳到循环结束的地方
.continue是一个无条件跳转指令跳到循环开始的地方
.while是先比较条件再执行循环体
.repeat是先执行循环体再比较条件
loop指令具有的优势:可以自动递减ecx的值来控制循环;
.while/.endw和.repeat/.until循环没有使用loop指令的优势,所以他们会在循环体内多设置一条参数递减的指令;
不使用loop指令的好处就是具有更多的灵活性(另外使用条件表达式);
使用.repat/.untilcxz伪指令即可以自动递减ecx的值来控制循环,又具有灵活性。
编译器将会强制使用loop指令来完成循环,循环开始前必须正确设置ecx的值。
既要使用loop指令来构成循环有要使用条件表达式的方法:
在.untilcxz伪指令后加条件测试语句。
但是,这种方法存在下面两种限制:
a) 只能是单个条件表达式,不能用&&或||来构成多项表达式;
b) 即使是单个表达式中,也只能用==或!=操作符,不能用其他比较大小的操作符;
原因:这时编译器的翻译方式是在一个比较指令后使用loopz或loopnz来构成循环,这个指令不能测试其它标志位。
原因:这时编译器的翻译方式是在一个比较指令后使用loopz或loopnz来构成循环,这个指令不能测试其它标志位。
参考资料:
a) 罗云彬的《Windows环境下32位汇编语言程序设计》(第二版)
b) Intel Architecture Software Developer Manual