《逆向工程核心原理》读书笔记——第4章 IA-32寄存器基本讲解

4.IA-32寄存器

  IA-32是英特尔推出的32位元架构,属于复杂的指令集架构,并且支持多种寄存器。下面列出了IA-32支持的寄存器类型。
在这里插入图片描述

  以上寄存器列表中,我们先要学习基本程序运行寄存器的相关内容,这是程序调试中最常见的寄存器,是学习程序调试初级技术必须掌握的内容。后面学习中、高级程序调试技术时,我们将继续学习有关控制寄存器(Control registers )、内存管理寄存器(Memory management registers )、调试寄存器(Debug registers)的知识。
基本程序运行寄存器
图4-1来自IA-32用户手册,描述了基本程序运行寄存器的组织结构,它由4类寄存器组成:
  通用寄存器( General Purpose Registers,32位,8个)
  段寄存器( Segment Registers,16位,6个)
  程序状态与控制寄存器( Program Status and Control Registers,32位,1个)
  指令指针寄存器( Instruction Pointer,32位,1个)
在这里插入图片描述

提示
  如图4-1所示,在寄存器名称缩略语之前添加字母E(Extended,扩展),表示该寄存器在16位CPU (IA-16)时就已经存在,并且其大小在IA-32下由原16位扩展为32位。
下面分别介绍一下各种寄存器。

1.通用寄存器

  顾名思义,通用寄存器是一种通用型的寄存器,用于传送和暂存数据,也可参与算术逻辑运算,并保存运算结果。IA-32中每个通用寄存器的大小都是32位,即4个字节,主要用来保存常量与地址等,由特定汇编指令来操作特定寄存器。除常规用途外,某些寄存器还具有一些特殊功能,请看图4-2(该图来自IA-32用户手册)。
在这里插入图片描述
提示
  为了实现对低16位的兼容,各寄存器又可以分为高(H:High)、低(L:Low )几个独立寄存器。下面以EAX为例讲解。
  ●EAX(accumulator): (0~31 )32位
  ●AX(accumulator): (0~15)EAX的低16位
  ●AH(accumulator): (8~15)AX的高8位
  ●AL(accumulator): (0~7)AX的低8位
  若想全部使用4个字节(32位),则使用EAX;若只想使用2个字节(16位),只要使用EAX的低16位部分AX就可以了。AX又分为高8位的AH与低8位的AL两个独立寄存器。借助这种方式,可以根据不同情况把一个32位的寄存器分别用作8位、16位、32位寄存器。
  各寄存器的名称如下所示。
  ●EAX(extend accumulator register):(针对操作数和结果数据的)累加器
  ●EBX(extend base register):(DS段中的数据指针)基址寄存器
  ●ECX(extend count register):(字符串和循环操作的)计数器
  ●EDX(extend data register):(IO指针)数据寄存器
  以上4个寄存器主要用在算术运算(ADD、SUB、XOR、OR等)指令中,常常用来保存常量与变量的值。某些汇编指令(MUL、DIV、LODS等)直接用来操作特定寄存器,执行这些命令后,仅改变特定寄存器中的值。
  此外,ECX与EAX也可以用于特殊用途。循环命令(LOOP)中,ECX用来循环计数(loop count),每执行一次循环,ECX都会减1。EAX一般用在函数返回值中,所有Win32 API函数都会先把返回值保存到EAX再返回。
请注意!
  编写Windows汇编程序时,Win32 API函数在内部会使用ECX与EDX,调用这些API时,ECX与EDX的值就会改变。所以,ECX与EDX中保存有重要数据时,调用API前要先把这些数据备份到其他寄存器或栈。
  通用寄存器中其他几个寄存器的名称如下所示。
  EBP(Base Pointer): (SS段中栈内数据指针)扩展基址指针寄存器
  ESI(Source Index):(字符串操作源指针)源变址寄存器
  EDI(Destination Index):(字符串操作目标指针)目的变址寄存器
  ESP(Stack Pointer): ( SS段中栈指针)栈指针寄存器
以上4个寄存器主要用作保存内存地址的指针。
  ESP指示栈区域的栈顶地址,某些指令(PUSH、POP、CALL、RET)可以直接用来操作ESP(栈区域管理是程序中相当重要的部分,请不要把ESP用作其他用途)。
  EBP表示栈区域的基地址,函数被调用时保存ESP的值,函数返回时再把值返回ESP,保证栈不会崩溃(这称为栈帧(Stack Frame)技术,它是代码逆向分析技术中的一个重要概念,后面会详细讲解)。ESI和EDI与特定指令(LODS、STOS、REP、MOVS等)一起使用,主要用于内存复制。

2.段寄存器

  段(Segment)这一术语来自IA-32的内存管理模型,学习段寄存器前,先了解一下段的有关知识。
提示
  段寄存器的相关知识对刚学习代码逆向分析技术的人而言比较难。所以阅读本部分内容时,并不需要完全掌握。随着代码逆向分析技术水平的提高,需要学习段寄存器时再深入学习亦可。
  IA-32的保护模式中,段是一种内存保护技术,它把内存划分为多个区段,并为每个区段赋予起始地址、范围、访问权限等,以保护内存。此外,它还同分页技术( Paging)一起用于将虚拟内存变更为实际物理内存。段内存记录在SDT ( Segment Descriptor Table,段描述符表)中,而段寄存器就持有这些SDT的索引( index )。
  请看图4-3(来自IA-32用户手册),它描述了保护模式下的内存分段模型。段寄存器总共由6种寄存器组成,分别为CS、SS、DS、ES、FS、GS,每个寄存器的大小为16位,即2个字节。另外,每个段寄存器指向的段描述符(Segment Descriptor)与虚拟内存结合,形成一个线性地址( Linear Address ),借助分页技术,线性地址最终被转换为实际的物理地址(Physical Address )。
提示
  不使用分页技术的操作系统中,线性地址直接变为物理地址。
在这里插入图片描述

  各段寄存器的名称如下。
  CS:Code Segment,代码段寄存器
  SS:Stack Segment,栈段寄存器
  DS:Data Segment,数据段寄存器
  ES:Extra ( Data ) Segment,附加(数据)段寄存器
  FS:Data Segment,数据段寄存器
  GS:Data Segment,数据段寄存器
  顾名思义,CS寄存器用于存放应用程序代码所在段的段基址,SS寄存器用于存放栈段的段基址,DS寄存器用于存放数据段的段基址。ES、FS、GS寄存器用来存放程序使用的附加数据段的段基址,如图4-3所示。
  程序调试中会经常用到FS寄存器,它用于计算SEH ( Structured Exception Handler,结构化异常处理机制)、TEB (Thread Environment Block,线程环境块)、PEB (Process Environment Block,进程环境块)等地址,这些都属于高级调试技术。

3.程序状态与控制寄存器

  ●EFLAGS:Flag Register,标志寄存器
  IA-32中标志寄存器的名称为EFLAGS,其大小为4个字节( 32位),由原来的16位FLAGS寄存器扩展而来。
  如图4-4所示,EFLAGS寄存器的每位都有意义,每位的值或为1或为0,代表On/Off或True/False。其中有些位由系统直接设定,有些位则根据程序命令的执行结果设置。
在这里插入图片描述

提示
  Flag一词具有“旗帜”、“旗标”的意思,“升旗”时设为1( On/True ),“降旗”时设为0 (Off/False ).
  如上所述,EFLAGS寄存器共有32个位元,掌握每位的含义是相当困难的。学习代码逆向分析技术的初级阶段,只要掌握3个与程序调试相关的标志即可,分别为ZF (Zero Flag,零标志)、OF (Overflow Flag,溢出标志)、CF (Carry Flag,进位标志)。
提示
  以上3个标志之所以重要,是因为在某些汇编指令,特别是Jcc(条件跳转)指令中要检查这3个标志的值,并根据它们的值决定是否执行某个动作。
  ●ZF(Zero Flag,零标志)
  若运算结果为0,则其值为1 ( True ),否则其值为0(False )。
  ●OF(Overflow Flag,溢出标志)
  有符号整数(signed integer)溢出时,OF值被置为1。此外,MSB (Most Significant Bit,最高有效位)改变时,其值也被设为1。
  ●CF(Carry Flag,进位标志)
  无符号整数(unsigned integer)溢出时,其值也被置为1。
刚开始会混淆OF和CF的发生条件,导致结果不尽如人意。不断积累调试经验就能明确区分了。

4.指令指针寄存器

  ●EIP: Instruction Pointer,指令指针寄存器
  指令指针寄存器保存着CPU要执行的指令地址,其大小为32位(4个字节),由原16位IP寄存器扩展而来。程序运行时,CPU会读取EIP中一条指令的地址,传送指令到指令缓冲区后,EIP寄存器的值自动增加,增加的大小即是读取指令的字节大小。这样,CPU每次执行完一条指令,就会通过EIP寄存器读取并执行下一条指令。
  与通用寄存器不同,我们不能直接修改EIP的值,只能通过其他指令间接修改,这些特定指令包括JMP、Jcc、CALL、RET。此外,我们还可以通过中断或异常来修改EIP的值。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值