我正在与NASM建立共享库.在该库中的某些函数中,我需要在C中称为静态变量的东西.基本上,我认为它在.data节中有一些空间:
SECTION .data
last_tok: dq 0 ; Define a QWORD
当我尝试在函数中访问last_tok时,就会出现问题.
我读了NASM Manual: 8.2 Writing Linux/ELF Shared Libraries,它解释了问题并给出了解决方案.
SECTION .data
last_tok: dq 0 ; Define a QWORD
SECTION .text
EXTERN _GLOBAL_OFFSET_TABLE_
GLOBAL strtok:function
strtok:
enter 0, 0
push rbx
call .get_GOT
.get_GOT:
pop rbx
add rbx, _GLOBAL_OFFSET_TABLE_ + $$- .get_GOT wrt ..gotpc
mov [rbx + last_tok wrt ..gotoff], rdi ; Store the contents of RDI at last_tok
mov rbx, [rbp - 8]
leave
ret
它可能与ELF32一起使用,但与ELF64一起出现以下错误:
nasm -f elf64 -o strtok.o strtok.s
strtok:15: error: ELF64 requires ..gotoff references to be qword
<builtin>: recipe for target 'strtok.o' failed
make: *** [strtok.o] Error 1
我究竟做错了什么?
解决方法:
有效地址格式仅允许32位位移,并将其符号扩展为64位.根据错误消息,您需要完整的64位.您可以通过寄存器添加它,例如:
mov rax, last_tok wrt ..gotoff
mov [rbx + rax], rdi
另外,调用.get_GOT是32位解决方案,在64位模式下,您可以在其中使用rip相对寻址.虽然以上可能会编译,但是我不确定它是否会工作.幸运的是,简单的解决方案是使用提及的rip相对地址来访问变量,从而:
SECTION .data
GLOBAL last_tok
last_tok: dq 0 ; Define a QWORD
SECTION .text
GLOBAL strtok:function
strtok:
mov [rel last_tok wrt ..gotpc], rdi ; Store the contents of RDI at last_tok
ret
请注意,对于私有(静态)变量,您可以只使用[rel last_tok]而不用完全搞定get方法.