Jack對分支迴圈語句偽指令反彙編前後的比較
標 題: 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
相關文章
- 分支、迴圈語句動態展示
- iOS逆向學習筆記 - 彙編(四) - 迴圈&選擇[cmp 比較指令]iOS筆記
- 【分支流程控制語句、迴圈流程控制語句】的學習
- Matlab的if語句switch語句for迴圈while迴圈語句練習MatlabWhile
- Shell指令碼之for迴圈語句的應用指令碼
- Shell指令碼應用 – for、while迴圈語句指令碼While
- PLSQL Language Referenc-PL/SQL控制語句-迴圈語句-FOR迴圈-FOR迴圈中的索引SQL索引
- 編寫迴圈插入表資料的語句。
- TypeScript 迴圈語句TypeScript
- JavaScript for 迴圈語句JavaScript
- MySQL迴圈語句MySql
- Oracle迴圈語句Oracle
- PLSQL Language Referenc-PL/SQL控制語句-迴圈語句-FOR迴圈SQL
- PLSQL Language Referenc-PL/SQL控制語句-迴圈語句-基本迴圈(EXIT語句)SQL
- JavaScript 流程控制語句詳解:if語句、switch語句、while迴圈、for迴圈等JavaScriptWhile
- x86彙編反編譯到c語言之——(2)if語句編譯C語言
- Python的迴圈語句Python
- PLSQL Language Referenc-PL/SQL控制語句-迴圈語句-WHILE迴圈SQLWhile
- JavaScript跳出for迴圈語句JavaScript
- java 迴圈語句(轉)Java
- C++ 反彙編:關於Switch語句的優化措施C++優化
- Python 迴圈語句的使用Python
- Vue 分支迴圈Vue
- PLSQL Language Referenc-PL/SQL控制語句-迴圈語句-FOR迴圈-下限和上限SQL
- 流程控制、 迴圈語句
- swift控制流——迴圈語句Swift
- 6、迴圈結構語句
- linux 迴圈控制語句Linux
- PL/SQL迴圈控制語句SQL
- Python-條件語句和迴圈語句Python
- [譯] part 9: golang 迴圈語句Golang
- 【Python基礎】for迴圈語句Python
- php中有哪些迴圈控制語句PHP
- MyBatis xml foreach迴圈語句MyBatisXML
- Java簡單迴圈語句案例Java
- c語言中,while(1)語句使用break語句跳出迴圈C語言While
- python04: while迴圈語句 break continue for in 迴圈PythonWhile
- Java語言程式設計—迴圈語句Java程式設計