x86过程调用内存分配

Chang Liu

所以我的教科书上有一个问题(计算机系统:程序员的观点问题3.64):

它给出如下代码:

typedef struct {
 int a;
 int *p;
} str1;

typedef struct {
 int sum;
 int diff;
} str2;

str2 word_sum(str1 s1) {
 str2 result;
 result.sum = s1.a + *s1.p;
 result.diff = s1.a - *s1.p;
 return result;
}

int prod(int x, int y) {
 str1 s1;
 str2 s2;
 s1.a = x;
 s1.p = &y;
 s2 = word_sum(s1);
 return s2.sum * s2.diff;
}

然后是prod和word_sum函数的汇编代码:

1 word_sum:
2  pushl %ebp
3  movl %esp, %ebp
4  pushl %ebx
5  movl 8(%ebp), %eax
6  movl 12(%ebp), %ebx
7  movl 16(%ebp), %edx
8  movl (%edx), %edx
9  movl %ebx, %ecx
10 subl %edx, %ecx
11 movl %ecx, 4(%eax)
12 addl %ebx, %edx
13 movl %edx, (%eax)
14 popl %ebx
15 popl %ebp

1 prod:
2  pushl %ebp
3  movl %esp, %ebp
4  subl $20, %esp
5  leal 12(%ebp), %edx
6  leal -8(%ebp), %ecx
7  movl 8(%ebp), %eax
8  movl %eax, 4(%esp)
9  movl %edx, 8(%esp)
10 movl %ecx, (%esp)
11 call word_sum
12 subl $4, %esp
13 movl -4(%ebp), %eax
14 imull -8(%ebp), %eax
15 leave
16 ret

并询问为什么prod在汇编代码第4行中的堆栈上分配20个字节。

我可以看到它将分别为str1和str2分配8个字节,但是我不知道第五个4字节的内存分配是什么。

另外,你们对学习x86堆栈框架结构和过程调用有什么建议(视频,文章,博客文章)吗?目前,我的计算机体系结构课程非常迷茫。

科林·多芬妮(Collin Dauphinee)

分配用于的8个字节,用于的s18个字节s2和用于传递word_sum地址以存储其结果的4个字节


我是怎么知道的?

如果我们查看的顶部prod,则会看到:

5  leal 12(%ebp), %edx
6  leal -8(%ebp), %ecx
7  movl 8(%ebp), %eax

第5行和第7行是访问调用方堆栈框架的唯一指令,因此它们必须是xy我们知道我们要存储指向的指针,y而第5行是一条lea指令,因此我们可以假定EDX成立&y而EAX持有x这仍然留下ECX,该ECX在我们的堆栈框架中保存着指向某个对象的指针。

继续,我们看到它正在堆栈中存储EAX,EDX和ECX,然后调用word_sum

8  movl %eax, 4(%esp)
9  movl %edx, 8(%esp)
10 movl %ecx, (%esp)
11 call word_sum

我们知道EAX和EDX拥有需要存储在中的值s1我们知道s1它将被传递给word_sum,并且参数将被传递到堆栈的顶部。第8行和第9行将EAX和EDX存储在非常靠近堆栈顶部的位置,因此我们可以假设是s1

返回struct的函数期望在堆栈的顶部传递额外的指针这是它应该将返回值存储在的地址。我们要存储在堆栈顶部的唯一其他内容是ECX,并且我们知道我们要存储word_sumin的结果s2,因此ECX必须是的指针s2

现在我们推测每个寄存器的内容;EAX是x,EDX是&y,而ECX是&s2

如果我们看起来较低,则可以确认我们的期望:

13 movl -4(%ebp), %eax
14 imull -8(%ebp), %eax

我们知道此函数的结果为s2.sum * s2.diff这里有一个imul指令,而且我们乘s2.sums2.diff,所以EBP-8必须指向s2.sum和EBP-4必须指向s2.diff

如果回溯到第6行,我们会看到EBP-8存储在ECX中,我们正确地怀疑它是指向的指针s2


通常,这样的调试问题几乎完全是利用您对生成程序集的代码的了解来进行有根据的猜测,然后使用消除过程来确认您的猜测是正确的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

x86过程调用内存分配

来自分类Dev

x86过程错误

来自分类Dev

x86过程错误

来自分类Dev

堆栈上的内存分配和缓冲区溢出,x86 ISA32

来自分类Dev

x86中的内存分段混乱

来自分类Dev

x86:使用内存/交换值?

来自分类Dev

x86和MIPS内存寻址

来自分类Dev

x86内存访问分段错误

来自分类Dev

释放内存:组装NASM x86

来自分类Dev

x86程序集中的结构分配

来自分类Dev

在C ++中使用x64系统和x86应用程序分配大内存

来自分类Dev

在x86中调用printf

来自分类Dev

x86 的替代调用约定

来自分类Dev

C 调用 ASM (YASM x86)

来自分类Dev

为什么在.NET 4.5下,“任何CPU(首选32位)”都允许我分配比x86更多的内存?

来自分类Dev

x86 mov /添加指令和内存寻址

来自分类Dev

x86程序集中存储的内存段在哪里

来自分类Dev

内存地址和数组,汇编x86

来自分类Dev

x86的简单寄存器分配方案

来自分类Dev

x86 Assembly(AT&T):如何在运行时动态地将内存分配给变量?

来自分类Dev

调用在malloc之后执行(汇编NASM x86)

来自分类Dev

用于调用函数的 x86 汇编宏(带参数)

来自分类Dev

x86 Assembly:编写程序以测试整个1MB内存的内存功能

来自分类Dev

x86:将操作注册为内存内容和内存地址?

来自分类Dev

(x86)的含义

来自分类Dev

指针的c ++内存分配过程

来自分类Dev

从Assembly x86 NASM中的内存中读取16位

来自分类Dev

x86 Assembly(高级索引模式):如何在起始地址之前以可变的数量访问内存?

来自分类Dev

512MB(x86)系统上有82MB的“保留内存”