Assembly x86指令的含义是什么;打电话给德沃德ptr ds:[00923030h]";?
下面的x86汇编指令是做什么的Assembly x86指令的含义是什么;打电话给德沃德ptr ds:[00923030h]";?,assembly,x86,addressing-mode,Assembly,X86,Addressing Mode,下面的x86汇编指令是做什么的 call dword ptr ds:[00923030h] 我怀疑这是一个间接呼叫,但它究竟是如何计算呼叫地址的?[EDIT]Updated 每当您看到一个内存操作数看起来像ds:0x00923030,这就是段相对寻址模式。tp引用的实际地址位于相对于ds段寄存器基址的线性地址0x00923030处 x86体系结构中的内存分割有点令人困惑,我认为它解释得很好 基本上,x86有许多特殊的段寄存器:cs(代码段)、ds(数据段)、es、fs、gs和ss(堆栈段)。每
call dword ptr ds:[00923030h]
我怀疑这是一个间接呼叫,但它究竟是如何计算呼叫地址的?[EDIT]Updated 每当您看到一个内存操作数看起来像
ds:0x00923030
,这就是段相对寻址模式。tp引用的实际地址位于相对于ds
段寄存器基址的线性地址0x00923030处
x86体系结构中的内存分割有点令人困惑,我认为它解释得很好
基本上,x86有许多特殊的段寄存器:cs
(代码段)、ds
(数据段)、es
、fs
、gs
和ss
(堆栈段)。每个内存访问都与某个段寄存器相关联。通常,您不指定段寄存器,并且根据内存的访问方式,使用默认段寄存器。例如,cs
寄存器用于读取指令
每个段寄存器都有一定的基址和限制。基址确定线性地址0x00000000对应的物理地址,限制确定该段允许的最大线性地址。例如,如果基址为0x00040000,限制为0x0000FFFF,则唯一有效的线性地址为0x00000000到0x0000FFFF,相应的物理地址为0x00040000到0x0004FFFF
因此,被调用的子例程所在的物理地址由存储在ds
段寄存器中的基址加上0x00923030给出。但我们还没有完成——指令中有单词ptr
。这增加了额外的间接寻址级别,因此子例程的实际目标是存储在位置ds:0x00923030
处的地址
在AT&T语法中(GNU汇编程序接受),指令的编写方式如下:
lcall *ds:0x00923030
有关指令作用的详细信息,请参阅。该指令的这个特殊变体是
“CALL r/m16”
(在寄存器附近调用间接/内存间接)。IIRC,它获取DS寄存器的值(并将其左移4位),加上给定的立即数,从产生的内存位置获取dword值,该位置成为要调用的地址。(编辑:这适用于16位实数模式,对于受保护模式,请参阅其他答案。)此特定操作码通过位于逻辑地址所指向位置的虚拟地址(此处为32位)进行调用ds:[00923030h]
逻辑地址由两部分组成:
然后,按照如下方式计算最终地址:从选择器获取的基址+偏移量
这样的代码是由编译器发出的,因为从外部dll导入的函数的最终虚拟地址在编译时通常无法知道(由于dll的重定基址)。通过使用这样的调用构造,操作系统加载程序可以在逻辑地址指向的地址指针处插入正确的虚拟地址,并且编译器不需要关心最终函数具有哪个地址。
调用dword ptr ds:[00923030h]
,意思是调用
指针中的某个值0092393h
在数据段中
不完全是这样,我认为这涉及到一个间接过程。因此,它应该是:被调用的子例程所在的物理地址由存储在ds段寄存器中的基址处的值加上0x00923030给出。段选择器不像您所说的那样指向物理地址,而是指向线性地址。当逻辑地址已解析为线性地址时,物理地址将在最后一步中获得。是的,分段->线性,然后虚拟->物理。此外,x86中的所有内存访问都是相对于某个段的ds:
是数据寻址模式的默认值,而不是ebp
或esp
作为基本寄存器。这个答案似乎还意味着call ds:1234
将具有较少的间接级别,即它可能执行EIP=1234,而不是从内存地址ds:1234
加载新的EIP值。但这毫无意义;ds:1234
中的ds:
已经表示它是(数据)内存源操作数。不,这是调用r/m32
,而不是16
。dword是32位,字是16位。大多数错误都很小,下面隐藏着一个不错的答案,但是链接副本上的答案非常好。这是错误的,偏移量没有添加到值中