汇编指令入门

本文详细解析了32位CPU寄存器模型,重点讲解ESP寄存器在栈内存管理中的作用,以及在汇编指令中的使用实例,如栈帧分配、数据传递和函数调用过程。通过举例`_add_a_and_b`和`_main`函数,展示了如何在`push`, `pop`, `call`等操作中管理堆栈和寄存器。
摘要由CSDN通过智能技术生成

汇编语言入门教程

寄存器模型

早期的cpu有8个寄存器,分别为:

EAX
EBX
ECX
EDX
EDI
ESI
EBP
ESP

这8个寄存器中,前面七个都是通用的。ESP寄存器有特定用途,保存当前Stack的地址。
我们常常看到 32位 CPU、64位 CPU 这样的名称,其实指的就是寄存器的大小。
32 位 CPU 的寄存器大小就是4个字节。

内存模型

程序运行的时候,操作系统会给它分配一段内存,用来储存程序和运行产生的数据。这段内存有起始地址和结束地址,比如从0x1000到0x8000,起始地址是较小的那个地址,结束地址是较大的那个地址。

内存模型-堆

用户主动请求而划分出来的内存区域,叫做 Heap(堆)。它由起始地址开始,从低位(地址)向高位(地址)增长。
Heap 的一个重要特点就是不会自动消失,必须手动释放,或者由垃圾回收机制来回收。

内存模型-栈

除了 Heap 以外,其他的内存占用叫做 Stack(栈)。简单说,Stack 是由于函数运行而临时占用的内存区域。
每执行一个函数,会在内存中建立一个帧(frame),函数中的变量都保存在此帧中。函数执行结束后,该帧回收,
释放所有的内部变量,不再占用空间。

如果函数内部再调用了函数,则为新函数再创建帧,一般来说,调用栈有多少层,就有多少帧。

所有帧存放在栈Stack中,生成新帧称为入栈Push,栈的回收叫做出栈Pop。
Stack 的特点就是,最晚入栈的帧最早出栈(因为最内层的函数调用,最先结束运行),这就叫做"后进先出"的数据结构。
每一次函数执行结束,就自动释放一个帧,所有函数执行结束,整个 Stack 就都释放了。

Stack是由内存区域的结束地址开始,从高位(地址)向低位(地址)分配。

cpu指令

这时会在 Stack 上为main建立一个帧—帧的大小固定吗?

_add_a_and_b:
   push   %ebx
   mov    %eax, [%esp+8] 
   mov    %ebx, [%esp+12]
   add    %eax, %ebx 
   pop    %ebx 
   ret  
_main:
   push   3     // 入栈,并将esp寄存器地址
   push   2
   call   _add_a_and_b 
   add    %esp, 8
   ret

程序从_main标签开始执行,这时会在 Stack 上为main建立一个帧,并将 Stack 所指向的地址,写入 ESP 寄存器。
push 3: 将3放入stack,这里就是将3写入main这个帧。
push还有一个前置操作。它会先取出ESP寄存器里的地址,将其减去4字节,然后将新地址写入ESP寄存器【
就是说,每次入栈或出栈,ESP寄存器中保存的栈地址也会变化?】
得到新地址后,3就会写入这个地址开始的4个字节。

push2: 同样栈地址减去4字节,更新ESP寄存器并将2入栈。

call: 调用函数。
push %ebx: 将ebx寄存器里面的值入栈(大小为4字节),同样入栈前栈地址先减去4字节,更新ESP寄存器的值,再写入栈。
【这里是因为要用到ebx寄存器,因此把里面存的值先提取出来,放在栈里,用完后用恢复出来】

mov: 将某个值写入寄存器。
将esp中的地址加8字节,得到新地址,按照新地址从Stack中取数据,根据推算得到的是2(Statck中先后写入了3、2、exb地址三个值,
每个值都占4字节,esp地址分别减4、减8、减12后得到exb寄存器值、2、3,说明esp取数从高地址向低地址取,需要得到的是数的结束地址),
将2写入eax寄存器。【为什么这里eax没有同ebx一样,先取出其中的值?】

mov: esp+12得到数字3,将3写入ebx寄存器

add: 两个运算子相加,结果写入第一个运算子。 将eax(2)和ebx(3)的值相加,得到结果5,写入eax

pop: 取出Stack最近写入的值(即最低地址的值),将其写入指定位置。 取出最近写入的值(最低地址,即ebx寄存器的原始值),
将其写回exb寄存器(加法已经做完,不再需要此寄存器了)

ret: 终止当前函数执行,将运行权交还给上层函数。也就是,当前函数的帧将被回收。
将运行权交还给上层函数。也就是,当前函数的帧将被回收。

add %esp, 8: 将esp寄存器里的地址,手动加上8字节,再写回 ESP 寄存器。
这是因为esb保存的是stack的开始地址,前面pop已经回收了4字节,这里再回收8字节,等于全部回收。

ret: 最后,main函数运行结束,ret指令退出程序执行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值