20170226听课笔记(程序的机器级表示)

上节课讲了递归、堆栈,及每一个函数的栈帧在堆栈中是怎么排列的,但并未深入到机器级的层次,对 CPU 来说,它到底是怎么维持这个堆栈的,以及上节课提到的 EPB 和 ESP 到底是如何处理的。

预备知识

EBP:永远指向当前栈帧的开始处。
ESP:永远指向栈的栈顶。
部分汇编指令

20170226听课笔记(程序的机器级表示)_第1张图片

正题:如何使用汇编语言执行一个简单的加法运算。

程序用 C 语言表示:

int demo(){
    int x = 10;
    int y = 20;
    int sum = add(&x, &y);
    printf("the sum is %d\n", sum);
    return sum;
}

int add(int *xp, int *yp){
    int x = *xp;
    int y = *yp;
    return x+y;
}

用汇编语言表示:

demo:
1  pushl  %ebp
2  movl  %esp %ebp
3  subl  %24 esp
4  movl  $10  -4(%ebp)
5  movl  $20  -8(%ebp)
6  leal  -8(%ebp)  %eax
7  movl  %eax  4(%esp)
8  leal  -4(%ebp) %eax
9  movl  %eax  esp
10  call add
11  打印结果(略)

add:
1  pushl  %ebp
2  movl  %esp %ebp
3  pushl  %ebx
4  movl  8(%ebp) %edx
5  movl  12(%ebp)  %ecx
6  movl  (%edx)  %ebx
7  movl  (%ecx)  %eax
8  add  %ebx  %eax
9  popl  %ebx
10  popl  %ebp
11  ret

人肉 CPU

20170226听课笔记(程序的机器级表示)_第2张图片
假设当前已有两个函数帧,ebp 当前指向的地址是1000,esp 当前指向的地址是804。

20170226听课笔记(程序的机器级表示)_第3张图片
1. 把 ebp 的值压栈。
因为 esp 永远指向栈顶,所以当前 esp 的值为800。
2. 把 esp 中的值放到 ebp 中。
此时 ebp 和 esp 中的值都是800。

20170226听课笔记(程序的机器级表示)_第4张图片
3. 把 esp 中的值减去24。
esp 中的值为776。

20170226听课笔记(程序的机器级表示)_第5张图片
4. 把10这个值放到 ebp 指向地址减去4个字节的地方(796)。
5. 把20这个值放到 ebp 指向地址减去8个字节的地方(792)。

20170226听课笔记(程序的机器级表示)_第6张图片
6. 把 ebp 减去8得到的地址,放到 eax 寄存器中(eax 的值是792)。
7. 把 eax 的值(792)放到 esp 的地址加4的地方去(780)。
8. (与前面两步类似)把 ebp 减去4得到的地址,放到 eax 寄存器中(eax 的值是796)。
9. 把 eax 的值(796)放到 esp 指向的地址处(776)。

20170226听课笔记(程序的机器级表示)_第7张图片
10. 调用 add 函数。

20170226听课笔记(程序的机器级表示)_第8张图片
1. (函数的前两步基本一致)把 ebp 的值压栈(800)。
2. 把 esp 中的值,放到 ebp 中去(此时同为768)。
3. 把 ebx 的值压栈(额外操作,因为接下来需要使用 ebx ,防止之前保存的值被冲掉,所以需要先保存到内存中,Intel 做出如下规定:对于 ax 、cx、ex,调用者需要保存,对于 bx,被调用者保存——有 push 操作,必定对应着后面的 pop 操作,第3行对应第9行)。

20170226听课笔记(程序的机器级表示)_第9张图片
4. 把 ebp 地址加8处的值,放到 edx 中(edx 的值是796)。
5. 把 ebp 地址加12处的值,放到 ecx 中(edx 的值是792)。
6. 把 edx 里的值作为地址寻值,把找到的数放到 ebx 中(ebx 的值是10)。
7. 把 ecx 里的值作为地址寻值,把找到的数放到 eax 中(eax 的值是20)。
8. 把 ebx 和 eax 中的值加起来放到 eax 中(eax 的值是30)。

20170226听课笔记(程序的机器级表示)_第10张图片
9. 弹出栈顶的值放到 ebx 中。
10. 弹出栈顶的值放到 ebp 中(此时 ebp 指向800)。
11. return,执行地址为100处的指令。
之后执行 demo 方法中的第11行。

你可能感兴趣的:(听课笔记)