【发布时间】:2011-10-30 16:25:37
【问题描述】:
所以最近我一直想从汇编中调用一些 win32 调用,并且我一直在使用 NASM 作为我的外部汇编器。我通过以下方式在我的代码中调用SendMessage:
call __imp__SendMessageW@16
这被组装成一个相对跳转(0xE8 操作码),结果是访问冲突。在调试器中,计算出的跳转偏移量似乎是正确的(__imp__SendMessageW@16 似乎确实存在于那里),但它仍然不起作用。当我从 C++ 调用该函数时,检查 Visual Studio 生成的程序集,我注意到它使用的不是相对直接的跳转,而是(在 MASM 的语言中)call dword ptr [__imp__SendMessageW@16],对应于 0xFF15 操作码。经过一番折腾后,我发现 NASM 语法将其编码为call dword near [dword __imp__SendMessageW@16],并让我的代码突然生效。
我的问题是,为什么一个有效而另一个无效?是否有一些代码重定位导致相对立即调用跳转到不友好的地方?我从来都不是汇编程序员,但我的印象始终是这两个调用应该做同样的事情,主要区别是一个是位置独立的,另一个不是(假设他们将 IP 移动到同一个地方)。考虑到这一点,代码理论的重定位是有道理的,但是你如何解释调试器显示正确的地址呢?
另外:这个调用中[] 语法背后的逻辑是什么?偏移量仍然是立即数(只是在 0xFF15 之后立即编码的小端序),除了指令获取之外,这里没有内存访问(我倾向于将[] 视为lea 上下文之外的取消引用)。
【问题讨论】:
标签: windows winapi assembly nasm