【发布时间】:2019-02-18 11:07:11
【问题描述】:
考虑 x64 英特尔程序集中的以下变量引用,其中变量 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]?马斯姆?如果是这样,它可能会使用正确的偏移量使rip + _a指向_a(即它不会使用_a的地址)。在 NASM 中,您使用mov eax, DWORD [REL _a](或者将其设置为默认值)。在编写程序集时,RIP 相关的东西用于“计算相对于 RIP 的地址”而不是“将这个特定的偏移量添加到 RIP”中,因为您几乎永远不知道您的代码将在哪里。 -
@MargaretBloom - 感谢您的回复。请参阅我更新的源代码问题。确实,我猜地址是相对于
rip寄存器的;但是,语法并没有反映出那么好,不是吗?所以,你说的是加载器在运行时将[rip + _a]替换为a的绝对地址;还是将_a替换为a(可能为负)w.r.t 相对于指令地址(mov rax, dword ptr [rip + _a])的相对偏移量? -
编辑后:这只是反汇编符号。它承载了使用 RIP 相对寻址和
_a是最终目标的事实。检查操作码,你会看到。这确实是一种误导性的符号。 -
@MargaretBloom - 非常感谢。
标签: assembly x86-64 gnu-assembler addressing-mode relative-addressing