您的位置:首页 > 其它

Jack对分支循环语句伪指令反汇编前后的比较

2007-04-05 15:28 393 查看
标 题: Jack对分支循环语句伪指令反汇编前后的比较
作 者: Jack Yang
时 间: 2007-04-05
链 接: http://blog.csdn.net/magus_yang/archive/2007/04/05/1552980.aspx

知识准备:
1. OR—Logical Inclusive OR
[align=center]Opcode[/align]
[align=center]Instruction[/align]
[align=center]Description[/align]
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
[align=center]Opcode[/align]
[align=center]Instruction[/align]
[align=center]Description[/align]
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
[align=center]Opcode[/align]
[align=center]Instruction[/align]
[align=center]Description[/align]
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
[align=center]Opcode[/align]
[align=center]Instruction[/align]
[align=center]Description[/align]
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
[align=center]Opcode[/align]
[align=center]Instruction[/align]
[align=center]Description[/align]
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
[align=left] [/align]
[align=center]Opcode[/align]
[align=center]Instruction[/align]
[align=center]Description[/align]
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来构成循环,这个指令不能测试其它标志位。

参考资料:
a) 罗云彬的《Windows环境下32位汇编语言程序设计》(第二版)
b) Intel Architecture Software Developer Manual
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: