【发布时间】:2012-02-26 20:00:35
【问题描述】:
我正在学习汇编语言。究竟什么是参数推送顺序?我了解它是如何将参数推入堆栈的,但是左右部分是什么意思?左边还是右边什么? 或者这仅仅是与命令的语义编写方式有关,即:
mov ebp, esp ;esp 从右到左移动到 ebp 中。
这是正确的还是有人可以启发我?
非常感谢!
【问题讨论】:
我正在学习汇编语言。究竟什么是参数推送顺序?我了解它是如何将参数推入堆栈的,但是左右部分是什么意思?左边还是右边什么? 或者这仅仅是与命令的语义编写方式有关,即:
mov ebp, esp ;esp 从右到左移动到 ebp 中。
这是正确的还是有人可以启发我?
非常感谢!
【问题讨论】:
处理器不知道“函数参数”。因此,当您想写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 中,其余参数在堆栈中。只要调用者和被调用者同意,就可以了。
【讨论】:
除了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 - 你的架构肯定会有一个标准的调用约定,因为没有它很难工作。
【讨论】: