运行 从汇编代码调用 c 库函数时出错

running error when calling a c library function from assmbly code

我试图更好地理解 linker 及其工作方式,所以我尝试调用 c 库 (MSVCRTD.lib) 中的简单函数 (printf),但是MASM 上的汇编代码。

我从 "MSVCRTD.lib" 库中剖析了外部符号,它有许多 printf 函数,例如:

__imp__printf
_printf
___imp___printf_l
;and more ...

我有 2 个挑战 (linking/building) 和 (运行ning)。

至于第一个挑战 link 将我的汇编代码写入库完全不是问题,我可以 link 我的汇编代码调用库的任何外部函数,我所需要的只是模仿函数的装饰(损坏)名称,以便 linker 可以识别它。我首先尝试了第二个“_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 应用程序

link 人成功构建了程序,但是当我 运行 程序崩溃时!

我阅读了 linker 的输出消息,除了以下行外,其他一切看起来都很正常:“Discarded _printf from MSVCRTD.lib(MSVCR100D.dll)”。

我用OllyDBG调试了程序,我发现应该落在函数上的调用指令实际上落在了一个被识别为DATA的区域!在 .rdata 部分

为什么 "_printf" 函数成功而 "__imp__printf" 没有:( , 任何 idias?

编辑:这不是解决方案,但我会留作以后参考。下一个答案中的解决方案。

我想我已经接近弄清楚为什么调用 _imp__printf 外部函数失败是因为跳转指令中的问题,这就是我所做的..

我试着构建了你好世界! C 程序查看 _imp__printf 函数在符号 table 中的样子,如果文件编译为 C 程序而不是汇编,然后我转储从两个调用程序编译的 OBJ 文件( MASM/ 和 c),结果非常有趣,这里是从 C 文件

编译的 OBJ 中的 _imp__printf

这里是从 MASM 文件

编译的 OBJ 中的 _imp__printf

有趣!并且在参考了COFF文档后,似乎重定位类型REL32会强制链接器无法正确处理导入地址table,因此跳转指令将像以前一样下降。

现在我的问题是 "how I can tell MASM to assemble the file with _imp__printf symbol type "DIR32" ?

感谢Jester先生和Raymond Chen先生 他们在评论中提供了问题的解决方案。

这是__imp__printf的声明。像工作示例一样声明为 PROC _printf 但有 DATA 如此声明。

Extern _imp__printf :DWORD

将使它像printf

一样工作

非常感谢你们,你们俩