汇编语言
通用寄存器
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 | 字符串操作的源指针;SS段的数据指针 | 6 | 0 - 0xFFFFFFFF |
EDI | 字符串操作的目标指针;ES段的数据指针 | 7 | 0 - 0xFFFFFFFF |
寄存器 | 编号(二进制) | 编号(十进制) | ||
---|---|---|---|---|
32位 | 16位 | 8位 | ||
EAX | AX | AL | 000 | 0 |
ECX | CX | CL | 001 | 1 |
EDX | DX | DL | 010 | 2 |
EBX | BX | BL | 011 | 3 |
ESP | SP | AH | 100 | 4 |
EBP | BP | CH | 101 | 5 |
ESI | SI | DH | 110 | 6 |
EDI | DI | BH | 111 | 7 |
MOV指令
MOV指令
MOV EXA,0AAAAAAAA
MOV AX,0BBBB
MOV AH,0CC
MOV AL,0DD
这是经过输入MOV指令的内容,接下来按F8一直运行看一看,我把初始的EAX存了AAAAAAAA
这就能够体现EAX,AX,AH,AL的关系,其他的关系同理
MOV的语法
1.MOV r/m8,r/m8 r 通用寄存器
2.MOV r/m16,r/m16 m 代表内存
3.MOV r/m32,r/m32 r8 代表8位通用寄存器
4.MOV r8/,r/m8 m8 代表8位内存
5.MOV r16,r/m16 imm 代表立即数
6.MOV r32,r/m32 imm8 代表8位立即数
7.MOV r8,imm8
8.MOV r16,imm16
9.MOV r32,imm32
MOV 目标操作数,源操作数
作用:拷贝源操作数到目标操作数
1.源操作数可以是立即数、通用寄存器、段寄存器或者内存单元
2.目标操作数可以是通用寄存器、段寄存器或者内存单元
3.操作数的宽度必须一样
4.源操作数和目标操作数不能同时为内存单元
ADD指令
ADD指令相当于加法运算
当我输入MOV EAX,1 时这时候寄存器内为EAX 00000001
下一行我输入ADD EAX,2 时寄存器内变成EAX 00000003
ADD指令语法:
ADD AL,imm8
ADD AX,imm16
ADD EAX,imm32
ADD r/m8,imm8
ADD r/m16,imm16
ADD r/m32,imm32
ADD r/m16,imm8
ADD r/m32,imm16
ADD r/m8,r8
ADD r/m16,r16
ADD r/m32,r32
ADD r8,r/m8
ADD r16,r/m16
ADD r32,r/m32
SUB指令
SUB指令相当于减法
在上ADD指令后再加上SUB EAX,2 寄存器内就变成了EAX 00000001
SUB指令跟ADD指令格式一样就把ADD换成SUB其他的都不变,为了简便在这里就不写了。
AND,OR,XOR,NOT指令
AND的指令就是与运算,相同位的两个数字都为1,则为1;若有一个不为1,则为0。
举个例子: 2 and 3 (下面的都是二进制数)
0010
0011
——
0010
运行过后结果还是00000002,是因为2and3就是2所以显示的就是00000002
OR,XOR,NOT指令和AND指令运算不同,AND,OR,XOR的指令语法都和ADD相同,NOT指令语法不一样
NOT指令语法:
NOT r/m8
NOT r/m16
NOT r/m32
内存
寄存器与内存
寄存器与内存的区别:
1.寄存器位于CPU内部,执行速度快,但比较贵
2.内存速度相对较慢,但成本较低,所以可以做的很大
3.寄存器和内存没有本质的区别,都是用于存储数据的容器,都是定宽的
4.寄存器常用的有8个,EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI
5.计算机中的几个常用计量单位,BYTE,WORD,DWORD
BYTE 字节 = 8(BIT)
WORD 字 = 16(BIT)
DWORD 双字 = 32(BIT)
1KB = 1024 BYTE
1MB = 1024KB
1GB = 1024MB
6.内存的数量特别庞大,无法每个内存单元都起一个名字,所以用编号来代替,我们称计算机CPU是32位后者是64位,有很多书上说之所以叫32位计算机是因为寄存器的宽度是32位,是不准确的,因为还有很多寄存器是大于32位的,32位计算机是指寻址编位32位。
计算机内存的每一个字节会有一个编号(即内存编号的单位是字节)(下图为16进制)
0x00000000
0x00000001
0x00000002
······
······
0xFFFFFFFF
32位计算机的编号最大是32位,也就是32个1,换成16进制为FFFFFFFF,也就是说32位计算机内存寻址的最大范围是0~FFFFFFFF内存的单位是字节,那内存中能存储的信息最多为FFFFFFFF+1字节,即4G
7.只要是32位的计算机,最多识别的内存不一定是4G,内存是可以物理扩展的
内存
1.内存格式
计算机中为了区别立即数和内存编号一般加中括号为内存编号即[0x12345678]为内存编号而0x87654321为立即数
2.从指定内存中写入/读取数据
mov dword ptr ds:[0x0812FF34],0x12345678
mov eax,dword ptr ds:[0x0012FF34]
dword(32位):要读/写多少 此时是4字节 byte == 1字节 word == 2字节
ptr:Point代表后面是一个指针(指针的意思就是里面存的不是普通的值,而是个地址)
ds:段寄存器
0x0012FF34:内存编号,必须是32位的,前面0可以省略
注意:地址编号不要随便写,因为内存是有保护的,并不是所有的内存都可以直接读写(需要特别处理)
建议地址编号写成esp
写入数据:
这是原本[0x0019FF74]编号地址对应的值为763AFA29,接下来用mov dword ptr ps:[0x0019FF74],0x12345678改一下
这时0x0019FF74里面对应的值变为12345678
读取数据:
把地址0x0019FF7C内容读取到EAX中,EAX的值为0019FFCC
写入指令:mov eax,dword ptr ds;[0x19FF7C](0可以省略)
运行后EAX对应的值就变成0x0019FF7C里面的值
3.寻址
寻址公式一:[立即数]
读取内存的值:
MOV EAX,DWORD PTR DS:[0x13FFC4]
MOV EAX,DWORD PTR DS:[0x13FFC8]
向内存中写入数据:
MOV DWORD PTR DS:[0x13FFC4],EAX
MOV DWORD PTR DS:[0x13FFC8],EAX
获取内存编号:
LEA EAX,DWORD PTR DS:[0x13FFC4]
LEA EAX,DWORD PTR DS:[ESP+8]
这是原始的EAX和ESP的值,运用上面两个公式
第一个获得了内存编号
ESP原本值是0019FF74再加上8就是0019FF7C
寻址公式二:[reg] reg代表寄存器,可以是8个通用寄存器的任意一个
读取内存的值:
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:[BCX+4]
向内存中写入数据:
MOV EDX,0x13FFD0
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,DWOED PTR DS:[EAX+ECX*4+4]
向内存中写入数据:
MOV EAX,13FFC4
MOV ECX,2
MOV DWOED PTR DS:[EAX+ECX*4+4],87654321
获取内存编号:
LEA EAX,DWORD PTR DS:[EAX+ECX*4+2]
如果最后存入的数据溢出将取最大范围