如果在AT& T汇编中带有和运算符条件的语句

时间:2018-05-26 05:41:11

标签: if-statement assembly conditional-statements operator-keyword

我如何在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

1 个答案:

答案 0 :(得分:0)

代码审核:

您的代码过于复杂。 (但这对初学者来说是正常的;如果你回顾一下这一次你有更多经验,你会说同样的事情。)

您不需要保存/恢复r10或r11 :允许函数破坏它们。即他们被召唤破坏了。通常你会使用“遗留”寄存器,如eax / rax和edx / rdx(32位操作数大小,因为你的数字很小)来保存代码大小。但您可以担心以后保存REX前缀; r10和r11都没问题。

您不需要任何jmp指令。 jmp到下一行是多余的,而无操作:执行会自行落到下一行,是否有标签。

如果条件为false,您只需要一个jejne跳过.if块。

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 || yx | y为真的相同情况下为真,因此我们可以执行or %rdi, %rsi,根据结果。如果OR结果为零,则jz跳过if块。