80x86汇编3-寄存器与内存
寄存器是什么?
通俗来讲,寄存是CPU内部的一块高速存储空间,速度远大于内存
32位通用寄存器
寄存器 | 主要用途 | 编号 | 存储数据的范围 |
---|---|---|---|
EAX | 累加器 | 0 | 0-0xFFFFFFFF |
ECX | 计数器 | 1 | 0-0xFFFFFFFF |
EDX | I/o指针 | 2 | 0-0xFFFFFFFF |
EBX | DS段的数据指针 | 3 | 0-0xFFFFFFFF |
ESP | 堆栈指针 | 4 | 0-0xFFFFFFFF |
EBP | SS段的数据指针 | 5 | 0-0xFFFFFFFF |
ESI | 字符串操作源指针 | 6 | 0-0xFFFFFFFF |
EDI | 字符串操作的目标指针 | 7 | 0-0xFFFFFFFF |
32位 通用寄存器由8位寄存器开始演变,一个32位寄存器包含了16位和8位
EAX其实是AX16位通用寄存器扩展而来,同理RAX64位通用寄存器也是由32位通用寄存器扩展而来!
基础汇编指令
MOV(移动)
MOV EAX,AAAAAAAA
MOV AX,1111
MOV ECX,33
MOV CX,3
…
MOV的语法:
MOV 目标操作数,源操作数
作用:拷贝源操作数到目标操作数
·1、源操作数可以是立即数、通用寄存器、段寄存器、或者内存单元.
·2、目标操作数可以是通用寄存器、段寄存器或者内存单元.
·3、操作数的宽度必须一样.
·4、源操作数和目标操作数不能同时为内存单元.
不是很了解不要紧,只需要记住一般情况下使用
MOV EAX,0x11111111 //把一个4字节的数字放到32/16/8位通用寄存器里
MOV EAX,[0x401050] //把内存中的数据放到32/16/8位通用寄存器里
·
ADD(加法)
加法指令不同于移动指令(MOV),加法指令可以把一个数据累加到内存中ADD EAX,12345678 //把EAX寄存器里面存储的内容与12345678相加,然后存到EAX,例如EAX是1,ADD加完以后EAX就是12345679
ADD [0x401050],12345678 //把数字和内存中的数据相加然后存回内存,同理EAX
!!ADD不可以两个数字相加,数字在汇编中被称为立即数,数字本身并没有存储内容的功能
- SUB(相减)
rep指令(大多数用于填充堆栈)
lea edi,[ebp-40]
mov ecx,0x10
mov eax,0xcccccccc
rep stos dword ptr[edi]
结论:rep会读取edi的地址,根据df标志位判断方向,根据ecx判断剩余次数,根据eax得到需要填充的值,再根据dword的宽度填充堆栈内存[edi],默认df=1,然后ecx-1,edi-dword
- movzx和movsx
MOVSX,MOVZX 与MOV指令区别:
1、MOVSX,MOVZX的操作数B所占空间必须小于操作数A.
2、MOV指令是原值传送,不会改动。而MOVSX与MOVZX有可能会改动
MOVSX与MOVZX的区别:
1、MOVSX将用操作数B的符号位扩展填充操作数A的余下空间,如果是负数则符号位为1,如果是正数则和MOVZX功能相同
2、MOVZX将用0来扩展填充操作数A的余下空间
__asm
{
mov bl,80
movzx ax,bl
}//0x0080
__asm
{
mov bl, 80
movsx ax, bl
}//0xFF80
内存
内存是我们最常用是存储数据的载体!它位于我们计算机的主板,但是主板上的内存条并不是我们实际使用的内存空间,我们使用的内存空间都是由操作系统分配和回收的虚拟内存!
寄存器与内存的区别:
- 寄存器位于CPU内部,执行速度快,但比较贵
- 内存速度相对较慢,但成本较低,所以可以做的很大
- 寄存器和内存没有本质区别,都是用于存储数据的容器,都是定宽的
- 寄存器常用的有8个:EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI
- 计算机中的几个常用计量单位:BYTE WORD DWORD
BYTE 字节 = 8(BIT)
WORD 字 = 16(BIT)
DWORD 双字 = 32(BIT)
1KB = 1024 BYTE
1MB = 1024 KB
1MB = 1024 KB
- 内存的数量特别庞大,无法每个内存单元都起一个名字,所以用编号来代替,我们称计算机CPU是32位或者64位,主要指的就是内存编号的宽度,而不是寄存器的宽度.有很多书上说之所以叫32位计算机是因为寄存器的宽度是32位,是不准确的,因为还有很多寄存器是大于32位的
计算机内存的每一个字节会有一个编号(即内存编号的单位是字节)
0x00000000 | 0x00000001 | 0x00000002 | 0x00000003 | 0x00000004 | 0x00000005 | … |
---|---|---|---|---|---|---|
00000000 | 00000001 | 00000002 | 00000003 | 00000004 | 00000005 | … |
32位计算机的编号最大是32位,也就是32个1 换成16进制为FFFFFFFF,也就是说,32位计算机内存寻址的最大范围是FFFFFFFF+1
内存的单位是字节,那内存中能存储的信息最多为:FFFFFFFF+1 字节 即4G,这也是为什么我们在一个XP的系统上面如果物理内存超过4G是没有意义的原因
内存的格式
1、每个内存单元的宽度为8(8个16进制数,4字节,32个2进制数)
2、[编号]称为地址
3、地址的作用:当我们想从内存中读取数据或者想向内存中写入数据,首先应该找到要读、写的位置。就像写信要写地址一样。
从指定的内存中读写数据:
mov dword ptr ds:[0x0012FF34],0x12345678
mov eax,dword ptr ds:[0x0012FF34]
dword :要读/写多少 此时是4字节 byte == 1字节 word == 2字节
ptr: Point 代表后面是一个指针 (指针的意思就是里面存的不是普通的值,而是个地址)
ds:段寄存器
0x0012FF34:内存编号,必须是32位的 前面0可以省略
注意:地址编号不要随便写,因为内存是有保护的,并不是所有的内存都可以直接读写(需要特别处理)
为什么需要dword?因为寄存器是定宽的,4字节的,如果是内存的话,可以存很多数据,如果不告诉系统你要操作是数据有多宽,就会出问题
汇编寻址公式:
.
立即数
读取内存的值:
MOV EAX,DWORD PTR DS:[0x13FFC4]
MOV EAX,DWORD PTR DS:[0x13FFC8]向内存中写入数据:
MOV DWORD PTR DS:[0x13FFC4],eax
MOV DWORD PTR DS:[0x13FFC8],ebx获取内存编号:
LEA EAX,DWORD PTR DS:[0X13FFC4]
LEA EAX,DWORD PTR DS:[ESP+8]
.
REG(通用寄存器)
读取内存的值:
MOV ECX,0x13FFD0
MOV EAX,DWORD PTR DS:[ECX]向内存中写入数据:
MOV EDX,0x13FFD8
MOV DWORD PTR DS:[EDX],0x87654321获取内存编号:
LEA EAX,DWORD PTR DS:[EDX]
MOV EAX,DWORD PTR DS:[EDX]
.
REG(通用寄存器)+立即数
读取内存的值:
MOV ECX,0x13FFD0
MOV EAX,DWORD PTR DS:[ECX+4]向内存中写入数据:
MOV EDX,0x13FFD8
MOV DWORD PTR DS:[EDX+0xC],0x87654321获取内存编号:
LEA EAX,DWORD PTR DS:[EDX+4]
MOV EAX,DWORD PTR DS:[EDX+4]
.
REG(通用寄存器)+REG*{1,2,4,8}
读取内存的值:
MOV EAX,13FFC4
MOV ECX,2
MOV EDX,DWORD PTR DS:[EAX+ECX*4]向内存中写入数据:
MOV EAX,13FFC4
MOV ECX,2
MOV DWORD PTR DS:[EAX+ECX*4],87654321获取内存编号:
LEA EAX,DWORD PTR DS:[EAX+ECX*4]
.
REG(通用寄存器)+REG*{1,2,4,8}+立即数
读取内存的值:
MOV EAX,13FFC4
MOV ECX,2
MOV EDX,DWORD PTR DS:[EAX+ECX*4+4]向内存中写入数据:
MOV EAX,13FFC4
MOV ECX,2
MOV DWORD PTR DS:[EAX+ECX*4+4],87654321获取内存编号:
LEA EAX,DWORD PTR DS:[EAX+ECX*4+4]
还没有评论,来说两句吧...