【问题标题】:running error when calling a c library function from assmbly code从汇编代码调用 c 库函数时出现运行错误
【发布时间】: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
  • _printfPROC_imp__printfDWORD。你正确地声明了_printf,所以它起作用了。你错误地声明了_imp__printf,所以它不起作用。
  • 因为 Jester 在第一条评论中是这么说的。你想做一个间接调用,这意味着你调用的东西不是一个过程。它是一个指向过程的指针。
  • 如果方括号和声明冲突,汇编器选择声明。听起来你需要在尝试做这样的花哨的东西之前获得更多的汇编器经验。

标签: c++ c debugging assembly linker


【解决方案1】:

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

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

Extern _imp__printf :DWORD

将使它作为printf工作

非常感谢你们俩

【讨论】:

    【解决方案2】:

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

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

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

    编译的OBJ中的_imp__printf

    这是从MASM文件

    编译的OBJ中的_imp__printf

    有趣!并且在参考了COFF文档之后,似乎重定位类型REL32会强制链接器不能正确处理导入地址表,所以跳转指令会像以前一样落下。

    现在我的问题是“我如何告诉 MASM 用 _imp__printf 符号类型“DIR32”组装文件?

    【讨论】:

      猜你喜欢
      • 2022-01-04
      • 1970-01-01
      • 1970-01-01
      • 2021-02-25
      • 2011-09-04
      • 2016-09-07
      • 2017-02-18
      • 1970-01-01
      • 2016-06-01
      相关资源
      最近更新 更多