计算机能识别的语言是机器语言,即0和1组成的指令,如0001,0111等,这种指令对于我们而言是不可读的,但是它与可编程语言(汇编语言)是一一对应的,每个汇编指令唯一对应于一条机器指令,而且汇编语言对应我们而言是可读的,这样我们从汇编入手,理解系统内核,明白高级语言代码的本质。
高级语言运行的流程一般是:
汇编语言可以通过编译得到机器语言,机器语言可以通过反汇编得到汇编语言
高级语言可以通过编译得到汇编语言 \ 机器语言,但汇编语言\机器语言几乎不可能还原成高级语言
汇编语言有 : 8086汇编,win32位汇编,win64汇编,ARM汇编
建议从8086汇编开始学习,从简单入手,再逐步深入。
首先我们需要简单了解一些CPU等硬件结构:
1. 总线:
定义:一根根导线的集合
分类:
(1)地址总线:
- 它的宽度决定了CPU的寻址能力
- 8086的地址总线宽度是20,所以寻址能力是1M( 2^20 ),
解析:每根线可以传0和1,2根线有 00/01/10/11四种组合,即2*2=2^2=4;那么n根线的寻址能力就是2^n
(2)数据总线
- 它的宽度决定了CPU的单次数据传送量,也就是数据传送速度
- 8086的数据总线宽度是16,所以单次最大传递2个字节(16bit)的数据,每根一个bit
(3)控制总线
- 它的宽度决定了CPU对其他器件的控制能力、能有多少种控制
2. 内存
内存地址空间的大小受CPU地址总线宽度的限制。
8086的地址总线宽度为20,可以定位2^20个不同的内存单元(内存地址范围0x00000~0xFFFFF),所以8086的内存空间大小为1MB
0x00000~0x9FFFF:主存储器。可读可写
0xA0000~0xBFFFF:向显存中写入数据,这些数据会被显卡输出到显示器。可读可写
0xC0000~0xFFFFF:存储各种硬件\系统信息。只读
3. 寄存器
我们可以通过修改寄存器的内容,达到对 CPU的控制;不同的结构 CPU 中的寄存器的个数、结构是不相同的
8086是16位结构CPU,其包含14个寄存器
其中,AX,BX,CX,DX为通用寄存器,用来存放一般性的数据,其可以分为高8位和低8位,如上图所示,AH为高8位,AL位低8位,其他类似。
4. 段寄存器:
因为8086的寻址方式为 段地址 * 16 + 偏移地址 (==实际的物理地址),下面我们介绍下段寄存器
CS (Code Segment):代码段寄存器
DS (Data Segment):数据段寄存器
SS (Stack Segment):堆栈段寄存器
ES (Extra Segment):附加段寄存器
(1)CS 和 IP
- CS为代码段寄存器,IP为指令指针寄存器,它们指示了CPU当前要读取指令的地址
- 任意时刻,8086CPU都会将CS:IP指向的指令作为下一条需要取出执行的指令
下面介绍一下流程:
jmp指令
CPU从何处执行指令是由CS、IP中的内容决定的,我们可以通过改变CS、IP的内容来控制CPU执行目标指令
8086提供了一个mov指令(传送指令),可以用来修改大部分寄存器的值,比如: mov ax,10、mov bx,20、mov cx,30、mov dx,40
但是,mov指令不能用于设置CS、IP的值,8086没有提供这样的功能
mov指令
add 和 sub 指令
下面我们写一个基本的汇编:
求 1133h 和 5566h 的 和
assume cs : code ;定义code为代码段
code segment
mov ax , 1133H ; ax初始值
mov bx , 5566H ; bx初始化
add ax, bx ; 将ax和bx相加,并且值存入ax中 (ax = ax + bx)
;退出程序
mov ah, 4ch
int 21h
code ends
end
segment和ends的作用是定义一个段,segment代表一个段的开始,ends代表一个段的结束,使用格式为:
段名 segment
:
段名 ends
* 一个有意义的汇编程序中,至少要有一个段作为代码段存放代码
* assume
* 将用作代码段的code段和CPU中的cs寄存器关联起来
* end
* 编译器遇到end时,就结束对源程序的编译
* 下面2句代码的作用是退出程序
mov ah,4ch
int 21h
* 也可以写成
mov ax, 4c00h
int 21h
参考:
https://www.jianshu.com/u/fa45480a8444 汇编篇