Jack對分支迴圈語句偽指令反彙編前後的比較

magus_yang發表於2020-04-04
標 題: 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
; 如果eax0,那麼目標運算元eax的每個位都設定為0ZF設定為1
; 如果eax不為0,那麼目標運算元eax的每個位都設定為1ZF設定為0
: 00401000 0BC0                  or eax,eax             
; 如果eax0(即相等,ZF==1),則短跳轉到地址0040100C
; 由於eax(ebx >= dwX)之間是&&的邏輯運算,
; 所以如果eax0eax && (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)的意思是,dwYecx相等結果為truedwYecx不相等結果為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個條件分支的判斷
; esi1進行位與操作,根據操作的結果對SFZFPF標誌位進行設定;
: 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?的結果為falseZERO? && CARRY?的結果肯定為false
; 那麼無需判斷CARRY?條件,直接跳轉到整個條件分支結構的結尾處
: 00401035 7507                  jne 0040103E         ;跳轉到整個條件分支結構的結尾處
 
;             CARRY?                4個條件分支的判斷的第2部分
; 如果CF==1,表示CARRY?的結果為trueZERO? && CARRY?的結果為true,那麼接著執行第4個條件分支的語句體;
; 如果CF==0,表示CARRY?的結果為falseZERO? && CARRY?的結果為false,那麼直接跳轉到整個條件分支結果的結尾處;
: 00401037 7305                  jnb 0040103E         ;跳轉到整個條件分支結構的結尾處
: 00401039 BE04000000       mov esi, 00000004        ;4個條件分支的語句體
 
: 0040103E                         ...                         ;0040103E地址對應整個條件分支結構的結尾
 
可以看出由.if/.elseif/.else/.endif條件分支偽指令構成的分支結構只能有一個條件被滿足。
 
 
 
迴圈語句偽指令反彙編前後的比較:
原始碼如下:
       // 1while迴圈
.while      eax > 1                  // 1while迴圈的判斷條件
                     mov esi,1              // 1while迴圈的語句體
                     .break .if ebx
                     .continue
                     mov esi,2
       .endw
       // 2repeat迴圈
       .repeat
                     mov esi,1              // 2repeat迴圈的語句體
                     .break .if !ebx
                     .continue
                     mov esi,2
       .until eax > 1                        // 2repeat迴圈的判斷條件
       // 3repeat迴圈
       .repeat
              mov esi,1                     // 3repeat迴圈的語句體
              .break
       .untilcxz                              // 3repeat迴圈的判斷條件
 
以上原始碼反編譯後得到的彙編指令:
;             .while                    1while迴圈的語句體開始
; while迴圈體的第1條語句直接跳轉到while迴圈條件的判斷語句(地址為00401012);
; 這裡體現出while迴圈是先判斷迴圈條件,然後再執行迴圈體語句;
: 00401000 EB10                  jmp 00401012
: 00401002 BE01000000       mov esi,00000001         ; while迴圈體的第一條語句
; 判斷ebx是否為0,
; 如果ebx0,那麼就繼續執行迴圈體接下來的語句,
; 如果ebx為非0,那麼就直接跳轉到第2repeat迴圈的開始處(地址為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迴圈,繼續執行第2repeat迴圈;
: 00401012 83F801               cmp eax,00000001
: 00401015 77EB                  ja 00401002
 
;             .repeat 2個迴圈開始
; repeat迴圈和while迴圈不同,是先執行迴圈體語句,然後再判斷迴圈條件
: 00401017 BE01000000       mov esi,00000001         ; 2repeat迴圈體的第一條語句
;             .break .if !ebx
; 判斷ebx是否為0,
; 如果ebx0,就結束第2repeat迴圈,跳轉到第3repeat迴圈的第一條語句(地址為0040102C),
; 如果ebx是非0,就繼續執行第2repeat迴圈的語句體;
: 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
; 2repeat迴圈條件的判斷語句,
; 如果eax小於且等於1,就跳轉到第2repeat迴圈體的第一條語句(地址為00401017),繼續執行迴圈體,
; 如果eax大於1,就推出第2repeat迴圈,繼續執行第3repeat迴圈;
: 00401027 83F801               cmp eax,00000001
: 0040102A 76EB                  jbe 00401017
 
;             .repeat 3個迴圈開始
: 0040102C BE01000000       mov esi,00000001         ; 3repeat迴圈體的第一條語句
;             .break
; 未帶判斷條件的.break語句,無條件跳轉出第3repeat迴圈體;
: 00401031 EB02                  jmp 00401035
;             .untilcxz
; 如果ecx暫存器的值遞減到0,就退出第3repeat迴圈,
; 如果ecx暫存器的值沒有遞減到0,就跳轉到第3repeat迴圈體的第一條語句(地址為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

相關文章