//a.c
extern int shared;
int main(){
int a=100;
swap(&a, &shared);
}
//b.c
int shared=1;
void swap(int* a, int* b){
*a ^= *b ^= *a ^= *b;
}
我使用以下命令编译两个文件:
gcc -c -fno-stack-protector a.c b.c
然后,我使用 objdump -d a.o
命令来检查 a.o 的反汇编代码。
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: c7 45 fc 64 00 00 00 movl $0x64,-0x4(%rbp)
f: 48 8d 45 fc lea -0x4(%rbp),%rax
13: be 00 00 00 00 mov $0x0,%esi
18: 48 89 c7 mov %rax,%rdi
1b: b8 00 00 00 00 mov $0x0,%eax
20: e8 00 00 00 00 callq 25 <main+0x25>
25: b8 00 00 00 00 mov $0x0,%eax
2a: c9 leaveq
2b: c3 retq
由于我的工作环境是Ubuntu 16.04 x86-64,我发现很难理解参数传递的顺序。
在我看来,这里的默认调用约定是fastcall
,因此参数是从右到左传递的。
我知道根据x86-64 System V ABI手册,rdi
和rsi
用于传递前两个参数
然而,根据反汇编代码,rdi
负责处理位于左侧的var a
,也就是第二个参数。
有人能帮我指出我的错误吗?
进行编译。我不知道你为什么要问,但这是完全正常的
-O0未优化的编译器输出,并且在任何x86-64 gcc版本上基本相同,除了使用
--enable-default-pie构建的gcc将使用
lea shared(%rip), %rsi`。(显然不适用于Ubuntu 16.04。) - Peter Cordes-std=c11
(而不是gnu11
)。https://gcc.gnu.org/onlinedocs/gcc/PowerPC-SPE-Options.html#index-mno-prototype说PowerPC gcc有一个-mprototype
选项,可以承诺对可变参数函数的调用进行适当的原型化,因此它可以避免在未原型化的调用之前执行PPC等效操作(在CR中清除/设置位)。没有提到仅限于C89。 - Peter Cordes