x86指令是什么意思“call dword ptr ds:[00923030h]”?

时间:2009-02-05 22:27:33

标签: assembly x86 addressing-mode

以下x86汇编程序指令有什么作用?

call dword ptr ds:[00923030h]

这是我怀疑的间接电话,但它究竟是如何计算电话的地址的呢?

4 个答案:

答案 0 :(得分:17)

[编辑]已更新

每当您看到类似ds:0x00923030的内存操作数时,就是段相对寻址模式。被引用的实际地址tp是相对于ds段寄存器的基址的线性地址0x00923030。

x86架构中的内存分段有些令人困惑,我认为Wikipedia可以很好地解释它。

基本上,x86有许多特殊的寄存器:cs代码段),ds数据 segment),esfsgsss stack 段)。每个存储器访问都与某个段寄存器相关联。通常,您不指定段寄存器,并且根据访问存储器的方式,使用默认段寄存器。例如,cs寄存器用于读取指令。

每个段寄存器都有一个基地址限制。基址确定线性地址0x00000000对应的物理地址,并且该限制确定该段的最大允许线性地址。例如,如果基址为0x00040000且限制为0x0000FFFF,则唯一有效的线性地址为0x00000000至0x0000FFFF,相应的物理地址为0x00040000至0x0004FFFF。

因此,被调用子程序所在的物理地址由存储在ds段寄存器中的基地址加上0x00923030给出。但是我们还没有完成 - 指令里面有ptr这个词。这增加了额外的间接级别,因此子例程的实际目标是位于ds:0x00923030存储的地址。

在AT& T语法中(由GNU汇编程序接受),该指令将按如下方式编写:

lcall *ds:0x00923030

有关该指令的完整详细信息,请参阅80386 reference manual。指令的这个特定变体是"CALL r/m16"(调用接近寄存器间接/内存间接)。

答案 1 :(得分:10)

此特定操作码通过位于逻辑地址ds:[00923030h]指向的位置的虚拟地址(此处为32位)进行调用。
逻辑地址由两部分组成:

  1. 这种情况下的16位段选择器ds,它基本上是操作系统管理的(全局/本地)描述符表的索引。这样的选择器还保存给定段的访问权限信息,在访问时检查(当前权限级别CPL
  2. 32位偏移量
    然后按如下方式计算最终地址:从选择器+偏移量
  3. 获取的基地址

    请注意,上面的计算表示一个线性地址,不是一个物理地址(参见intel手册volume 3a,图2.2),然后通过4KB分页的标准机制进行翻译,即地址由页面目录索引,页面表和所选页面的偏移量组成。但请记住,所有主流操作系统都使用所谓的平坦内存模式,这意味着所有段选择器都指向地址0x00000000,限制设置为0xFFFFFFFF,这就是为什么你可以在所有段之间进行转换并最终导致(容易)利用缓冲区溢出。

    您给出的汇编程序指令很可能是通过可执行文件的导入地址表(请参阅this伟大的文章以获取更多详细信息)调用,即它不太可能是一个序数子例程打电话。
    像这样的代码是由编译器发出的,因为来自外部dll的导入函数的最终虚拟地址通常在编译时是不可知的(由于dll的重新定义)。通过使用这样的调用构造,OS加载器可以通过逻辑地址在地址指针处插入正确的虚拟地址,并且编译器无需关心最终函数具有哪个地址。

答案 2 :(得分:1)

IIRC,它接受DS寄存器的值(并将其向左移4位),再加上给定的立即值,从得到的存储单元中取出一个双字值,该值成为要调用的地址。 (编辑:这适用于16位实模式,对于保护模式,请参阅其他答案。)

答案 3 :(得分:1)

call dword ptr ds:[00923030h],表示call的指针00923939h中的data segment