【问题标题】:ASM to push function arguments to the stackASM 将函数参数推送到堆栈
【发布时间】:2013-06-14 16:25:29
【问题描述】:

我正在尝试使用 vs2008 将程序移植到 x64。然而,问题在于,这是一些 x64 不支持的内联 asm 代码。此 asm 代码用于将具有未知类型或编号的参数从 dll 推送到函数。它是一个基于 interpeter 的程序,您可以在其中指定要从某个 dll 使用的函数,程序会推送参数并在编译时调用该函数。

使用各种来源,我得出的结论是生成单独的 .asm 文件,其中包含 asm 函数,这些函数可以编译为 unsing masm 及其链接到 vs2008 的 obj 文件。为 x86 和 x64 使用不同的文件,程序为这两个问题构建。然而问题是,这些函数并没有复制内联汇编正在做的事情。

我转换了以下内联代码,例如:

double a = Evaluate(arg[i]).num;
_asm  push a  + 4 
_asm  push a
j += 8;

收件人:

double a = Evaluate(arg[i]).num;
EvaluateFuncArgFloat(a);
j += 8;

使用以下 .asm 文件:

TITLE EvaluateFuncArgFloat                      (evaluate_asm.asm)

.386
.model flat, C

.code
EvaluateFuncArgFloat PROC a:DWORD

        push    a + 4
        push    a
        ret

EvaluateFuncArgFloat ENDP

END

这并没有达到我的预期。 double 根本不会像使用内联 asm 时那样在函数中结束。

我的猜测是有一个小错误或我遗漏了一些东西,但经过多次尝试后,我似乎无法让它工作。希望有人能帮我解决这个问题,非常感谢。

【问题讨论】:

  • 调用函数的语义不能与内联程序集相同...涉及函数调用,这将修改堆栈。
  • 这段代码之后会发生什么?在 x86-64 上,函数参数可能会在寄存器中而不是在堆栈中找到。
  • 感谢你们的帮助。 Michael:在这段代码之后,它使用解释的名称和以下声明调用函数:double (*func_d)(void);
  • 你没有把你的堆栈搞得一团糟吗?两次推送和一次 ret 意味着它会返回到第二次推送
  • @user2486757:哦,你还在使用 32 位代码。好吧,要让您的汇编函数返回到正确的位置,您可以尝试将其更改为:pop eax/push dword ptr [a+4]/push dword ptr [a]/push eax/ret

标签: visual-c++ assembly 64-bit push inline-assembly


【解决方案1】:

一个偷偷摸摸的方法可能是

 EvaluateFuncArgFloat PROC a:DWORD

    pop eax            ;ret address popped to a safe register (if not ax/eax)
    push    a + 4
    push    a
    push eax           ;ret address back at top of stack
    ret

 EvaluateFuncArgFloat ENDP

问题是您将 2 个数字压入堆栈,但没有将它们删除 a+4 和 a

大概你的原始代码的另一部分在原始程序中处理这个

【讨论】:

  • 谢谢阿迪!我使用了上面迈克尔评论的代码。它包括 dword ptr,效果很好。您添加的注释也是正确的,稍后在解码代码中恢复堆栈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-16
  • 2011-11-12
  • 1970-01-01
  • 2019-04-26
  • 2016-07-14
相关资源
最近更新 更多