我正在学习汇编语言。什么是参数推送顺序?我理解它如何被推入堆栈但左右部分是什么意思?什么左?或右? 或者这只是与语义编写命令的方式有关,即:
mov ebp,esp; esp从右到左移动到ebp。
这是正确的还是有人可以启发我?
非常感谢!
答案 0 :(得分:14)
处理器不知道'函数参数'。因此,当你想写f(a,b,c)
时,你真的需要在某个地方推送参数。
这是惯例。我知道在大多数x86机器上,函数参数从右到左被推入堆栈,即第一个c,然后是b,然后是a。
push c
push b
push a
call f
现在被叫函数可以使用ebx -1
代表a,ebx - 2
代表b,ebx - 3
代表c。
您还可以建立一个约定:前两个参数位于寄存器ebx
和ecx
中,其余位于堆栈中。只要来电者和被叫者同意,你就没事了。
答案 1 :(得分:10)
除xtofl的解释外,您可能希望查看此x86 calling conventions表。关于参数顺序,你会注意到的是几乎所有参数都是从右到左推送的(最右边的参数是先推的),Pascal除外。
另一个场景xtofl没有涉及寄存器参数 - 一些ABI要求某些参数位于寄存器中而不是堆栈上的。例如,在x86_64
系统上,函数:
int add3(int a, int b, int c)
将提出参数:
a -> rdi
b -> rsi
c -> rdx
具体来说,这看起来像(英特尔语法):
mov rdi, [source-of-a]
mov rsi, [source-of-b]
mov rdx, [source-of-c]
call add3
因此寄存器从寄存器列表从左到右填充然后堆栈使用从右到左。
正如xtofl所说,如果调用者和被调用者同意你做什么并不重要 - 但是,如果调用者和被调用者不同意这会导致不兼容问题,这显然是实际上,不仅对于汇编程序而且对于更高级别的语言也是一个问题 - 幸运的是,编译器主要从右到左运行。为了进一步阅读,您可能会发现堆栈的被调用者/调用者清理很有趣 - 并注意它是如何标准化为x86_64
的一种方法。
你没有说你正在使用x86
- 你的架构肯定会有一个标准的调用约定,因为没有它就很困难。