Assembly x86指令的含义是什么;打电话给德沃德ptr ds:[00923030h]";?

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(堆栈段)。每

下面的x86汇编指令是做什么的

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]

逻辑地址由两部分组成:

  • 一个16位段选择器,在本例中为ds,它基本上是操作系统管理的(全局/本地)描述符表的索引。这种选择器还保存给定段的访问权限信息,该信息在访问时被检查(当前特权级别)
  • 32位偏移量
    然后,按照如下方式计算最终地址:从选择器获取的基址+偏移量
  • 请注意,上述计算表示一个线性地址,而不是物理地址(请参阅英特尔手册,图2.2),然后通过4KB分页的标准机制转换该地址,即地址由页目录索引、页表和所选页的偏移量组成。请记住,所有主流操作系统都使用所谓的平面内存模型,这意味着所有段选择器都指向地址0x00000000,限制设置为0xFFFFFF,这就是为什么可以在所有段之间强制转换,并最终导致(轻松)利用缓冲区溢出的原因

    您给出的汇编指令很可能是通过可执行文件的导入地址表(有关更多详细信息,请参阅great article)进行的调用,也就是说,这不太可能是顺序子例程调用。

    这样的代码是由编译器发出的,因为从外部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位。大多数错误都很小,下面隐藏着一个不错的答案,但是链接副本上的答案非常好。这是错误的,偏移量没有添加到值中