前言
今天还是很无聊的一节,因为之前早就学过这方面的知识,还是带大家了解一下 DTDdebug 以及 ollydebug 咋用,这俩用法以及界面都是很相似的,但调一些 C 语言写的程序的时候,个人还是比较喜欢内置的那个调试的快捷键,带大家加深一下数据宽度的概念,看完之后,应该就能深刻的理解为什么要有数据宽度这个概念了
课堂
32 位通用寄存器
-
程序在计算的时候,需要用到数据,那么这些数据都需要地方来存储,寄存器和内存就是用来存储数据的容器
-
计算机用来存储数据的有 CPU 中的寄存器和内存条中的内存。CPU 中的寄存器虽然容量小,但是可以高速进行读写;内存虽然存取速度相对较慢一些,但是可以存储大量的内容
-
我们今天学习的是 CPU 中常用到的数据宽度为 32 位的容器,称为 32 位通用寄存器
什么是 32 位,就是下面的寄存器可以用 32 位来存储数据,通俗来说就是一个寄存器可以用 32 个 0 或者 1 来存数据。虽然当初设计时不同的寄存器建议存什么东西做什么运算,但是实际上自己想怎么用寄存器就怎么用,知道有哪些寄存器即可,明确一点昂,这个寄存器可和那个说的多少多少架构的操作系统没关系,那个还是看的是寻址能力,和地址总线的宽度有关
通用寄存器
寄存器不光是只有 32 位的,还有 8 位,16 位,64 位的寄存器,这样统称为通用寄存器,那有人问为什么还有 8 位的呢,这就和历史原因有关系,都是不断发展的,一开始 16 位的计算机,只有 AX,哪有 EAX 的概念,那计算机不断发展了,也不能舍弃原来的,所以就保留了,反正没有什么坏处,而且某些情况下使得操作数据更加的灵活
-
我们根据需要的大小来挑选合适宽度的寄存器,只要能够存下需使用的数据即可
-
16 位寄存器在 32 位寄存器中,16 位寄存器是 32 位寄存器的一部分。可以这么理解,32 位寄存器的前半部分为 16 位寄存器;前四个 16 位寄存器(ax,cx,dx,bx)又可以分为两个 8 位寄存器
这个是海东老师给的代码演示,大家可以去试试
汇编指令
MOV
-
格式:
mov eax,0xAAAAAAAA
指令中 mov 叫操作码,eax 叫目标操作数,0xAAAAAAAA 叫源操作数。 -
作用:mov 指令就是将源操作数复制一份放到目标操作数!
-
要求:
-
源操作数宽度必须和目标操作数宽度一致:这个有人说如果原操作数是一个立即数呢,这个要不要显式的去指出这个立即数的宽度呢,可以但是没有必要,因为计算机会隐式的去转换,比如 mov eax,1 那就是 32 位的 1,mov ax,1 那就是 16 的 1
-
即 eax 为 32 位寄存器,那么只能将 32 位的源操作数存入 eax 中,如果少了会在高位自动补零,如果多了,则会从低位取 32 位,后面多余部分会被丢弃
-
源操作数可以是立即数、通用寄存器、段寄存器(后面会讲)、或者内存单元
-
目标操作数可以是通用寄存器、段寄存器或者内存单元
-
源操作数和目标操作数不能同时为内存单元(很多汇编程序都不允许,但有特例),这个在之后的某个指令会说到,但是本质还是不能直接操作两块内存,因为内存与内存之间是没有线相连的
-
-
语法:r 通用寄存器;m 代表内存;imm 代表立即数;r8 代表 8 位通用寄存器;m8 代表 8 位内存;imm8 代表 8 位立即数
MOV r8/m8,r8 #可以将8位通用寄存器中的值存入8位通用寄存器或者8位内存中
MOV r16/m16,r16
MOV r32/m32,r32
MOV r8,r8/m8 #可以将8位通用寄存器或者8位内存中的值存入8位寄存器中
MOV r16,r16/m16
MOV r32,r32/m32
MOV r8,imm8 #将一个8位的立即数存入8位通用寄存器中
MOV r16,imm16
MOV r32,imm32
ADD
-
格式:与 mov 类似,有操作码,目标操作数和源操作数构成
-
作用:将目标操作数与源操作数相加,将结果存入到目标操作数
-
要求:
-
源操作数宽度可以和目标操作数宽度不一致!(只能源操作数为立即数时可以不一样)
-
源操作数可以是立即数、通用寄存器、段寄存器(后面会讲)、或者内存单元
-
目标操作数可以是通用寄存器、段寄存器或者内存单元
-
源操作数和目标操作数不能同时为内存单元
-
-
语法:
ADD r8/m8,imm8
ADD r16/m16,imm16
ADD r32/m32,imm32
ADD r16/m16,imm8 #源操作数与目标操作数可以不一致!!
ADD r32/m32,imm8
ADD r8/m8,r8
ADD r16/m16,r16
ADD r32/m32,r32
ADD r8,r8/m8
ADD r16,r16/m16
ADD r32,r32/m32
SUB
-
格式:操作码 目标操作数,源操作数
-
作用:将目标操作数减源操作数的结果存入目标操作数
-
误解:可能大家认为,这个 sub 和 add 是一样的,就像经常所说的,减一个数相当于加一个数的相反数,但是这点在计算机里面是行不通的,尤其在 JCC 那里会体现的很明显,之后再说吧
-
语法:
SUB AL, imm8
SUB AX, imm16
SUB EAX, imm32
SUB r/m8, imm8
SUB r/m16,imm16
SUB r/m32,imm32
SUB r/m16, imm8
SUB r/m32, imm8
SUB r/m8, r8
SUB r/m16, r16
SUB r/m32, r32
SUB r8, r/m8
SUB r16, r/m16
SUB r32, r/m32
AND
-
格式:操作码 目标操作数,源操作数
-
作用:目标操作数与源操作数做与逻辑运算,将结果存入目标操作数
-
要求:
-
源操作数和目标操作数不能同时为内存单元
-
源操作数宽度可以和目标操作数宽度不一致!
-
-
语法:
AND r8/m8, imm8
AND r16/m16,imm16
AND r32/m32,imm32
AND r16/m16, imm8
AND r32/m32, imm8
AND r8/m8, r8
AND r16/m16, r16
AND r32/m32, r32
AND r8, r8/m8
AND r16, r16/m16
AND r32, r32/m32
OR
-
作用:目标操作数与源操作数做或逻辑运算,将结果存入目标操作数
-
语法:
OR r8/m8, imm8
OR r16/m16,imm16
OR r32/m32,imm32
OR r16/m16, imm8
OR r32/m32, imm8
OR r8/m8, r8
OR r16/m16, r16
OR r32/m32, r32
OR r8, r8/m8
OR r16, r16/m16
OR r32, r32/m32
XOR
-
作用:目标操作数与源操作数做亦或逻辑运算,将结果存入目标操作数(后面加密解密时经常使用)
-
语法:
XOR r8/m8, imm8
XOR r16/m16,imm16
XOR r32/m32,imm32
XOR r16/m16, imm8
XOR r32/m32, imm8
XOR r8/m8, r8
XOR r16/m16, r16
XOR r32/m32, r32
XOR r8, r8/m8
XOR r16, r16/m16
XOR r32, r32/m32
NOT
-
格式:操作码 操作数(只有一个操作数)
-
作用:操作数做非逻辑运算,将结果存入操作数中
-
语法:
NOT r8/m8 NOT r16/m16 NOT r32/m32
NOT r8/m8
NOT r16/m16
NOT r32/m32
作业
- 使用 OD 打开一个 EXE 程序,并找到寄存器窗口
- 单步执行程序(F8)
因为一个可执行程序打开会发现它停在了一个地址处,至于为什么后面学汇编详解,这里我们只需知道 EIP 寄存器中的存的值是什么,此时程序就执行到哪了,反过来说也可以。那么我们如果按 F8,则会从现在停在的地址,单步往后执行一条指令
-
记住这个 8 个通用寄存器的名称,按照顺序:EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI
-
如何自己写汇编指令,在左上角的框框里,双击程序正在执行的地址那一行的指令,可以新添加指令或者修改指令,最后按 Assemble 添加或修改成功。添加或修改后,这条指令会作为程序即将执行的指令,当按 f8 时,程序会执行你新添加的指令,添加多条,会依次向下覆盖,程序执行处在第一条你新添加的指令地址处
剩下的就自己上手试试吧,奥里给