我如何在AT&T Assembly
中使用&运算符作为条件来执行if语句?
assume x = 0x60
assume y = 0x45
例如:
if(x and y)
//do something
这会是正确的代码吗?
.globl func
func:
push %r10 //r10 = x
push %r11 //r11 = y
movq $0x60, %r10
movq $0x45, %r11
jmp .loop
.loop:
movq %r10, %r12
and $r11, %r12
cmpq $0xFF, %r12
je .if
jmp .done
.if:
//Do something here
jmp .done
.done:
pop %r10 //r10 = x
pop %r11 //r11 = y
ret
答案 0 :(得分:0)
代码审核:
您的代码过于复杂。 (但这对初学者来说是正常的;如果你回顾一下这一次你有更多经验,你会说同样的事情。)
您不需要保存/恢复r10或r11 :允许函数破坏它们。即他们被召唤破坏了。通常你会使用“遗留”寄存器,如eax / rax和edx / rdx(32位操作数大小,因为你的数字很小)来保存代码大小。但您可以担心以后保存REX前缀; r10和r11都没问题。
您不需要任何jmp
指令。 jmp
到下一行是多余的,而无操作:执行会自行落到下一行,是否有标签。
如果条件为false,您只需要一个je
或jne
跳过.if
块。
您的and/cmp
条件对布尔值或按位and
没有意义。为什么只有设置了所有8位才真实?像pcmpeqb
这样的SSE2 SIMD指令产生0或0xFF比较结果,但如果两个输入操作数都不为零,则没有指令产生0xFF
。 (所以你实施的是if ((x&y) == 0xFF)
对于按位if(x & y)
,请使用test %r10,%r11 / jz .done
。对于布尔值,x上的test-and-branch为非零(test %r10,%r10 / jz .done
,然后重复y。
.globl bitwise_and # args: x in RDI, y in RSI
bitwise_and: # x86-64 System V calling convention
test %rdi, %rsi # set flags according to x&y
jz .Lfalse # skip the next block if (x&y) == 0
# if condition was true, fall into the if block
.Lfalse:
ret
或者布尔值
.globl boolean_and # args: x in RDI, y in RSI
boolean_and:
test %rdi, %rdi
jz .Lfalse
test %rsi, %rsi
jz .Lfalse
# if condition was true, fall into the if block
.Lfalse:
ret
遗憾的是,x86没有一种非常好的方法只使用一条分支指令来检查输入是否为零。像C x && y
运算符的短路行为一样单独检查每个输入是编译器经常做的事情。
对于x || y
,情况要好得多:x || y
在x | y
为真的相同情况下为真,因此我们可以执行or %rdi, %rsi
,根据结果。如果OR结果为零,则jz
跳过if
块。