Windows下32位汇编学习
0x01 前言
DOS下16位汇编学的时候完全就是硬啃,因为和现在用到的知识几乎不沾边,Windows下32位汇编开始涉及我们用到的知识,学起来还有点动力,本篇博客简单记录下Windows下32位汇编的学习总结
0x02 基本概念
CPU工作模式
从DOS下16位汇编到Windows下32位汇编,CPU的工作模式也从实模式变为保护模式(其实还有实模式和虚拟86模式,但本篇博客意在总结只挑重点说),这时CPU里的寄存器已经从16位变为32位,寻址空间也从之前的1MB变为4GB,并且多了两个东西,一个是内存分页机制,一个是优先级,内存分页机制可以为虚拟内存提供良好支持,后面内存管理中会提到,优先级包含4个级别,0-3级,0级就是常说的内核层ring0级,3级就是应用程序层ring3级,由于历史原因,Windows操作系统不使用1级和2级
内存管理
保护模式下Windows的内存管理和实模式下DOS的内存管理有很大不同,DOS下内存管理通过两个16位的寄存器得到一个20位地址,也就是最终的物理地址,而在保护模式下,首先,寄存器变为32位,2的32次幂=4GB,也就是说单个寄存器即可寻址4GB,不再需要之前(段地址:偏移地址)的形式,其次,由于内存分页机制,内存被分为一个个4KB大小的页,这些物理上不相邻的4KB大小的页通过一个叫“页表”的映射器,映射为虚拟地址,供操作系统和应用程序使用,人们常说的应用程序可以使用4GB,其实是因为CPU是一个分时处理器,例如,在0.001-0.002这个时间段,全部的4GB内存属于程序A,在0.002-0.003这个时间段,全部的4GB内存属于程序B,在0.003-0.004这个时间段,全部的4GB内存属主又切换回程序A,大概就是这个意思,从物理上看,实际的一块内存地址,可能上一秒属于程序A,下一秒属于程序B,从逻辑上看,一块内存地址,一直属于程序A
中断和异常
中断指当程序执行过程中有更重要的事情需要实时处理,通过中断控制器通知CPU,CPU保存好当前程序的地址后,转到中断处理程序,处理完后再通过保存的地址回来,异常指遇到指令异常、除法除0、权限异常等问题,转到异常处理程序,处理过程和中断处理程序一样,DOS下的中断和异常可以由用户控制,但是Windows下的中断和异常则有严格的限制,因为异常/中断处理程序的优先级比较高(优先级不高也没法优先进入中断),通过一个叫“门”的概念控制如何调用中断/异常处理程序
0x03 代码演示
Win32下汇编相比C语言不同的是,为语句找到他们该去的地方,比如代码段,数据段,堆栈段等,下面看一个反汇编例子
C语言代码
1 | #include <stdio.h> |
上述代码的反汇编代码
1 | ; main函数部分 |
反汇编代码解读:
1、首先是常规的EBP入栈,用于保存上一个栈基址指针
2、然后将栈顶指针(ESP)的值赋给栈基址指针(EBP)
3、栈向下延伸16字节
4、接下来该调用函数add了,此时EBP-4是第一个局部变量x的地址,EBP-8是第二个局部变量y的地址,由于C/C++遵循的调用标准是cdecl,也就是参数入栈时是从右向左,所以先将局部变量y入栈,再将局部变量x入栈
5、程序准备进入函数add的栈帧,进入之前会先把返回地址压入栈
6、进入函数add的栈帧后,同样是EBP、ESP那一套
7、此时以当前栈帧的EBP为基址,变量x和变量y的地址就应该是EBP+8和EBP+12,计算完后弹出返回地址,继续执行函数add后面的指令