【问题标题】:x86 assembly pushing parameters before a jumpx86 程序集在跳转前推送参数
【发布时间】:2019-10-15 18:15:56
【问题描述】:

我正在从事一个高级设计项目,但遇到了一个小障碍。有没有在汇编中,你可以有一个情况,你推参数,然后跳转到不同的位置,然后调用函数?

您似乎无法从我可用的文件中获取信息,但它们并非包罗万象。任何帮助将不胜感激,谢谢!

【问题讨论】:

  • 当然,为什么不呢?例如,您可能会根据条件调用具有不同参数的函数。
  • 只要保持正确的状态,你就可以跳到任何你想跳的地方。作为汇编程序员,这完全取决于您。编译器不会像 C(或者当然是 C++)那样自动生成/插入代码,所以跳转并不“危险”。

标签: assembly x86


【解决方案1】:

重要的是当执行到达您要调用的函数的顶部时堆栈上的内容。它到达那里的方式或顺序无关紧要,只是 ESP 指向返回地址,ESP+4 指向第一个堆栈 arg,依此类推。

函数也不知道或关心您是使用calljmp 尾调用还是jae 到达它条件尾调用。

您甚至根本使用push,您可以在函数顶部使用sub esp, 24,只需使用mov 来存储您的参数。 (就像 gcc -m32 -maccumulate-outgoing-args 所做的那样,它曾经在没有堆栈引擎的旧 CPU 上运行良好,而 push 效率不高。)Why does gcc use movl instead of push to pass function args?

(当然更有效的调用约定在寄存器中传递参数,只有在有超过 2 或 3 个整数/指针参数时才使用堆栈。但同样的区别,调用约定指定进入函数时所需的状态,不是你是如何做到这一点的。


既然您甚至不得不问这个问题,请记住 CPU 基本上是一个状态机。每条指令对体系结构状态(寄存器和内存内容,包括特殊的寄存器,如 EFLAGS 和指令指针)都有其记录的影响。除此之外,没有上下文。你如何达到一个状态并不重要,重要的是你处于其中。


对于部分寄存器停顿、存储转发停顿、分支预测以及多条指令的重叠执行等情况,上下文对性能很重要。但不是为了正确。

(我忽略了 Spectre / Meltdown 漏洞利用,它创建了已知的微架构状态,然后将其读入架构状态。)

【讨论】:

    【解决方案2】:

    你所说的一个例子可能是这样的;

        cmp     al, 32
    
        push    48
        push    ecx
        push    esi
        jae     test
    
        call    func01
        jmp     done
    
    test:
        call    func02
    
    done:
    

    两个函数都需要相同的三个参数,但取决于 AL >= 32 是否确定调用哪个函数。

    【讨论】:

    • 我建议在推送之后做cmp al,32,这样它就可以和jae进行宏融合。当您使用cmptest 时,将标志集与标志读取分开不再是一个好主意。如果您想在cmp 之后但在jcc 之前使用movlea 破坏eax,那将是有道理的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 2014-06-30
    相关资源
    最近更新 更多