我试图更好地理解链接器及其工作方式,因此我尝试从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世界时c编译器调用的函数! c申请
链接器成功构建程序,但是当我运行程序时它会崩溃!
我读取了链接器输出消息,除了表示:"从MSVCRTD.lib(MSVCR100D.dll)中删除_printf"。
我使用OllyDBG调试程序,我发现应该登陆该函数的调用指令实际上落在一个被识别为DATA的区域!在.rdata部分
为什么" _printf" 功能成功且" __ imp__printf" 没有:(,任何idias?
答案 0 :(得分:1)
感谢Jester先生和Raymond Chen先生 他们在评论中为问题提供了解决方案。
这是__imp__printf
的声明。它被声明为PROC,就像工作示例_printf
一样,但有数据如此声明。
Extern _imp__printf :DWORD
将使其成为printf
非常感谢你们两位
答案 1 :(得分:0)
编辑:这不是解决方案,但我会留待以后参考。下一个答案中的解决方案。
我想我已经接近弄清楚为什么因为跳转指令中的问题而调用_imp__printf
外部函数失败,这就是我所做的..
我试图打造你好世界! C程序看看_imp__printf
函数在符号表中的样子如果文件编译为C程序而不是程序集,我然后转储从两个调用程序编译的OBJ文件(MASM /和c),结果非常有趣,这里是从 C文件
_imp__printf
以下是从 MASM文件
编译的OBJ中的_imp__printf
有趣!并且在引用COFF文档后似乎重定位类型REL32将强制链接器不能正确处理导入地址表,因此跳转指令将像以前一样掉落。
现在我的问题是"我怎么能告诉MASM用_imp__printf
符号类型组装文件" DIR32"吗