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

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

预备知识

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

这里写图片描述

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

程序用 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

这里写图片描述
假设当前已有两个函数帧,ebp 当前指向的地址是1000,esp 当前指向的地址是804。

这里写图片描述
1. 把 ebp 的值压栈。
因为 esp 永远指向栈顶,所以当前 esp 的值为800。
2. 把 esp 中的值放到 ebp 中。
此时 ebp 和 esp 中的值都是800。

这里写图片描述
3. 把 esp 中的值减去24。
esp 中的值为776。

这里写图片描述
4. 把10这个值放到 ebp 指向地址减去4个字节的地方(796)。
5. 把20这个值放到 ebp 指向地址减去8个字节的地方(792)。

这里写图片描述
6. 把 ebp 减去8得到的地址,放到 eax 寄存器中(eax 的值是792)。
7. 把 eax 的值(792)放到 esp 的地址加4的地方去(780)。
8. (与前面两步类似)把 ebp 减去4得到的地址,放到 eax 寄存器中(eax 的值是796)。
9. 把 eax 的值(796)放到 esp 指向的地址处(776)。

这里写图片描述
10. 调用 add 函数。

这里写图片描述
1. (函数的前两步基本一致)把 ebp 的值压栈(800)。
2. 把 esp 中的值,放到 ebp 中去(此时同为768)。
3. 把 ebx 的值压栈(额外操作,因为接下来需要使用 ebx ,防止之前保存的值被冲掉,所以需要先保存到内存中,Intel 做出如下规定:对于 ax 、cx、ex,调用者需要保存,对于 bx,被调用者保存——有 push 操作,必定对应着后面的 pop 操作,第3行对应第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)。

这里写图片描述
9. 弹出栈顶的值放到 ebx 中。
10. 弹出栈顶的值放到 ebp 中(此时 ebp 指向800)。
11. return,执行地址为100处的指令。
之后执行 demo 方法中的第11行。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值