汇编学习—学习书籍《汇编语言》(第四版)清华大学出版社 王爽 著

汇编语言是人和计算机沟通的最直接的方式,它描述了机器最终所要执行的指令序列。


基础知识

汇编语言产生与组成

每一种微处理器(cpu),由于硬件设计和内部结构的不同,就需要用不同的电平脉冲来控制,使它工作。所以每一种微处理器都有自己的机器指令集,也就是机器语言。

早期的机器语言是用0,1表示。1打孔,0不打孔。但这样过于繁琐,因此产生了汇编语言

汇编语言的主体是汇编指令。与机器指令的最大区别在于指令的表示方法。

1
2
3
操作:寄存器BX的内容送到AX中
机器指令:1000100111011000
汇编指令: mov,ax,bx

因为计算机只能读懂机器指令,因此程序员用汇编指令编写完源程序后,还需要用编译器将其编译为机器码,最后再给计算机执行。程序员→汇编指令→源程序→编译器→机器码→计算机

汇编语言组成:

1
2
3
汇编指令:机器码的助记符,有对应的机器码  (核心)
伪指令:没有对应的机器码,由编译器执行,计算机不执行
其他符号:如+、-、*、/,由编译器识别,没有对应的机器码

CPU对存储器的读写

1
2
3
存储单元的地址(地址信息,地址总线,N根地址线,可寻找2的N次方内存单元,其宽度决定CPU寻址能力)
器件的选择,读或写的命令(控制信息,控制总线,其宽度决定了CPU对外部器件的控制能力)
读或写的数据(数据信息,数据总线,其宽度决定cpu和外界的数据传送速度)
1
2
3
操作:传送3号单元的内容入AX
机器指令:10100001 00000011 00000000
汇编指令:MOV AX,[3]

存储器芯片

从读写属性分:RAM(随机存储器)、ROM(只读存储器)

从存储器的功能和连接分:

  • RAM用于存放CPU使用的绝大部分程序和数据,主存储器由装在主板上的RAM和插在扩展插槽上的RAM组成。
  • 装有BIOS(basic input output system)的ROM
  • 接口卡上的RAM,如显示卡上的RAM,即显存,将需要显示的内容写入显存,就会出现在显示器上。

内存地址空间

汇编中,面对的是内存地址空间

CPU在操控存储器的时候,把它们都当做内存对待,把它们总的看做一个由若干个存储单元组成的逻辑存储器,即内存地址空间。CPU在地址空间中读写数据,实际上就是在相对应的物理存储器中读写数据

1
2
3
0~9FFFF->主随机存储器RAM
A0000~BFFFF->显存中写入数据,并被显示卡输出到显示器上
C0000~FFFFF->无效的写入数据,在ROM中无法改写

寄存器

寄存器是CPU中程序员可以用指令读写的部件,程序员通过改变各种寄存器中的内容来实现对CPU的控制。

通用寄存器:AX,BX,CX,DX,用来存放一般性数据

8086CPU是16位的,为了保证兼容,将寄存器分为两个可独立使用的8位寄存器AH和AL,AL是低8位,AH是高8位。

几条汇编指令

汇编指令 控制CPU完成的操作 用高级语言的语法描述
mov ax,18 将18送入寄存器AX AX=18
mov ah,78 将78送入寄存器AH AH=78
add ax,8 将寄存器AX中的数值加上8 AX=AX+8
mov ax,bx 将寄存器BX中的数据送入寄存器AX AX=BX
add ax,bx 将AX和BX中的数值相加,结果存在AX中 AX=AX+BX

在写汇编指令或一个寄存器的名称时不区分大小写

注意:1、ax为16位寄存器,只能存放4位十六进制的数据,若有5位数据,则舍去最高位

​ 2、在进行数据传送或运算时,指令的两个操作对象的位数应当是一致的

1
2
3
4
5
6
7
mov ax,bx
mov ax,18H
mov al,18H
而:
mov ax,bl
mov bh,ax
等都是错误的指令

物理地址

CPU访问内存单元时,要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有唯一的地址,将这个唯一的地址称为物理地址。

CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址。在CPU向地址总线上发出物理地址之前,必须在内部先形成这个物理地址。不同的CPU可以有不同的形成物理地址的方式。

8086CPU是16位机,那什么是16位结构的CPU呢?

  • 运算器一次最多可以处理16位的数据
  • 寄存器的最大宽度为16位
  • 寄存器和运算器之间的通路为16位

也就是在8086CPU中,能够一次性处理、传输、暂时存储的信息的最大长度是16位。但它有20位地址总线,因此在内部用两个16位地址合成的方法来形成一个20位的物理地址。两个16位的地址,分别是段地址和偏移地址

  • 两个16位地址通过内部总线→地址加法器→形成20位的物理地址→通过内部总线送入输入输出控制电路→把20位物理地址送入地址总线→存储器

其中,地址加法器采用物理地址=段地址*16+偏移地址的方法合成。

段地址

其实,内存并没有分段,段的划分来自于CPU。由于物理地址=基础地址(段地址*16)+偏移地址,使得我们可以用分段的方式来管理内存。我们可以认为:地址10000H~100FFH的内存单元组成一个段,该段的起始地址为10000H,段地址为1000H,大小为100H

段地址*16必然是16的倍数,所以一个段的起始地址一定是16的倍数,偏移地址为16位,16位的寻址能力是2^16B即64KB,所以一个段的长度最大是64KB

段寄存器

段寄存器是段地址存放的位置,8086CPU中有4个寄存器:CS,DS,SS,ES。当8086CPU要访问内存时由这4个段寄存器提供内存单元的段地址。

CS和IP

CS是代码段寄存器,IP是指令指针寄存器。设CS中的内容为M,IP中的内容为N,8086CPU将从内存M16+N开始,读取一条指令并执行。即 CS 16+IP

  • 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器
  • IP=IP+所读取指令的长度,从而指向下一条指令
  • 执行指令,转到第一步,重复过程

修改CS、IP指令

程序员可以通过改变CS、IP中的内容来控制cpu执行目标指令

1
2
3
4
5
6
7
8
9
10
11
12
修改AX中的内容:
mov指令->传送指令
eg:mov ax,123
修改CS、IP的指令:jmp指令
同时修改CS、IP的内容:jmp段地址:偏移地址-->用指令中给出的段地址修改CS,偏移地址修改IP
eg:jmp 2AE3:3,执行后,CS=2AE3H,IP=0003H,CPU将从2AE33H处读取指令
jmp 3:0B16,执行后,CS=0003H,IP=0B16H,CPU将从00B46H处读取指令
仅修改IP的内容:jmp+某一合法寄存器-->用寄存器中的值修改IP-->mov IP,ax
eg:jmp ax,指令执行前:ax=1000H,CS=2000H,IP=0003H
指令执行后:ax=1000H,CS=2000H,IP=1000H
jmp bx,指令执行前:bx=0B16H,CS=2000H,IP=0003H
指令执行后,bx=0B16H,CS=2000H,IP=0B16H

代码段

根据需要,可以将一组内存单元定义为一个段。这段内存是用来存放代码的,即代码段

1
2
3
4
mov ax,0000(B0 00 00)
add ax,0123H(05 23 01)
mov bx,ax(8B D8)
jmp bx(FF E3)

这段长度为10个字节的指令,存放在123B0H~123B9H的一组内存单元中,把这组内存单元称为代码段