1. 基础知识
概念
-
汇编语言
- 汇编语言是机器指令的助记符,每一种CPU都有自己的汇编指令集
- 组成
- 汇编指令:机器指令的助记符,有对应的机器码
- 伪指令:由编译器执行,没有对应机器码,机器不执行
- 其他符号
-
存储单元
- 微型机存储单元可以存储一个B(Byte,字节),即8个二进制位,存储无符号值0~255
-
总线
- 计算机中专门连接CPU和其他芯片的导线,称为总线。导线从物理上讲,就是一根根导线的集合,一根导线可以传送的稳定状态只有两种,高电平或低电平,分别可以代表1和0。
- 带宽:一个CPU有N跟总线,可以称总线的宽度为N。
- 根据传送的信息不同,总线从逻辑上又分为,地址总线,控制总线和数据总线。
-
地址总线:地址总线的宽度决定了CPU的寻址能力
- 寻址范围为2^N -1
- 寻址能力为2^N
- 数据总线:数据总线的宽度决定了CPU与其他部件进行数据传送石一次的数据传送量
- 控制总线:控制总线的宽度决定了CPU对系统中其他器件的控制能力
-
内存地址空间
- CPU在操纵不同器件时,把他们都当作内存来对待,把所有物理存储器总的看作一个由若干个存储器组成的逻辑存储器,每个物理存储器在这个逻辑存储器中占有一个地址段,即一段地址空间。把这个逻辑存储器称作内存地址空间。
CPU对存储器的读写
- CPU要想进行数据的读写,必须通过总线与外部器件(芯片)进行下面3类信息的交互
- 地址信息,存储单元的地址
- 控制信息,器件的选择,读或写的命令
- 数据信息,读或写的数据
例:CPU从3号单元读取数据
- CPU通过地址线将地址信息3发出
- CPU通过控制线发出命令,选中存储器芯片,并发出读取数据的指令
- 存储器将3号单元中的数据通过数据线送入CPU
机器码:10100001 00000011 00000000 汇编指令:MOV AX,[3]
存储容量的转换
- 地址总线宽度和寻址能力的转换
- 数据总线宽度和数据一次传送能力
2. 寄存器
AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW
2.1 通用寄存器
有AX(accumulator)、BX(base)、CX(count)、DX(data)
8086上一代CPU(8080、8085)是8位的,为了保证兼容,这四个寄存器每个都可以分为两个独立使用的寄存器
2.3 几条汇编指令
2. 当16位寄存器看做独立的8位寄存器时,操作不会对16位寄存器产生影响
2.4 物理地址
所有的内存单元构成的存储空间是一个一位线性空间,每一个内存单元都在这个空间有唯一的地址,把每个内存单元唯一的称作物理地址。
2.5 16位的CPU
2.6 8086CPU给出物理地址的方法
8086CPU有20根地址总线,有1MB的寻址能力,但在内部一次性处理、传输、暂时存储的地址为16位,顾8086CPU在内部采取用两个16位地址合成的方法来形成一个20位的地址。
地址加法器采物理地址 = 段地址×16 + 偏移地址 的方法合成物理地址
2.8 段的概念
在编程时根据需要,可以把一些内存看做一个段,用段地址×16定位段的起始地址,用偏移地址定位段中的内存单元
2.9 段寄存器
8086CPU提供4个段寄存器:CS(Code Segment)、DS(Data Segment)、SS(Stack Segment)、ES(Extra Segment)
2.10 CS和IP
CS:IP是CPU中最重要的两个寄存器,他们指示了CPU当前要执行的指令地址,CS为代码段寄存器存放指令的段地址,IP(Extra Segment)为指令指针寄存器存放指令的偏移地址,
注意:内存中的信息可以看做指令或数据,CPU将CS、IP中的内容看做指
2.11 修改CS、IP的指令
在CPU中,程序员能够用指令读写的部件只有寄存器,程序员需要通过改变CS、IP中的内容实现对CPU的控制。
mov指令(传送指令)不能用于设置CS、IP中的值,能够改变CS、IP值的指令统一称为转移指令、
2.12 代码段
专门用来存储指令的内存区域,需要用CS:IP指向才可以执行。
总结
- CPU访问内存单元时,必须提供内存单元的物理地址。8086CPU在内部用段地址和偏移地址移位相加的方式形成最终的物理地址。
- 段地址在段寄存器中存放,8086CPU中CS存放指令的段地址,IP存放指令的偏移地址,任意时刻CPU将CP:IP中的地址当做指令执行。
-
8086CPU工作过程
- 从CS:IP指向的内存单元读取指令,读取的指令放入指令缓存器
- IP指向下一条指令
- 执行指令(转到1,重复这个过程)
实验:基本指令
-
R命令(Register):
R, R [register name]。显示和修改寄存器内容。 -
D命令(Dump):
D [address], D [range]。内存16进制显示。 -
E命令(Enter):
E address[list]。修改内存字节 -
A命令(Assemble):
a [adress]。逐行汇编。 -
U命令(Unassemble):
U [address], range。查看汇编代码(反汇编)。 -
T命令(Trace):
T [=address][value]。跟踪执行。
3. 寄存器内存访问
3.1 内存中字的存储
CPU中,用16位来存储一个字,高八位存储高位字节,低八位存储低位字节,即一个字需要两个地址连续的内存单元存放。
我们把组成的内存单元叫做字单元,以后把起始地址为N的字单元简称为N地址单元。
3.2 DS和[address]
读取10000H单元的数据,[address]表示一个偏移地址为address的内存单元
mov bx,10000H
mov ds,bx // 把DS设为10000H
mov al,[0] // 这时候[0], 就是取1000H:0的意思
注意:8086CPU不支持直接将数据送入段寄存器,需要先把数据放在一个通用寄存器,再移动到段寄存器
3.3 字的传送
3.4 mov、add、sub的指令
例:
mov ax,8
mov ax,bx
mov ax,[0]
mov [0],ax
mov ds,ax
mov ax,ds
mov ds,[0]
3.5 数据段
可以专门用DS来存放数据段的段地址
3.6 栈
3.7 CPU提供的栈机制
任意时刻,SS:SP指向栈顶元素
push ax指令
1)SP=SP-2
2)向SS:SP指向的字单元中送入数据
pop ax
1)将SS:SP指向的字单元读取数据
2)SP=SP+2
3.8 栈顶超界的问题
8086CPU没有设置防止栈溢出的机制,需要自己注意
实验二:栈
注意:
Debug的T命令在执行修改器SS的指令时,下一条指令也紧接着被执行
4. 第一个程序
4.1 写出到执行
- 编写汇编源程序(用 Edit或记事本等,文件保存为.asm)
- 对源程序进行编译(用masm.exe对源程序进行编译,生成 .obj文件)
- 链接(用link.EXE文件进行链接,生成 .exe文件)
- 执行
4.2 源程序包括伪指令和汇编指令
assume cs:codesg // 将段寄存器cs和codesg关联起来
// 定义一个段,一个汇编程序由多个段组成,这些段用来存放代码、数据或当做栈空间来使用。如下简单的实例中最少有一个段来存放代码
codesg segment // 一个段的开始, codesg 为段名称
4.3 操作系统的外壳(shell)
任何通用的操作系统都要提供一个称谓shell的程序,用户(操作人员)使用这个程序来操作计算机系统进行工作。DOS的shell称作命令解释器,command.com,DOS启动时,先完成其他重要的初始化工作,然后运行命令解释器程序command,将exe文件加载入内存,而且Command设置CS:IP指向程序的第一条指令,使程序可以运行,最后程序返回时,返回到command中,CPU继续运行command。
4.4 程序被装入内存什么地方?
实验三:编程编译连接跟踪
5 [BX]和loop指令
5.1 [bx]和内存单元
[bx]相当于用寄存器起变量的作用做偏移地址,注意他的段地址是DS
在debug程序中 mov al,[6]表示吧六号内存单元的值放入al,在汇编程序中需要mov bx,6 再mov al,[bx]
段前缀(ds:,cs:,ss:,es:)
形式 mov ax,cs:[bx] //用来显示的声明段地址
如果不加段前缀, 直接 mov ax,[bx] 则默认段前缀为ds:
5.2 约定
- 描述性符号():(地址或寄存器)表示里面的内容
- idata表示常量
5.3 循环指令loop
assume cs:code
code semgent
mov ax,0
mov cx,236 //cx循环次数
s: add ax,123 //循环标号 s: 标示一个地址存放需要循环的语句
loop s //开始循环
mov ax,4c00h
int 21h
code ends
end
5.4 debug
g 命令+偏移地址 跳到cs:编译地址所存代码行
p 命令 遇见loop语句直接跳到循环结束
实验4 [bx]和loop
、
注意1
将0:200用0020:0 表示
bl把低八位赋值到0020:[bx]