3_寻址模式

寻址模式

我们来一个简单的例子, 看看它的寻址模式是怎么用的.

寻址模式使用实例

这边给出一个 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 交叉再放回去原来的地址里面去