以下是做什么的?
testq %rdx, %rdx
cmovg %rcx, %rax
我知道 testq 是按位和两个寄存器之间的,但它如何与标志一起使用?
这将在 c 中转化为什么?
例如如果 %rdx
将保存值 0x01
,那么我们将有 0x01
& 0x01
= 0x01
,这将设置
ZF = 0, SF = 0, OF = 0.
对于我能找到的 cmovg 执行如果
˜(SF ˆ OF) & ˜ZF
这将解析为
˜(0 ˆ 0) & ˜0 = ˜(0) & ˜0 = 1 & 1 = 1.
这是否意味着将执行 cmovg 并且相应的 c 代码将针对 d = %rdx
、a = rax
和 c = rcx
:
if(d > 0){
a = c;
}
或者有人可以换句话解释一下吗?
此外,我一直在尝试将此程序集转换为相应的 C 代码。目前我得到的结果就像 testq %rdx, %rdx with jne .L4 上的无限 while 循环。附上上述内容。任何人都知道正确的解决方案是什么?我目前的解决方案是这样的:
p:
movq (%rdi), %rdx
testq %rdx, %rdx
je .L5
movl $0, %eax
.L4:
leaq (%rax,%rdx), %rcx
testq %rdx, %rdx
cmovg %rcx, %rax
addq $8, %rdi
movq (%rdi), %rdx
testq %rdx, %rdx
jne .L4
ret
.L5:
movl $0, %eax
ret
解决方案(错误):
#include<stdlib.h>
#include <stdio.h>
int func(int *rdi){
int rdx = *rdi;
if(rdx == 0){
int rax = 0;
return rax;
}
int rax = 0;
do {
int rcx = rax + rdx;
if(rdx > 0){
rax = rcx;
}
rdi += 8;
rdx = *rdi;
} while(rdx != 0);
return rax;
}
int main(int argc, char const *argv[]) {
int var = 20;
int *ip;
ip = &var;
func(ip);
}
最佳答案
(转自评论,回复原问题)
if(d > 0){ a = c; }
是的,这是正确的。下面我将尝试展示如何快速“解码”这个模式,而不必一直计算标志寄存器值。
Notice: Intel syntax ahead, as it's way clearer for the operands order in comparisons; AT&T is similar but with the operands reversed (and more strange characters spread around).
“数字比较”条件代码最好在“经典”序列的上下文中理解
cmp a, b
jCC label
CC
(条件代码)此处的部分指的是您在 >
之间进行比较的“运算符”(如 <
、==
、a
)和 b
;所以:
-
jg
→ "j如果a
g大于b
则跳转"; -
jl
→ "j如果a
小于b
l "; -
je
→ "j如果a
e等于b
"; -
jne
→ "j如果a
n不e等于b
"; -
ja
→ "j如果a
是 boveb
"; -
jb
→ "j如果a
是b低于b
则跳转"; - ...所有“e”变体(
jbe
、jae
、...)
(上/下对与大/小对的不同之处在于a
/b
用于无符号值之间的比较,g
/l
用于有符号值;此外,还有a lot of synonyms ,特别是 je
是 jz
AKA“如果为零则跳转”的同义词,jne
对于 jnz
又称为“如果不为零则跳转”;反汇编程序可能会产生 jz
或 je
,它们是一样的)
现在,进入你的案例:
-
test reg,reg
完全等同于cmp reg,0
( apart from the status of AF ,这是无关紧要的);这很容易理解:-
test
执行and
在操作数之间并根据结果设置标志;所以,test reg,reg
只需根据reg
设置标志(and
对一个数字本身进行 nop); -
cmp b,a
计算b-a
并根据结果设置标志;鉴于b-0 == b
,cmp b,0
只需根据b
设置标志, 与test b,b
完全一样.
-
cmovg
是cmovCC
的一个实例指令,条件代码g
,即“如果 greater 则移动”。
那么,你的
test rdx,rdx
cmovg rax,rcx
相当于
cmp rdx,0
cmovg rax,rcx
它清楚地读作“将 rdx 与零进行比较,如果它更大,则在 rax 中移动 rcx”。
关于c - 汇编testq和cmovg指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46570431/