第三章
一、题目回顾
针对8086,在debug中执行以下命令:-e 0:200 10 20。在debug中,使用a命令,写出汇编指令,计算内存单元地址00200H,00201H两个字节数据的总和,并将结果保存在00202H中。
方法一: 方法二: 方法三:
mov ax,0 mov ax,0 mov bx,20
mov ds,ax mov ds,ax mov ds,bx
mov al,[200] mov al,[200] mov al,[0]
add al,[201] mov [200],al add al,[1]
mov [202],al mov al,[201] mov [2],al
add [201],al
关于栈的说法,正确的是
- 入栈和出栈只能从栈顶操作。
- 栈空间中,固定的一端称为栈顶。
- 栈空间中,栈顶会随着数据的入栈和出栈而动态变化
- 通过入栈和出栈指令,访问的是栈顶,而mov、add等指令可以通过偏移地址访问栈中其他单元。
将00200H-002FFH这段内存当作栈来使用,初始栈为空
方法一: 方法二:
mov ax,0 mov bx,20H
mov ss,ax mov ss,bx
mov sp,300H mov sp,100H
关于栈的说法,正确的是:
- 8086dos汇编中约定栈空间的入栈和出栈均以字为单位,而其他有些汇编指令则支持以字,字节,双字等作为入栈和出栈操作的单位。
- SS全称Stack Segement Register,栈段寄存器,用来存放栈段的地址
- SP全称Stack Pointer Register,栈指针寄存器,用来存放栈顶的偏移指针
- SS:SP构成了栈顶的逻辑地址,通过SS*16+SP可以计算出栈顶的物理地址。
---------------------------------------------------------------------------------------------------------------------------------
二、寄存器
DS和[address]
mov ax,1000H
mov ds,ax ;ds<-1000H
mov al,[0] ;al<-(ds:0)
mov bl[1] ;bl<-(ds:1)
ds中的值默认为段地址
mov指令形式
mov 寄存器, 常数 mov ax, 1000H
mov 寄存器, 寄存器 mov bx, ax
mov 寄存器, 内存单元 mov ax, [1]
mov 寄存器, 段寄存器 mov ax, ds
mov 内存单元, 常数 mov [1], byte ptr 3
mov 内存单元, 寄存器 mov [1], ax
mov 内存单元, 段寄存器 mov [1], ds
mov 段寄存器, 寄存器 mov ds, ax
mov 段寄存器, 内存单元 mov ds, [1]
注意:
- 两个操作数长度要一致
- 常数(立即数)不能作为目的操作数
- 常数作为源操作数时,如果最高位是十六进制的a-f,前面要加零。
add 指令形式
add 寄存器, 常数 add ax, 1000H
add 寄存器, 寄存器 add bx, ax
add 寄存器, 内存单元 add ax, [1]
add 内存单元, 常数 add [1], byte ptr 3
add 内存单元, 寄存器 add [1], ax
sub指令形式
sub 寄存器, 常数 sub ax, 1000H
sub 寄存器, 寄存器 sub bx, ax
sub 寄存器, 内存单元 sub ax, [1]
sub 内存单元, 常数 sub [1], byte ptr 3
sub 内存单元, 寄存器 sub [1], ax
小结
- 字在内存中存储时,要用两个连续地址的内存单元来存放,字的低位字节存放在低地址单元中,高位字节存放在高地址中。
- 用mov指令访问内存单元,可以在mov指令中只给出单元的偏移地址,此时段地址默认在DS寄存器中。
- [ADDRESS]表示一个偏移地址位address的内存单元
- 在内存和寄存器之间传送字型数据时,低地址单元和低八位,高地址单元和高八位相对应。
- mov、add、sub是具有两个操作对象的指令。jmp是具有一个操作对象的指令。
- 数据和程序没有区别。被CS:IP指向的信息是程序;被传送、运算等指令操作的是数据。我们可以自己定义出代码段,数据段,栈段。
---------------------------------------------------------------------------------------------------------------------------------
三、栈
栈的特性: 后进先出
两个概念: 栈底、栈顶
两个操作: 入栈、出栈
一个约定: 8086中栈以字为存取单位
栈顶: 最后入栈的字数据所对应的地址单元
栈底: 固定的一端,栈区最高地址单元的前一个单元
入栈: 把数据存入栈
出栈: 从栈取出数据
push 指令执行步骤:
- SP=SP-2;
- 向SS:SP指向的字单元中送入数据
pop指令执行步骤:
- 从SS:SP指向的字段元中读取数据
- SP=SP+2
栈为空时,栈顶指向栈底+2
任意时刻,SS:SP指向栈顶元素
汇编指令 功能
push 寄存器 将寄存器值入栈
pop 寄存器 用寄存器保存出栈数据
push 内存单元 将内存单元内容入栈
pop 内存单元 用内存单元保存出栈数据
push 段寄存器 将段寄存器值入栈
pop 段寄存器 用段寄存器保存出栈数据
指令形式 功能
push ax 栈 ← ax
pop ax ax ← 栈
push [0] 栈 ← ds:0对应的内存单元字数据
pop [0] ds:0对应的内存单元 ← 栈
push ds 栈 ← ds
pop ds ds ← 栈
对8086CPU而言,push和pop的操作:
入栈和出栈均以字为单元
操作对象不能是常数
pop 段寄存器中,段寄存器不能是CS和SS
以下两种情形会发生「栈顶超界」问题:
当栈满的时候,再使用push指令入栈;
当栈空的时候,再使用pop指令出栈;
8086CPU不会自动考虑栈顶超界,需要程序员在编程设计时自己考虑。栈区长度不同,栈顶超界的具体情形也不同。
小结
1. 「段」是一个逻辑上的概念。编程时,可根据需要指定一段内存区用作数据段、代码段或是栈段。
2. 用作数据段时,要把段地址→DS.用作栈段时,要把段地址→SS,栈顶偏移地址 → SP。用作代码段时,段地址→CS,要取的指令偏移地址→IP。但CS和IP的值不能使用mov改变.
3. 一段内存可以同时用作代码段、数据段、栈段。由编程时灵活确定。
4. 在8086CPU中,每个段的最大长度不能超过64KB。
(因为寄存器是16位的,能表示的地址范围只能是0000H~FFFFH,即0~216-1)

浙公网安备 33010602011771号