本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
学习教材:《汇编语言(第4版)》王爽著 此笔记是书中内容+自我总结,方便查阅和复习 请支持原著
一、内存中字的存储
CPU中一个字寄存在一个十六位寄存器中。其中:高八位存放高位字节,低八位存放低位字节
字单元由两个连续单元组成,起始地址为N的字单元称为N地址字单元,N地址单元由地址为N和N+1两个单元构成

- 0地址单元中存放的字节型数据是11H
- 0地址字单元中存放的字型数据是2211H(注意顺序)(地址单元和地址字单元)
- 1地址字单元中存放的字型数据是3322H
二、内存地址寄存器
内存地址由段地址和偏移地址组成,DS寄存器用来存放段地址,偏移地址由[...]表示。
mov bx,1000H
mov ds,bx
mov al,[0]
指令执行时,CPU自动取DS内的数据作为段地址,最终将10000H(1000:0)中的数据送入了al
由上所示,CPU不支持将数据直接送入DS寄存器,需要将地址数据先送入一个普通寄存器(即上方的bx),再将普通寄存器中的地址数据传入DS段寄存器。
实验:写出下面的命令执行后内存中的值

mov ax,1000H //ax=1000H
mov ds,ax //ds=1000H
mov ax,2C34H //ax=2C34H
mov [0],ax //&10000H=2CH, &10001H=34H
mov bx,[0] //bx=2C34
sub bx,[2] //bx=2C34H-1122H=1B12H
mov [2],bx //&10002H=12H, &10003H=1BH
最终10000H-10003H为:34、2C、12、1B
三、mov、sub、add指令
mov支持的操作
- mov 寄存器,数据
- mov 寄存器,寄存器
- mov 寄存器,段寄存器
- mov 寄存器,内存单元
- mov 内存单元,寄存器
- mov 内存单元,段寄存器
- mov 段寄存器,内存单元
- mov 段寄存器,寄存器
用mov指令访问内存单元可以只给出偏移地址,段地址默认存放在ds寄存器中
add、sub支持的操作
- add(sub) 寄存器,数据
- add(sub) 寄存器,寄存器
- add(sub) 寄存器,内存单元
- add(sub) 内存单元,寄存器
寄存器的清零
要清零寄存器,可以用mov置零或是sub自减。区别在于sub ax,ax的机器码是二字节,而mov ax,0的机器码是三字节
四、栈
栈有两种基本操作:入栈和出栈,操作规则为LIFO(Last In First Out,后进先出),且这两种操作都是以字为单位进行,对应指令为push与pop。
首先入栈的存入最高位字单元

五、栈地址寄存器
当我们将某一段内存当作栈来使用时,CPU是如何知道这段地址是栈呢?
8086CPU中有两个寄存器段寄存器SS和寄存器SP,SS存有栈顶段地址,SP存有偏移地址。任意时刻,SS:SP指向栈顶元素
如同DS,SS也不支持直接传入数据,需要普通寄存器作为中转
空栈时
若栈空,SP会指向栈最高地址单元的下一个地址

六、push、pop指令
支持的操作
注意:以字为单元
- push(pop) 寄存器
- push(pop) 段寄存器
- push(pop) 内存单元
例如:
mov ax,1000H
mov ds,ax
push [0]
pop [2]
push ax的执行
- SP-=2,SS:SP指向当前栈顶前面的单元,成为新栈顶
- 将ax的内容送入新栈顶
pop ax的执行
- 将SS:SP指向的数据送入ax,即当前栈顶值送入ax
- SP+=2,SS:SP指向当前栈顶下面的单元,成为新栈顶

七、栈顶越界问题
对满栈进行入栈、对空栈进行出栈都会导致栈顶超出了栈空间,引起栈顶超界问题
栈顶超界是危险的,可能会导致栈外的重要数据、代码被以外改写,引发不可预料的错误
8086CPU不保证对栈的操作不会引起越界,它只知道当前栈顶的位置,而不知道栈的空间大小。因此操作栈时要人工考虑栈顶越界问题
实验:编程
-
将10000H~1000FH作为空栈;
-
设置AX=001AH,BX=001BH,先后入栈;
-
将AX,BX清零;
-
从栈中恢复AX,BX的数据;
mov ax,1000H mov ss,ax mov sp,0010H //注意空栈的栈顶指针 mov ax,001AH mov bx,001BH push ax push bx sub ax,ax sub bx,bx pop bx pop ax
八、栈段
我们可以将长度为N(N<=64KB)的一组地址连续,起始地址是16的倍数的内存单元当作一个栈空间使用,从而定义了一个栈段
一段内存可以既是代码存储空间,又可以是数据存储空间,还可以是栈空间,也可以什么都不是。关键在于CPU中寄存器的设置,即CS、IP、SS、SP、DS的设置。是因为先有了寄存器设置,才有了那段内存的属性
为什么一个栈段最大是64KB?
由于对栈的操作是基于更改SP完成,而SP是一个十六位寄存器,因此只能到FFFFH,若继续移动那么栈就会循环到栈最低地址从而引发覆盖