本文需要用到的指令
mov A,B ; 将B的值复制到A中
sub A,B ; A-B 且将结果放入A中
neg A ; 对 A 进行求补 ,0-A 并将结果放入A中 ,当运算结果为0时 ,CF位为 0 , 否则都为1
sbb A,B ; A-B-CF 且将结果放入A中
and A,B ; A&B 且将结果放入A
add A,B ; A+B 且将结果放入A
cmp A,B ; A-B 但不保存结果 , 只影响标志位
cmovxx REG1,REG2 ; 满足条件则将 REG2的内容复制到REG1中
setxxx REG ; 满足条件则将REG置为1,否则置为0
xxx 取值
z : 相等
e : 相等 (equ)
l : 小于 - 有符号 (less)
g : 大于 - 有符号 (greadter)
b : 小于 - 无符号 (blow)
a : 大于 - 无符号 (above)
test A,B ; A&B 但不保存结果 , 只会影响标志位
dec A ; A-1 , 且将结果保存到 A 中
情况一 : 表达式二三皆为常量 , 表达式一为等式
示例
int a = argc == 8 ? 2 : 5
int b = argc == 0 ? 4 : 3
在 VC++6.0 中的情况
int a = argc == 8 ? 2 : 5
; 以下为反汇编代码
mov eax,[argc]
sub eax,8
neg eax
sbb eax,eax
and eax,3
add eax,2
int b = argc == 0 ? 4 : 3
; 以下为反汇编代码
mov eax,[argc]
neg eax
sbb eax,eax
and al,0FF
add eax,4
以下为上诉代码分析
以第一段代码为例
mov eax,[argc]
sub eax,8 ; eax = argc == 8 ? 0 : !0
neg eax ; CF = eax == 0 ? 0 : 1
sbb eax,eax ; eax = CF == 0 ? 0 : -1
and eax,3 ; eax = eax == 0 ? 0 : 3
add eax,2 ; eax = eax == 0 ? 2 : 5
第二段代码同理
由此可得出以下代码定式 : arg == A ? B : C
mov reg,[arg]
sub reg,A if A == 0 可省略这一步
neg reg
sbb reg,reg
and reg,C-B
add reg,B
以下为 VS2022中的情况
int a = argc == 8 ? 2 : 5
; 以下为反汇编代码
mov eax,[argc]
cmp eax,8
mov ecx,2
mov eax,5
cmovz eax,ecx
int b = argc == 0 ? 4 : 3
; 以下为反汇编代码
mov eax,[argc]
test eax,eax
mov ecx,4
mov eax,3
cmovz eax,ecx
以下为上诉代码分析
以第一段代码为例
mov eax,[argc]
cmp eax,8 ; ZF ? eax == 8 ? 1 : 0
mov ecx,2
mov eax,5
cmovz eax,ecx ; eax = ZF == 1 ? 2 : 5
第二段代码同理(只是将cmp eax,0 改成了 test eax,eax)
由此可得出以下代码定式 : arg == A ? B : C
mov reg1,[arg]
cmp reg1,A
mov reg2,B
mov reg1,C
cmovz reg1,reg2
情况二 : 表达式二三皆为常量 , 表达式一为不等式
示例
int a = argc >= 8 ? 20 : 15;
int b = argc <= 0 ? 2 : 4;
在 VC++6.0 中的情况
int a = argc >= 8 ? 20 : 15;
;以下为反汇编代码
mov eax,[argc]
xor ecx,ecx
cmp eax,8
setl cl ;这里有可能会是 setge , 这里指令不同会略微影响下面指令中的数值
dec ecx
and ecx,5
add ecx,15
int b = argc <= 0 ? 2 : 4;
;以下为反汇编代码
mov eax,[argc]
xor ecx,ecx
cmp eax,0
setg cl ;这里有可能会是 setle , 这里指令不同会略微影响下面指令中的数值
dec ecx
and ecx,-2
add ecx,4
以下为上诉代码分析
以第一段代码为例
mov eax,[argc]
xor ecx,ecx
cmp eax,8
setl cl ; cl = eax < 8 ? 1 : 0
dec ecx ; ecx = eax < 8 ? 0 : -1
and ecx,5 ; ecx = eax < 8 ? 0 : 5
add ecx,15 ; ecx = eax < 8 ? 15 : 20
第二段代码同理
由此可得出以下代码定式 : arg >= A ? B : C
mov REG1,[arg]
xor REG2,REG2
cmp REG1,A
setl REG2
dec REG2
and REG2,B-C
add REG2,C
在 VS2022 中的情况
int a = argc >= 8 ? 20 : 15;
;以下为反汇编代码
mov eax,[argc]
cmp eax,8
mov eax,20
mov ecx,15
cmovl eax,ecx
int b = argc <= 0 ? 2 : 4;
;以下为反汇编代码
cmp eax,0
mov eax,2
mov ecx,4
cmovg eax,ecx
以下为上诉代码分析
以第一段代码为例
mov eax,[argc]
cmp eax,8
mov eax,20
mov ecx,15
cmovl eax,ecx ; eax = eax < 8 ? 15 : 20
第二段代码同理
由此可得出以下代码定式 : arg >= A ? B : C
mov REG1,[arg]
cmp REG1,A
mov REG1,B
mov REG2,C
cmovl REG1,REG2
情况三 : 表达式二三为变量 , 表达式一为不等式
示例
int a = argc >= 8 ? argc/3 : argc*3
在 VC++6.0 中的情况
int a = argc >= 8 ? argc/3 : argc*3
; 以下为反汇编代码
mov eax,[argc]
cmp eax, 8
jl ELSE_NODE
argc/3 反汇编代码
jmp END_IF
ELSE_NODE:
argc*3 反汇编代码
END_IF
以上代码没什么好分析的 , 就是编译成了 if-else 的结构
在 VS2022 中的情况 (分情况 , 有时会成if-else结构,有时会成以下结构)
int a = argc >= 8 ? argc/3 : argc*3
; 以下为反汇编代码
mov edx,[argc]
argc/3 的反汇编代码
mov eax,argc/3
argc*3 的反汇编代码
mov ecx,argc*3
cmp edx,8
cmovl eax,ecx
以上代码与前两种情况一致 , 无本质区别