运行 从汇编代码调用 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
一样工作
非常感谢你们,你们俩
我试图更好地理解 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 文件
_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
非常感谢你们,你们俩