1.汇编语言简介和发开环境搭建

汇编语言介绍

编辑-弄成汇编程序-连接程序-调试程序

1
masm一下 -> link一下 -> debug一下
1
2
编程 -> .asm -> 编译 -> .obj -> 链接 -> .exe -> 加载 -> 内存中的程序 -> 运⾏
(edit) (masm) (link) (command) (CPU)

这里需要下载一个masm 的一个集成环境【在虚拟机里面搞】

image-20230505134948035

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
;完整段的Hello World程序
DATAS SEGMENT
STRING DB 'Hello World!',13,10,'$'
DATAS ENDS

CODES SEGMENT ;codes
ASSUME CS:CODES,DS:DATAS
START:
MOV AX,DATAS
MOV DS,AX ;让ds 和 datas相互关联
LEA DX,STRING ;调用字符串开始地址
MOV AH,9 ;
INT 21H ;调用dos系统中断中的9号功能:显示字符串

MOV AH,4CH
INT 21H ;调用dos系统4cH号功能:结束程序
CODES ENDS
END START

这个代码应该看得懂三。【只要你看过8086汇编】

2.寄存器-x64和x86寄存器传参方式

80X86计算机组织基础知识

计算机主要是由于CPU【运算器和控制器】,存储器,输入输出设备构成

80X86寄存器组

通用寄存器——AX,BX,CX,DX,SP,BP,DI,SI八个通用寄存器【用于8086,8088】

1
其实去看过8086汇编的也知道,具体咋使用的可以去看看

AX,BX,CX,DX可称为数据寄存器用来暂时存放寄存器过程中所得到的操作数,结果,其他信息。可以裁分为AH,AL来访问【16为->8位】

  • AX(accumulator)主要作为累加器使用,用于算数运算
  • BX(base)主要用作存储器的地址的时候,用作基地址寄存器
  • CX(count)用来存放数据,循环次数啥的
  • DX(data)用于32位数据的高16位

SP,BP,SI,DI主要用于偏移地址,也就是指针或者变址寄存器。不能拆分来访问

  • SP(stack pointer)堆栈指针寄存器,用来指向栈顶的偏移地址
  • BP(base pointer)基地址指针寄存器
  • SI(source index)原先的地址寄存器,确定某一个存储单元
  • DI(destination index)目的变地址寄存器。【和SI不同的就是SI是原先的,DI是目的的地方。比如copy一段东西,SI指向要copy内容的地址,DI指向的是要copy到哪里的地址】

专用寄存器IP,SP,FLAGS【OF,SF,ZF,CF,AF,PF…】

  • IP(instruction pointer)代码段的偏移地址,会自动加
  • SP 堆栈指针寄存器,堆栈栈顶地址,始终指向栈顶
  • FLAGS 标志寄存器,里面存放的是一些标志

6个条件标志用来记录运行结果状态的信息,是CPU自己根据运算操作来设置的

  • OF(overflow flag)为溢出标志。在运算过程中,操作数超出了机器能表示的范围称为溢出,此时OF位置为1,否则置为0.【无符号数】
  • SF(sign flag)为符号标志。记录运算结果的符号,结果为负时置为1,否则置为0。
  • ZF(zero flag)为零标志。运算结果为0时置为1,否则置为0。
  • CF(carry flag)为进位标志。记录运算时从最⾼有效位产⽣的进位值。例如,执⾏加法指令时,最⾼有效位有进位时置为1,否则置为0。
  • AF(auxiliary carry flag)为辅助进位标志。记录运算时第3位(半个字节)产⽣的进位值。进位时置为1,否则置为0。【有符号数】
  • PF(parity flag)为奇偶标志。当结果操作数中1的个数为偶数时置为1,否则置为0

段寄存器——CS,DS,SS,ES

  • CS 代码段
  • DS 数据段
  • SS 堆栈段
  • ES 没啥用段,多出来用的

3.内存存储方式

内存访问

win32 :windows骗了每一个程序都有4GB的独立空间,其实没有啦

32位的内存地址,也就是可寻址的空间是4GB啦【一个内存单元是8位啦】

8x2^32 (位)

8x2^32 / 8 / 1024 / 1024 / 1024 = 4G

mov 向内存中添加数据或者获取数据

1
2
3
mov dword ptr ds:[内存地址],立即数
mov dword ptr ds:[内存地址],32位通用寄存器
mov 32位通用寄存器,dword ptr ds:[内存地址]

要注意的是:前后俩个的数据的宽度要一致哦
这些在汇编基础里面都有讲过,这里在回顾一下和总结一下

内存地址的5种形式

  • 立即数
1
2
3
4
读:
mov eax,dword ptr ds:[0x13ffc4]
写:
mov dword ptr ds:[0x13ffc4]
  • [寄存器]
1
2
3
4
5
6
读:
mov ecx,0x13ffd0
mov eax,dword ptr ds:[ecx]
写:
mov edx,0x13ffd8
mov dword ptr ds:[edx],0x8765431
  • [寄存器+立即数]
1
2
3
4
5
6
读:
mov ecx,0x13ffd0
mov eax,dword ptr ds:[ecx+1]
写:
mov edx,0x13ffd8
mov dword ptr ds:[edx+1],0x8765431
  • 寄存器+寄存器*{1,2,4,8}
1
2
3
4
5
6
7
8
读:
mov eax, 0x13FFC4
mov ecx, 0x2
mov edx, dword ptr ds:[eax+eax*4]
写:
mov eax, 0x13FFC4
mov ecx, 0x2
mov dword ptr ds:[eax+eax*4], 0x87654321
  • 寄存器+寄存器*{1,2,4,8}+立即数
1
2
3
4
5
6
7
读:
mov eax, 0x13FFC4 mov ecx, 0x2
mov edx, dword ptr ds:[eax+eax*4+4]
写:
mov eax, 0x13FFC4
mov ecx, 0x2
mov dword ptr ds:[eax+eax*4+4], 0x87654321
  • 注意:在读和写的时候前后俩个的宽度要一样

4.存储模式

存储模式【大,小端】

大端模式:数据高位放在低地址中,数据低位放在高地址中

小段模式:数据低位放在低位地址中,数据高位放在高位地址中

比如:mov word ptr ds:[0x000000000],0x1A2B

大端存储: 0x00000000 => 1A 0x00000001 => 2B

小端存储: 0x00000000 => 2B 0x00000001 => 1A

其实这里就是要小心数据存储的时候去读取数据的时候读的数据内容

mov word ptr ds:[0x0012ffc4], 0x1A2B

image-20230505210357578

存储器的管理模式

80x86系列:也就是内存分段管理,分成若干个段。每一个段的起点用一个段寄存器…

存储器的分段含义,存储单元的逻辑地址和物理地址之间的转换关系

:也就是我们在汇编入门中所说的“血汗工厂”

16位的CPU 访问20根地址线【1M】的存储空间

存储单元的逻辑地址分为:段地址和偏移量。

1
物理地址=段地址x16 + 偏移量

段寄存器的引用

代码段:CS:IP

数据段:DS:BX DS:SI

附加段:ES:BX ES:DI

堆栈段:SS:SP SS:BP


访问存储器⽅式 缺省的段寄存器 可选⽤的段寄存器 偏移量

取指令 CS IP

堆栈操作 SS SP

⼀般取操作数 DS CS、ES、SS 有效地址

串操作 源操作数 DS CS、ES、SS SI

⽬标操作数 ES DI

使⽤指针寄存器 BP SS CS、DS、ES 有效地址


在内存单元中读取数据的时候一定要注意读取方式哦【我现在遇到的都是小端读取】