目录 Table of Contents
寻址模式
我们来一个简单的例子, 看看它的寻址模式是怎么用的.
寻址模式使用实例
这边给出一个 swap 小程序
void swap(int *xp. int *yp)
{
int t0 = *xp;
int t1 = *yp;
*xp = t1;
*yp = t0;
}
这个函数接受两个指针作为它的输入参数, 这两个指针都是指向内存地址, 里面存的是 int, 然后函数把两个内存地址里面的内容调换一下
然后我们用 gcc 编译出 .s 汇编程序
swap :
;set up
pushl %ebp
movl %esp, %ebp
pushl %ebx
;body
movl 12(%ebp), %ecx
movl 8(%ebp), %edx
movl (%ecx), %ebx
movl (%edx), %ebx
movl %eax, (%edx)
movl %ebx, (%ecx)
;finish
movl -4(%ebp), %ebx
movl %ebp, %esp
popl %ebp
我们现在主要关注这个 body 部分
实例分析
源程序中有 4 个变量, 下表列出了寄存器与这 4 个变量的对应关系
寄存器 | 变量 |
---|---|
%ecx | yp |
%edx | xp |
%eax | t1 |
%ebx | t0 |
这个图给出了程序栈的结构
ebp 的地址往上加, 加 4, 加 8, 加 12.
ebp + 8 就可以访问被传过来的参数.
它如果往下呢, 就可以访问你这个过程的一些局部变量和临时存储, 这里不展开了.
我们从这个实例出发, 我们可以看到 ebp + 8 实际上就是 xp, ebp + 12 就是 yp.
这样子的话, 程序怎么走, 我们看一下.
首先我们从这边看一看, ebp 的初始值是 0x104, 实际上它指向 old ebp 这个值, 这个值我们不关心就不写了.
我们继续往下走, ebp + 12, 实际上就相当于说我又把 ebp 加上 12, 加 12 就相当于在栈的地址里面存放 yp, 就是输入给你的那个参数的值, 那个参数是 0x120. 注意, 0x120 这个参数本身是 int* 类型的, , 它不是你具体要交换的那个数.
取了 yp 之后, 我们取 xp. xp 就是 8(%ebp). xp 存放在 0x10c 里面, 我们就把它的内容取出来了.
我们刚才取出来了 ecx, ecx 就是 yp 的内容, yp 本身就是 int* 类型, 所以 yp 本身是个地址. 我们把这个值加个括号, 采用基址访问内存的方式, (%ecx), 把 ecx 这个值作为地址, 再把地址里面的数据取出来放到 eax 里面去.
下面是 edx, 然后我们把 edx 以此类推. 相当于把 xp 这个指针指向的地址里面的数据提取出来, 放到 ebx.
我现在 eax, ebx 分别存放了 yp xp 这两个指针指向的地址的内容, 然后把这两个内容, 也就是 eax ebx 交叉再放回去原来的地址里面去