考虑以下x64 Intel汇编中的变量引用,其中变量a
在.data
部分声明:
mov eax, dword ptr [rip + _a]
我不理解这个变量引用是如何工作的。因为 a
是指向变量运行时地址的符号(带有重定位),那么 [rip + _a]
如何解引用正确的 a
内存位置呢?实际上,rip
保存当前指令的地址,它是一个大正整数,所以加法会得到一个错误的 a
地址。
相反,如果我使用 x86 语法(非常直观):
mov eax, dword ptr [_a]
我遇到了以下错误:在64位模式下不支持32位绝对寻址。
有什么解释吗?
1 int a = 5;
2
3 int main() {
4 int b = a;
5 return b;
6 }
编译:gcc -S -masm=intel abs_ref.c -o abs_ref
:
1 .section __TEXT,__text,regular,pure_instructions
2 .build_version macos, 10, 14
3 .intel_syntax noprefix
4 .globl _main ## -- Begin function main
5 .p2align 4, 0x90
6 _main: ## @main
7 .cfi_startproc
8 ## %bb.0:
9 push rbp
10 .cfi_def_cfa_offset 16
11 .cfi_offset rbp, -16
12 mov rbp, rsp
13 .cfi_def_cfa_register rbp
14 mov dword ptr [rbp - 4], 0
15 mov eax, dword ptr [rip + _a]
16 mov dword ptr [rbp - 8], eax
17 mov eax, dword ptr [rbp - 8]
18 pop rbp
19 ret
20 .cfi_endproc
21 ## -- End function
22 .section __DATA,__data
23 .globl _a ## @a
24 .p2align 2
25 _a:
26 .long 5 ## 0x5
27
28
29 .subsections_via_symbols
mov eax, dword ptr [rip + _a]
?MASM?如果是的话,它可能会使用正确的偏移量使rip + _a
指向_a
(即它不会使用_a
的地址)。在NASM中,您可以使用mov eax,DWORD [REL _a]
(或将其设置为默认值)。在编写汇编代码时,RIP相对位置用于“相对于RIP计算此地址”,而不是“将此特定偏移量添加到RIP”,因为您几乎永远不知道您的代码将在何处。 - Margaret Bloomrip
寄存器的;但是,语法并没有很好地反映出来,不是吗?所以,您的意思是加载程序会在运行时用a
的绝对地址替换[rip + _a]
;还是_a
会被替换为指令地址(mov rax, dword ptr [rip + _a]
)与a
的相对偏移量(可能是负数)? - Shuzheng_a
是最终目标。检查操作码即可看到。这的确是一种误导性的表示法。 - Margaret Bloom