我有一个用汇编编写的函数foo,并在
Linux(Ubuntu)64位上用yasm和GCC编译.它只是使用puts()向stdout输出一条消息,它的外观如下:
bits 64
extern puts
global foo
section .data
message:
db 'foo() called', 0
section .text
foo:
push rbp
mov rbp, rsp
lea rdi, [rel message]
call puts
pop rbp
ret
它由GCC编译的C程序调用:
extern void foo();
int main() {
foo();
return 0;
}
构建命令:
yasm -f elf64 foo_64_unix.asm
gcc -c foo_main.c -o foo_main.o
gcc foo_64_unix.o foo_main.o -o foo
./foo
这是问题所在:
运行程序时,它会打印一条错误消息,并在调用puts期间立即发生段错误:
./foo: Symbol `puts' causes overflow in R_X86_64_PC32 relocation
Segmentation fault
用objdump反汇编后,我看到调用的地址错误:
0000000000000660 :
660: 90 nop
661: 55 push %rbp
662: 48 89 e5 mov %rsp,%rbp
665: 48 8d 3d a4 09 20 00 lea 0x2009a4(%rip),%rdi
66c: e8 00 00 00 00 callq 671
671: 5d pop %rbp
672: c3 retq
(671是下一条指令的地址,不是put的地址)
但是,如果我在C中重写相同的代码,则调用方式会有所不同:
645: e8 c6 fe ff ff callq 510
即它引用了PLT的投注.
有可能告诉yasm生成类似的代码吗?