如何在 x86 中编写 C“&&”运算符?例如:
int a = ...
int b = ...
int c = a && b;
x86 中最后一行的等价物是什么?
编辑:我想在没有任何跳跃的情况下完成上述操作。
编辑:g++ 生成这个,但我不明白:
testl %edi, %edi
setne %dl
xorl %eax, %eax
testl %esi, %esi
setne %al
andl %edx, %eax
最佳答案
下面是 GCC 在 -O3
中的实现方式。
movl 8(%esp), %edx ;; load argument into edx
xorl %eax, %eax ;; eax = 0
movl 4(%esp), %ecx ;; load other argument into ecx
testl %edx, %edx ;; Is EDX nonzero?
setne %al ;; al = 1 if Z = 0
xorl %edx, %edx ;; EDX = 0
testl %ecx, %ecx ;; Is ECX nonzero?
setne %dl ;; dc = 1 if Z = 0
andl %edx, %eax ;; edx &= eax
注意这段代码并没有短路;这是因为在这种情况下,GCC 可以证明第二个参数没有副作用。如果第二个参数有副作用,则必须使用跳转来实现它。例如:
int test(int *a, int *b) {
return (*a)++ && (*b)++;
}
变成:
test:
pushl %ebx ;; save ebx
movl 8(%esp), %eax ;; load a into eax
movl 12(%esp), %ecx ;; load b in to ecx
movl (%eax), %edx ;; *a -> edx
leal 1(%edx), %ebx ;; ebx = edx + 1
movl %ebx, (%eax) ;; *a <- ebx
xorl %eax, %eax ;; eax = 0
testl %edx, %edx ;; if the old value of *a was 0...
je .L2 ;; jump to the end
movl (%ecx), %eax ;; *a -> eax
testl %eax, %eax ;; does *a = 0?
leal 1(%eax), %edx ;; edx = *a + 1 (does not set flags!)
setne %al ;; al = 1 if Z (ie, if a = 0 at the testl above)
movl %edx, (%ecx) ;; save edx to *a (increment *a)
movzbl %al, %eax ;; zero-extend al to eax
.L2:
popl %ebx ;; restore ebx
ret ;; return
关于c - 如何在 x86 中编写 C "&&"运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6721041/