【问题标题】:x64 argument and return value calling conventionx64 参数和返回值调用约定
【发布时间】:2021-08-01 07:15:47
【问题描述】:

我用-Os -march=haswell 调用Clang 12.0.0 来编译以下C 程序:

int bar(int);

int foo(int x) {
  const int b = bar(x);
  if (x || b) {
      return 123;
  }
  return 456;
}

生成以下程序集:

foo:                                    # @foo
        push    rbx
        mov     ebx, edi
        call    bar
        or      eax, ebx
        mov     ecx, 456
        mov     eax, 123
        cmove   eax, ecx
        pop     rbx
        ret

https://gcc.godbolt.org/z/WsGoM56Ez

据我了解,foo 的调用者在 RAX/EAX 中设置了 x。 foo 然后调用 bar,这不需要修改 RAX/EAX,因为 x 作为未修改的输入传递。

or eax, ebx 指令似乎将输入 x 与 bar 的结果进行比较。这个结果如何在 EBX 中结束? mov ebx,edi 的作用是什么?

【问题讨论】:

标签: c assembly x86-64 calling-convention


【解决方案1】:

恐怕你弄错了:

您可以通过编译像 int foo(int x){return x;} 这样的函数来验证基础知识 - 您只会看到 mov eax, edi

这是一个注释版本:

foo:                                    # @foo
        push    rbx           # save register rbx
        mov     ebx, edi      # save argument `x` in ebx
        call    bar           # a = bar()  (in eax)
        or      eax, ebx      # compute `x | a`, setting FLAGS
        mov     ecx, 456      # prepare 456 for conditional move
        mov     eax, 123      # eax = 123
        cmove   eax, ecx      # if `(x | a) == 0` set eax to 456
        pop     rbx           # restore register rbx
        ret                   # return value is in eax

编译器将x || b 优化为(x | b) != 0,从而允许无分支代码生成。

请注意,mov 不会修改 FLAGS,这与大多数整数 ALU 指令不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-29
    • 2021-06-25
    相关资源
    最近更新 更多