Cha*_*son 4 c assembly x86-64 calling-convention
我调用 Clang 12.0.0 来-Os -march=haswell编译以下 C 程序:
int bar(int);
int foo(int x) {
const int b = bar(x);
if (x || b) {
return 123;
}
return 456;
}
Run Code Online (Sandbox Code Playgroud)
生成以下程序集:
foo: # @foo
push rbx
mov ebx, edi
call bar
or eax, ebx
mov ecx, 456
mov eax, 123
cmove eax, ecx
pop rbx
ret
Run Code Online (Sandbox Code Playgroud)
https://gcc.godbolt.org/z/WsGoM56Ez
据我了解,foo 的调用者在 RAX/EAX 中设置了 x。然后 foo 调用 bar,这不需要修改 RAX/EAX,因为 x 是作为未修改的输入传递的。
该or eax, ebx指令似乎是将输入 x 与 bar 的结果进行比较。该结果如何最终进入 EBX?有何目的mov ebx,edi?
恐怕你误会了:
x在调用bar.int只使用低半部分)您可以通过编译类似的函数来验证基础知识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
Run Code Online (Sandbox Code Playgroud)
编译器进行优化x || b,(x | b) != 0允许生成无分支代码。
请注意,mov与大多数整数 ALU 指令不同,它不会修改 FLAGS。
| 归档时间: |
|
| 查看次数: |
1552 次 |
| 最近记录: |