8086 汇编笔记(二):寄存器(内存访问)

一、内存中字的存储

字单元的概念:字单元,即存放一个字型数据(16 位)的内存单元,由两个地址连续的内存单元组成

由上一章学习可知:高地址内存单元中存放字型数据的高位字节,低地址内存单元中存放字型数据的低位字节

现在有以下几个问题

(1) 0 地址单元中存放的字节型数据是多少? 20H

(2) 0 地址字单元中存放的字型数据是多少? 4E20H

(3) 2 地址单元中存放的字节型数据是多少? 12H

(4) 2 地址字单元中存放的字型数据是多少? 0012H

(5) 1 地址字单元中存放的字型数据是多少? 4E12 H

注意: 1 地址字单元,即起始地址为 1 的字单元,它由 1 号单元和 2 号单元组成

二、DS 和 [address]

8086 CPU 中有一个 DS 寄存器,通常用来存放要访问数据的段地址。比如我们要读取 10000H 单元的内容,可以用如下的程序段进行:

复制代码
mov bx,1000H
mov ds,bx
mov al,[0]

上面的 3 条指令将 10000H(1000:0) 中的数据读到 al 中

8086 CPU 自动取 ds 中的数据为内存单元的段地址"[...]"表示一个内存单元,"[...]"中的 0 表示内存单元的偏移地址

另一个案例,如果将 10000H 单元的内容送入 al 中呢

复制代码
mov [0],al

三、字的传送

前面我们用 mov 指令在寄存器和内存之间进行字节型数据的传送(8 位)

只要在 mov 指令中给出 16 位的寄存器就可以进行 16 位数据的传送了

四、数据段

比如,将 123B0H~123B9H 的内存单元定义为数据段。现在要累加这个数据段中的前3 个单元中的数据,代码如下:

复制代码
mov ax,123BH
mov ds,ax
mov al,0
add al,[0]
add al,[1]
add al,[2]
..............................

答案解析:

五、栈

六、CPU 提供的栈机制

8086 CPU 提供入栈和出栈指令,最基本的两个是 PUSH(入栈) 和 POP(出栈)。

8086 CPU 的入栈和出栈操作都是以字为单位进行的

请看以下指令

复制代码
mov ax,0123H
push ax
mov bx,2266H
push bx
mov cx,1122H
push cx
pop ax
pop bx
pop cX

指令执行过程如下

8086 CPU 中,有两个寄存器,段寄存器SS和寄存器SP,栈顶的段地址存放在 SS 中,偏移地址存放在 SP 中

任意时刻,SS:SP 指向栈顶元素

pop 指令执行过程

七、栈顶超界问题

8086 CPU 不保证我们对栈的操作不会超界

总结:我们在编程的时候要自己操心栈顶超界的问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致的超界;执行出操作的时候也要注意,以防栈空的时候继续出栈而导致的超界。

八、push、pop 指令

复制代码
push 寄存器
push 段寄存器
push 内存单元

pop 寄存器
pop 段寄存器
pop 内存单元

编程:

将 10000H~1000FH 这段空间当作栈,初始状态栈是空的,将 AX、BX、DS

中的数据入栈

复制代码
mov ax,1000H    ;设置栈的段地址,SS=1000H,不能直接向段寄存器SS中送入数据,所以用 ax 中转
mov ss,ax
mov sp,0010H
push ax
push bx
push cx

编程:

将 10000H~1000FH 这段空间当作栈,初始状态栈是空的,设置 AX-001AH,BX-001BH:将 AX、BX 中的数据入栈,然后将 AX、BX 清零,从栈中恢复 AX、BX 原来的内容

复制代码
mov ax,1000H
mov ss,ax
mov sp,0010H    ;初始化栈顶
mov ax,001AH
mov bx,001BH
push ax
push bx
mov ax,0
mov bx,0
pop bx
pop ax
复制代码
mov ax,1000H
mov ss,ax
mov sp,0002H
mov ax,2266H
push ax

push ax 是入栈指令,它将在栈顶之上压入新的数据。一定要注意:它的执行过程是,先将记录栈顶偏移地址的 SP 寄存器中的内容减 2,使得 SS:SP 指向新的栈顶单元,然后再将寄存器中的数据送入 SS:SP 指向的新的栈顶单元

原因:因为 8086 处理器是从高地址到低地址增长栈

九、栈段

如果将 10000H~IFFFFH 这段空间当作栈段,初始状态是空的,此时,SS=1000H,SP=?

栈段基址和栈指针的初始值

  • 栈段寄存器(SS)确定栈段的基址。给定SS = 1000H,那么栈段基址为10000H。
  • 栈指针(SP)指示当前栈顶的偏移量。对于一个空栈,SP的初始值应指向栈段的末尾,以便第一次 PUSH 操作能够在栈的顶部进行。

栈指针初始值的计算

8086处理器的栈段从高地址向低地址增长。即:

  • 栈顶在栈段的高地址。
  • 栈底在栈段的低地址。

为了确保栈初始为空,我们需要将SP设置为指向栈段的最高地址的下一个字(word)。

栈段范围是从10000H到1FFFFH,总大小为FFFFH字节。栈段最高地址是1FFFFH,如果初始SP指向1FFFFH,那么第一个 PUSH 操作会将数据放在1FFFDH和1FFFEH(SP减2后)的位置。因此,我们设置SP为栈段的最大容量加1,即栈段结束地址的下一个位置。

具体步骤

  1. 计算栈段大小

    • 栈段基址 = 10000H
    • 栈段结束 = 1FFFFH
    • 栈段大小 = 1FFFFH - 10000H + 1 = FFFFH + 1 = 10000H
  2. 设置初始SP

    • 初始SP = 栈段大小 = 10000H

由于8086处理器中的栈操作将SP减2后再存储数据,这样设置SP可以保证在第一次PUSH操作时SP减2后刚好在1FFFEH和1FFFDH位置存储数据。

相关推荐
EasyDSS37 分钟前
国标GB28181设备管理软件EasyGBS远程视频监控方案助力高效安全运营
网络·人工智能
玩转4G物联网40 分钟前
零基础玩转物联网-串口转以太网模块如何快速实现与TCP服务器通信
服务器·网络·物联网·网络协议·tcp/ip·http·fs100p
派阿喵搞电子1 小时前
Ubuntu下有关UDP网络通信的指令
linux·服务器·网络
网安INF1 小时前
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
java·web安全·网络安全·flink·漏洞
jackson凌1 小时前
【Java学习笔记】SringBuffer类(重点)
java·笔记·学习
lubiii_1 小时前
墨者学院-密码学实训隐写术第二题
web安全·网络安全·密码学
huangyuchi.2 小时前
【Linux】LInux下第一个程序:进度条
linux·运维·服务器·笔记·进度条·c/c++
南玖yy2 小时前
硬盘寻址全解析:从 CHS 三维迷宫到 LBA 线性王国
汇编·硬件架构·lba模式·chs模式
搬码临时工2 小时前
外网访问内网服务器常用的三种简单操作步骤方法,本地搭建网址轻松让公网连接
服务器·网络·智能路由器
moongoblin2 小时前
行业赋能篇-2-能源行业安全运维升级
运维·安全·协作