【发布时间】:2023-04-06 10:31:01
【问题描述】:
我试图更好地理解链接器及其工作原理,因此我尝试从 c 库 (MSVCRTD.lib) 中调用简单函数 (printf),但在 MASM 上使用汇编代码。
我从“MSVCRTD.lib”库中剖析了外部符号,该库具有许多 printf 的功能,例如:
__imp__printf
_printf
___imp___printf_l
;and more ...
我遇到了 2 个挑战(链接/构建)和(运行)。
至于将我的汇编代码链接到库的第一个挑战根本不是问题,我可以将我的汇编代码与对库的任何外部函数的任何调用链接起来,我只需要模仿装饰的(Mangled)函数的名称,以便链接器可以识别它。我首先尝试了第二个“_printf”,它锁定得更短更好,在反汇编它的代码后,我知道它在堆栈上需要 2 个参数,这是一个 cdecl 调用约定,所以我编写了它需要的代码,它是:
.386
.model flat,stdcall
.stack 4096
option casemap :none
Extern printf :PROC ; MASM will decorate it to be "_printf"
.data
message byte "Hello C library, this is MASM calling"
.code
main proc
push 0
push offset message
call printf
add esp,8 ; clean the stack
retn
main endp
end
然后射击!一切都很顺利。
但是当我用 "_imp__printf" 尝试同样的事情时,问题开始了。
BTY:这个函数是你编写著名的 hello world 时 c 编译器调用的函数! c应用
链接器成功构建程序,但是当我运行程序时它崩溃了!
我阅读了链接器输出消息,除了以下行:“Discarded _printf from MSVCRTD.lib(MSVCR100D.dll)”之外,一切看起来都很正常。
我用 OllyDBG 调试了程序,发现应该落在函数上的调用指令实际上落在了一个被识别为 DATA 的区域上!在 .rdata 部分中
为什么 "_printf" 函数成功而 "__imp__printf" 没有:( , 任何 idias?
【问题讨论】:
-
那是一个指针,确保你写了
call [_imp__printf]。 -
你误报了
_imp__printf。这是DWORD而不是PROC。 -
_printf是PROC。_imp__printf是DWORD。你正确地声明了_printf,所以它起作用了。你错误地声明了_imp__printf,所以它不起作用。 -
因为 Jester 在第一条评论中是这么说的。你想做一个间接调用,这意味着你调用的东西不是一个过程。它是一个指向过程的指针。
-
如果方括号和声明冲突,汇编器选择声明。听起来你需要在尝试做这样的花哨的东西之前获得更多的汇编器经验。
标签: c++ c debugging assembly linker