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来构成循环,这个指令不能测试其它标志位。
 
 
参考资料:
a)         罗云彬的《Windows环境下32位汇编语言程序设计》(第二版)
b)        Intel Architecture Software Developer Manual
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值