10 x86 assembly addressing-mode
以下x86汇编程序指令有何功能?
call dword ptr ds:[00923030h]
Run Code Online (Sandbox Code Playgroud)
这是我怀疑的间接电话,但它究竟是如何计算通话的地址的呢?
Ada*_*eld 17
[编辑]更新
每当你看到类似的内存操作数时ds:0x00923030,这就是一个段相对寻址模式.被参考的实际地址tp是相对于ds段寄存器的基地址的线性地址0x00923030 .
x86架构中的内存分段有点令人困惑,我认为Wikipedia在解释它方面做得很好.
基本上,86具有许多特殊段寄存器: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
Run Code Online (Sandbox Code Playgroud)
有关该指令的完整详细信息,请参阅80386参考手册.指令的这种特定变体是"CALL r/m16"(调用接近寄存器间接/存储器间接).
new*_*gre 10
此特定操作码通过位于逻辑地址指向的位置的虚拟地址(此处为32位)进行调用ds:[00923030h].
逻辑地址由两个组件组成:
请注意,上面的计算表示线性地址,而不是物理地址(参见intel手册第3a卷,图2.2),然后通过4KB分页的标准机制进行转换,即地址由页面目录的索引,页面组成.表和所选页面的偏移量.但请记住,所有主流操作系统都使用所谓的平坦内存模式,这意味着所有段选择器都指向地址0x00000000,限制设置为0xFFFFFFFF,这就是为什么你可以在所有段之间进行转换并最终导致(容易)利用缓冲区溢出.
您给出的汇编程序指令很可能是通过可执行文件的导入地址表(请参阅这篇伟大的文章以获取更多详细信息)进行调用,即这不太可能是一个序数子例程调用.
像这样的代码是由编译器发出的,因为来自外部dll的导入函数的最终虚拟地址通常在编译时是不可知的(由于dll的重新定义).通过使用这样的调用构造,OS加载器可以通过逻辑地址在地址指针处插入正确的虚拟地址,并且编译器无需关心最终函数具有哪个地址.
| 归档时间: |
|
| 查看次数: |
8220 次 |
| 最近记录: |