在程序集中获取参数值

Get parameter value in Assembly

提问人:Võ Khắc Bảo 提问时间:8/28/2023 最后编辑:Peter CordesVõ Khắc Bảo 更新时间:8/29/2023 访问量:44

问:

我是 Assembly 的初学者,所以我对从另一个函数在函数调用中传递参数感到困惑。具体来说,我有这样的代码: 集会:

bar:
pushl   %ebp
movl    %esp, %ebp
subl    $16, %esp
movl    $555, -4(%ebp)
movl    12(%ebp), %eax
movl    8(%ebp), %edx
addl    %edx, %eax
movl    %eax, -8(%ebp)
leave
ret
foo:
pushl   %ebp
movl    %esp, %ebp
subl    $8, %esp
movl    $222, 4(%esp)
movl    $111, (%esp)
call    bar
leave
ret

原始 C 代码:

void
bar(int a, int b)
{
 int x, y;

 x = 555;
 y = a+b;
 }

 void
 foo(void) {
 bar(111,222);
 }

在汇编代码中,我不明白为什么在 foo() 中

movl $222, 4(%esp)
movl $111, (%esp)
call bar

可以再次被 bar() 读取:

movl 12(%ebp), %eax
movl 8(%ebp), %edx

我试图分析,但我仍然不明白 foo() 函数中的 esp - 8 个字节是否可以等同于 bar() 函数 esp - 16 个字节中读取的位置?像 12、8、4 这样的偏移数字在这两个函数之间是否相关? 我对此感到非常困惑。如果有人向我解释或给我一个具体的例子来理解这个问题,我将不胜感激。 谢谢

程序集 x86 参数传递 内存堆栈

评论

1赞 Jester 8/28/2023
仅跟踪堆栈使用情况。 放置 4 个字节的返回地址,使用另外 4 个字节。然后复制到 .因此,差异是 8 个字节,这就是您从 .callpush ebpespebp22212(%ebp)4(%esp)
0赞 Võ Khắc Bảo 8/28/2023
谢谢你的回答,这正是我一直在寻找的

答:

3赞 teapot418 8/28/2023 #1

让我们想象一些样本值,并跟踪 ESP/EBP 会发生什么。另外请记住,推动某些东西(包括隐藏在里面的“”)会降低ESP。push eipcall

bar:  ;ESP=88
pushl   %ebp    ;ESP=84
movl    %esp, %ebp   ;EBP=84
subl    $16, %esp    ;ESP=78
movl    $555, -4(%ebp)
movl    12(%ebp), %eax   ;@96->EAX
movl    8(%ebp), %edx    ;@92->EDX
addl    %edx, %eax
movl    %eax, -8(%ebp)
leave
ret
foo:
pushl   %ebp         ;starting here:
movl    %esp, %ebp   ;let's assume ESP=100,EBP=100
subl    $8, %esp     ;ESP=92
movl    $222, 4(%esp) ;222->96
movl    $111, (%esp)  ;111->92
call    bar
leave
ret

评论

0赞 Võ Khắc Bảo 8/28/2023
你的答案很容易理解。谢谢!
0赞 Peter Cordes 8/29/2023
有趣的事实:一些 ABI(如 Linux 上 i386 System V 的现代版本)要求在 a 之前对齐 16 字节的 ESP,因此 ESP % 16 == 12 在函数输入时。但大多数其他 32 位调用约定(包括 *BSD 上的 i386 System V 和 macOS 删除 32 位支持之前的 macOS)只需要 4 字节对齐,因此这些 ESP 值是可能的。(更合理的是,它们像什么,但小数字是一个很好的例子,除了与示例值在同一范围内。call0x7fff0058
0赞 Peter Cordes 8/29/2023
有趣的事实: / 2x 而不是 2x 是 P5 等 CPU 的旧 GCC 调整的结果,以及 Pentium-M 的堆栈引擎使 push/pop single-uop 之前的早期 P6。相关选项是 和 - 为什么 gcc 使用 movl 而不是 push 来传递函数参数?,其中还提到 GCC 在 2014 年将默认值更改为 favor。sub $8, %espmovpush-maccumulate-outgoing-args-mpush-args-mtune=genericpush