Assembly 什么是PC相对寻址,如何在MASM中使用它?
我正在学习Jack Crenshaw的编译器教程(如果你看我的个人资料,这就是我所有的问题都是关于lol的),它刚好达到了引入变量的程度。他评论说68k要求所有东西都是“位置独立的”,这意味着它是“PC相对的”。我知道PC是程序计数器,在x86上是EIP。但是他使用了类似于Assembly 什么是PC相对寻址,如何在MASM中使用它?,assembly,x86,masm,68000,addressing,Assembly,X86,Masm,68000,Addressing,我正在学习Jack Crenshaw的编译器教程(如果你看我的个人资料,这就是我所有的问题都是关于lol的),它刚好达到了引入变量的程度。他评论说68k要求所有东西都是“位置独立的”,这意味着它是“PC相对的”。我知道PC是程序计数器,在x86上是EIP。但是他使用了类似于movex(PC),D0的语法,其中X是一个变量名。我在前面读了一点,后面没有提到在.data中声明变量。这是怎么回事?要在x86中实现这一点,我将用什么替换X(PC)呢 老实说,我甚至不确定它是否应该输出工作代码,但到目前为
movex(PC),D0
的语法,其中X是一个变量名。我在前面读了一点,后面没有提到在.data中声明变量。这是怎么回事?要在x86中实现这一点,我将用什么替换X(PC)呢
老实说,我甚至不确定它是否应该输出工作代码,但到目前为止,它已经输出了,我已经向我的编译器添加了代码,添加了适当的头文件等,以及一个批处理文件来组装、链接和运行结果 许多处理器支持PC相对或绝对寻址 但是,在X86机器上存在以下限制:
- 跳转和呼叫始终与PC相关(除非基于寄存器)
- 其他地址总是绝对的(除非基于寄存器)
CALL x
x:
; Now address "x" is on the stack
POP EDI
; Now EDI contains address of "x"
; Now we can do (pseudo-)PC-Relative addressing:
MOV EAX,[EDI+1234]
如果在编译/链接期间内存中的代码地址未知(例如,对于Linux下的动态库(DLL)),因此变量的地址(此处位于地址“x+1234”)未知,则使用此选项。这里简要概述了静态分配的全局变量(这就是这个问题的内容)真的是这样,该怎么办呢 什么是变量 对于机器来说,没有变量这样的东西。它从来没有听说过他们,从来没有关心过他们,只是对他们没有概念。它们只是一种约定,将一致的含义分配给RAM中的特定位置(在虚拟内存的情况下,是地址空间中的一个位置) 实际上,变量放在哪里取决于你自己,但这是合理的。如果要对它进行写入(很可能是这样),它最好位于一个可写位置,这意味着:该变量的地址应该位于一个已分配且可写的内存区域内。.data部分只是这方面的另一个约定。你不必这样称呼它,你甚至不需要一个单独的部分(如果你真的愿意,你可以让你的.text部分可写并在那里分配你的globals),你甚至可以使用操作系统函数,如
VirtualAllocEx
(或等效函数),在固定位置分配内存并使用它(但不要这样做)。这取决于你。但是.data部分是放置它们的方便地方
“分配”变量只是选择一个地址的问题,这样变量就不会与任何其他变量重叠。这并不难,只需按顺序排列它们:在要放置它们的地方的开始处启动一个指针var_ptr
(因此.data部分的VA,或者如果使用链接器,则为0),然后针对每个变量v
:
的位置v
是l
align(变量ptr,四舍五入到2的功率(大小v))
- 将
设置为var\u ptr
l+sizeof(v)
mov eax, dword ptr [variablelabel]
或者,在x64上,可能是这样
mov eax, dword ptr [rel variablelabel]
它将发出一个rip相对地址。如果这样做,就不必关心RIP的当前值或变量的分配位置,汇编程序/链接器将负责处理它。在x64上,使用这样的RIP相对地址很常见,原因如下:
- 它允许.data段位于不是第一个4GB(或2GB)地址空间的某个位置,只要它靠近.text段
- 它比绝对64位地址的指令短
- 只有两条指令甚至采用绝对64位地址,即
和mov-rax[imm64]
mov[imm64],rax
- 你可以免费获得重新安置