博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
逆向基础---vc汇编(一)
阅读量:4123 次
发布时间:2019-05-25

本文共 4202 字,大约阅读时间需要 14 分钟。

首先介绍我们会经常看到的一些寄存器:

4个数据寄存器(EAX、EBX、ECX和EDX)

2个变址和指针寄存器(ESI和EDI)

2个指针寄存器(ESP和EBP)

4个数据寄存器(EAX、EBX、ECX和EDX):

32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。对低16位数据的存取,不会影响高16位的数据。这些低16位寄存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。

4个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每个寄存器都有自己的名称,可独立存取。程序员可利用数据寄存器的这种“可分可合”的特性,灵活地处理字/字节的信息。

那么如何理解eax,ax,al(ah)之间的关系呢?

专业点可以这样解释:Eax是32位寄存器,ax是16位寄存器,al(ah)是八位寄存器。

那么eax存储的数据就是ax的两倍,ax是al(ah)的两倍。

Eax可以存储的数字是DWORD(双字)ax存储的是WORD(字)AL(AH)存储的是BYTE(字节),那么为什么又有AH和AL呢,我们可以这样理解,AX=AH+AL,AH存储的是AX的高8位数据,AL存储的是AX的低八位数据。H这里就是HIGH,L就是LOW.

假设eax是红色区域,那么eax现在就是64636261;

那么ax就是eax的低十六位,也就是6261;

Al是61;AH是62。

其他ebx,ecx,edx也有类似的bx,bl,bh等对应的寄存器,原理和上面相同。

在用途方面,他们有各自默认的用途:

Eax用来保存所有API函数的返回值。

寄存器AX和AL通常称为累加器(Accumulator),用累加器进行的操作可能需要更少时间。累加器可用于乘、除、输入/输出等操作,它们的使用频率很高;

寄存器BX称为基地址寄存器(Base Register)。它可作为存储器指针来使用;

寄存器CX称为计数寄存器(Count Register)。在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数;

寄存器DX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。

由于存储的数据大小关系,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址, 32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果,而且也可作为指针寄存器,所以,这些32位寄存器更具有通用性。(什么是基址,什么是变址以后会说到)

2个变址和指针寄存器(ESI和EDI)

32位CPU有2个32位通用寄存器ESI和EDI。其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响高16位的数据。

寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register),它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。

变址寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。它们可作一般的存储器指针使用。在字符串操作指令的执行过程中,对它们有特定的要求,而且还具有特殊的功能。

 

2个重要的指针寄存器(ESP和EBP)

这两个指针寄存器都和“栈”这个神秘的东东有关,那么什么是栈呢?这俩指针寄存器又有何作用呢?

从计算机科学的角度看,栈是一种数据结构,是一种先进后出的数据表。栈的最常见操作有两种:Push(入栈)和Pop(出栈)。

我们可以把栈想象成一摞扑克牌:

PUSH:为栈增加一个元素的操作是push,相当于在这摞扑克牌最上面再放一张

POP:从栈中取出一个元素的操作叫做POP,相当于从这摞扑克牌取出最上面的一张。

TOP:标识栈顶位置,并且是动态变化的。每做一次PUSH操作,它都会自增1;

相反,每做一次POP 操作,它会自减1。栈顶元素相当于扑克牌最上面一张,只有

这张牌的花色是当前可以看到的。

BASE:标识栈底位置,它记录着扑克牌最下面一张的位置。BASE 用于防止栈空后继续弹栈(牌发完时就不能再去揭牌了)。很明显,一般情况下,BASE 是不会变动的。

用王爽《汇编语言》中的图说明一下push和pop操作

代码如下:

mov ax,0123H

push ax

mov bx,2266H

push bx

mov cx,1122H

pop ax

pop bx

pop cx

mov是传送数据的指令,mov ax,0123H表明把0123H这个值给ax

H代表0123是十六进制数

mov是传送数据的指令,mov ax,0123H表明把0123H这个值给ax,H代表0123是十六进制数,图中左边的10000H等数值表明内存地址,箭头指向栈顶位置,那么针对此例栈底就是1000FH,栈顶由于入栈和出栈操作在不断变化。那么在这里栈底1000FH就是BP栈顶(不断变化的箭头)就是SP(BP和SP分别是16位下的寄存器,与ebp,esp类似)

内存的栈区实际上指的就是系统栈。系统栈由系统自动维护,它用于实现高级语言中函数的调用。对于类似C 语言这样的高级语言,我们无需担心他们是如何操作的。一般说来,只有在使用汇编语言的时候,才需要和它直接打交道。

那么ESP和EBP指的分别是什么呢?

(1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。

(2)EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。 

需要记住几个要点,记住eax一般用来保存函数的返回值,记住esp是栈顶指针寄存器,ebp是栈底指针寄存器。

下面阅读一段hello world的汇编代码与源码的对照。编译器为vc6。

1:    // hello assemble.cpp : Defines the entry point for the console application.2:    //3:4:    //#include "stdafx.h"5:    #include "stdio.h"6:    int main(int argc, char* argv[])7:    {00401010   push        ebp                         		          //上一个函数的栈基址入栈00401011   mov         ebp,esp                                            //然后将现在的栈顶esp作为main函数调用时的栈底00401013   sub         esp,40h                                            //参考http://bbs.pediy.com/archive/index.php?t-150357.html 分配局部变量空间,vc在debug模式会自动多分配0x40空间,防止意外栈破坏00401016   push        ebx                                                //保护寄存器00401017   push        esi                                                //保护寄存器00401018   push        edi                                                //保护寄存器00401019   lea         edi,[ebp-40h]                                      //局部变量起始地址0040101C   mov         ecx,10h                                            //局部变量字节数00401021   mov         eax,0CCCCCCCCh00401026   rep stos    dword ptr [edi]                                    //使用0xCC填充局部变量,用于判断栈破坏,0xCC对应int 3指令,若不小心跳到栈上执行将触发调试中断8:        printf("Hello World!\n");00401028   push        offset string "Hello World!\n" (0042201c)0040102D   call        printf (00401060)00401032   add         esp,49:        return 0;00401035   xor         eax,eax                                             //异或操作,赋值为零10:   }00401037   pop         edi                                                 //下面就是恢复寄存器,销毁栈帧了00401038   pop         esi00401039   pop         ebx0040103A   add         esp,40h0040103D   cmp         ebp,esp0040103F   call        __chkesp (004010e0)00401044   mov         esp,ebp00401046   pop         ebp00401047   ret

转载地址:http://snopi.baihongyu.com/

你可能感兴趣的文章
DLL中建立进程共享数据段需要注意的语法问题
查看>>
服务器端技术----Http请求的处理过程
查看>>
C语言-预处理指令2-条件编译
查看>>
C语言-预处理指令3-文件包含
查看>>
C语言-变量类型
查看>>
C语言-static和extern关键字1-对函数的作用
查看>>
C 语言-static和extern关键字2-对变量的作用
查看>>
【JavaScript 教程】浏览器—History 对象
查看>>
还不会正则表达式?看这篇!
查看>>
100道+ JavaScript 面试题,助你查漏补缺
查看>>
JavaScript深入理解之闭包
查看>>
这才是学习Vite2的正确姿势!
查看>>
7 个适用于所有前端开发人员的很棒API,你需要了解一下
查看>>
25个构建Web项目的HTML建议,你需要了解一下!
查看>>
【web素材】02-10款大气的购物商城网站模板
查看>>
6种方式实现JavaScript数组扁平化(flat)方法的总结
查看>>
如何实现a===1 && a===2 && a===3返回true?
查看>>
49个在工作中常用且容易遗忘的CSS样式清单整理
查看>>
20种在学习编程的同时也可以在线赚钱的方法
查看>>
隐藏搜索框:CSS 动画正反向序列
查看>>