8086汇编学习之DS寄存器、SS/SP寄存器
相关博客:8086汇编基础知识、通用寄存器、CS/IP寄存器与Debug的使用
一、DS寄存器
一个8086CPU寄存器均是16位的,而数据类型有以下两种:
1Byte = 8bit (字节型数据)
1word = 2Byte = 16bit (字型数据)
16位寄存器存储一个字,而在内存中需要两个空间连续的字节存储一个字。(高位地址存放高位数据,低地址存放低位数据)。 任何两个地址连续的内存单元,N号单元与N+1号单元可以看做两个字节单元,也可以看做一个地址为N的字单元中的低字节单元(N)和高字节单元(N+1)。举例如图:
那么CPU如何访问这些地址中的数据呢?我们知道CPU通过CS:IP寄存器获取下一条指令的地址。而要获取数据就需要通过DS寄存器,DS段地址寄存器:存放要访问数据的段地址。
-e 2000:0000 11 22 33 44 //向2000:0000设置初始值
-a
mov bx,2000
mov ds,bx //设置DS段地址寄存器的值为2000
mov al,[0]
mov cx,[1]
以上指令将2000:0000地址单元的字节型数据值读取到al(8位)寄存器中。将2000:0001地址单元的字型数据读取到cx(16位)寄存器中。[]表示内存单元,其中的0表示偏移地址,对哪个段偏移的呢?8086CPU会自动读取ds的数据最为内存单元的段地址。最终的寄存器值为:
BX=2000
DS=2000
AX=0011
CX=3322
测试如下:
同样,DS和CS等段地址寄存器都是相通的,不支持将数据直接送进段地址寄存器中,要通过其它寄存器中转,这属于硬件设计问题。
当然,我们将[n]可以存向al、ax,也可以将al、ax存向[n](各种合理组合,都是可以的):
mov [0],al //al的值存到ds:[0]的地址中
mov [2],ax //ax字型数据,al存入ds:[2]和ah存入ds:[3]
add ax,[0] //相加的结果保存到ax中
add [0],ax //相加的结果保存到ds:[0]与ds:[1]的地址中
sub al,[0] //相减的结果保存到al中
sub [0],ah //相减的结果保存到ds:[0]的地址中
...
以下几条指令
mov ds,1000
add ds,ax
sub ds,ax
...等等都是不合理的
在内存中,数据与指令是完全没有区别的,而在寄存器中,数据与指令是有区别的,因为不同寄存器保存的是不同类型数据的地址(CS保存指令数据段地址,DS保存操作数段地址…)而CPU负责读取CS:IP确定下一条指令存放的地址,读取DS得知将要处理的数据的段地址,根据指令中偏移地址找到具体数据。所以说,汇编程序通过CPU读取寄存器寻找指令与数据,进行一系列操作。
二、SS/SP栈段寄存器:
在C、C++、Java…一系列高级语言中,我们都使用过栈这种数据结构,在汇编这种古老的语言中,栈当然也是存在的。那么如何在汇编中使用寄存器描述一个栈空间?就需要用到SS与SP寄存器。对于8086汇编来说,一次入栈/出栈的字节数都是2字节即1字。
push指令 –> ①SP - 2 –> ②将字型数据存放到SS:SP地址中
pop指令 –> ①将SS:SP地址的字型数据取出来 –> ②SP + 2
上面这个步骤就像C中我们入栈前先移动栈顶指针,再入栈。出栈时先取出数据,再将栈顶指针向栈底移动(属于“满栈”(先移动Top再压栈))。
指令使用规则:
push 16bit寄存器/push “DS:[n]”:寄存器可以为 (ax\bx\cx\dx\ds\es\ss\sp…),8位寄存器不可以。(SP-2,从指定寄存器/“DS:[n]”地址中读取数据入栈)
pop 16bit寄存器/pop “DS:[n]”:(从栈中取出数据放到寄存器/“DS:[n]”地址中,SP+2)
(在Debug中“DS:”需要省略,只用一个[n],CPU自动会从DS中读取栈段地址。可以从寄存器或DS:[]地址中读取数据入栈但是不能“push FFFF”将值直接入栈,出栈亦然)
注意:栈底在高内存地址,任意时刻,SS:SP指向栈顶元素(那么SS:SP两个寄存器就类似于一个Top指针),所以说栈在哪里是由SS:SP决定的(给SS:SP初值即为栈底)。但是栈的大小是没有严格界限的,当SP-2<0时,又会从FFFF开始减,但是不保证其权限。可能越界错误,可能不越界错误(不会自动判断栈满/栈空)。而关于栈的越界问题需要程序员自己注意(这个比C更自由,但更不安全)。
eg:
/*通过Debug的-r修改SS:SP*/
-r SS
2000
-r SP
10
/*或者:通过寄存器中转修改SS:SP*/
mov ax,2000
mov ss,ax
mov sp,10 //IP寄存器不能直接用值修改,但是SP寄存器可以//就是指定栈底地址为2000:10,此时SS:SP=2000:0010
mov ax,1234
mov bx,5678
push ax //SP-2=000E,2000:E与2000:F中分别存放34和12
push bx //SP-2=000C,2000:C与2000:D中分别存放78和56
pop cx //出栈CX=5678,SP+2=000E
pop dx //出栈DX=1234,SP+2=0010
我们将入栈过程分析一下,如图所示:
出栈则是其逆过程,先出值到寄存器中,再移动栈顶指针(修改SS:SP寄存器值)
明白了CS、DS、SS寄存器后我们就可以为数据段(text)、代码段(code)、栈段(stack)总结一下了:
数据段:存放数据的段(段地址在DS中)
代码段:存放代码的段(段地址在CS中)
栈段:存放临时性数据的并且由SS:SP维护的段(段地址在SS中)
三、DS、SS、SP寄存器混合使用:
(例题为王爽老师的《汇编语言》第三章检测点3.2)
将10000H~1001FH中的八个字,逆序复制到20000H~2001FH中,如何用栈做?
法一:
从ds:[]入栈,ds:[]是源(10000H~1000FH),栈是目标(20000H~2000FH)
//设置数据段地址
mov ax,1000H
mov ds,ax //设置栈段地址
mov ax,2000H
mov ss,ax
mov sp,10H //从数据段向栈段复制:是从指定数据段(10000H~1000FH)向指定栈段(20000H~2000FH)存放数据
push [0]
push [2]
push [4]
push [6]
push [8]
push [A]
push [C]
push [E]
法二:
出栈至ds:[],栈是源(20000H~2000FH),ds:[]是目标(10000H~1000FH)
//设置数据段地址
mov ax,2000H
mov ds,ax//设置栈段地址
mov ax,1000H
mov ss,ax
mov sp,0H//从栈段向数据段复制:是将指定栈中(10000H~1000FH)值放到指定的数据段中(20000H~2000FH)
pop [E]
pop [C]
pop [A]
pop [8]
pop [6]
pop [4]
pop [2]
pop [0]
混合图解:
法一测试:
先给10000H~1000FH设定初始值:
执行所有出栈指令后,可以看到10000H~1000FH的值被按字(不是安字节)逆序复制到了20000H~2000FH。
8086汇编学习之DS寄存器、SS/SP寄存器相关推荐
- 8086汇编学习之[BX],CX寄存器与loop指令,ES寄存器等
同类学习笔记总结: (一).8086汇编学习之基础知识.通用寄存器.CS/IP寄存器与Debug的使用 (二).8086汇编学习之DS寄存器.SS/SP寄存器 一.汇编程序的基本格式: 1.基本格式与 ...
- 8086寄存器学习笔记-SS 寄存器和 SP 寄存器
SS 寄存器和 SP 寄存器: SS 寄存器:Stack Segment (堆栈段寄存器) SP 寄存器:Stack Pointer(堆栈指针寄存器) 这两个寄存起是为了访问内存用的,SS为段寄存器, ...
- 8086汇编学习小记-1
8086汇编学习小记-1 View Code assume cs : codesg, ds : datasg, ss : stacksgdatasg SEGMENT... datasg ENDSsta ...
- 8086汇编学习小记-王爽汇编语言实验12
8086汇编学习小记-王爽汇编语言实验12 0号中断处理程序,开始安装在0000:0200处的程序最后用死循环导致显示不出'divided error',改成直接退出就正常显示了.注意修改ss,sp之 ...
- 栈Stack和段寄存器SS,SP(学习汇编)
1. 栈有2个基本操作:入栈.出栈 2. 栈顶的元素总是最后入栈,最先出栈:后进先出. 3. 8086CPU提供入栈和出栈的指令,最基本的两个是 PUSH(入栈) 和 POP(出栈) push ax ...
- 【汇编语言】栈区与SS:SP寄存器
汇编语言 - 栈 栈是一块特殊的内存空间,本文涉及的CPU为8086CPU,所有与内存地址有关的数字皆为16进制 前言 栈的运行规律 - 先进后出,后进先出 以下为入栈的过程: 以下是出栈的过程: 以 ...
- 8086 汇编寄器基础篇 物理地址- 寻址方式 - 寄存器说明
基本数据类型 规定 计算机的存是以二进制位表示的信息位数一般是8的倍数 字节 一个字节由8个二进制组成 字符串 是指由字符构成的一个线性数组, 通常每个字符用一个字节表示,但有时可用以字和双字 ...
- 汇编学习教程:循环和CX寄存器
引言 在上面博文中,我们主要学习了BX寄存器配合DS寄存器完成内存访问,同时也探究了Masm编译器面对弱指定和强指定两种情况时所产生的不同编译结果. 我们提到:xx:[idata] 是强指定格式,这种 ...
- 汇编学习笔记1 通用寄存器和段寄存器详解
一.通用寄存器 寄存器 编号(二进制) 编号(十进制) 64位 32位 16位 8位 累加寄存器 RAX EAX AX AL 000 0 计数寄存器 RCX ECX CX ...
最新文章
- 28. Leetcode 25. K 个一组翻转链表 (链表-反转链表)
- Maven的maven-install-plugin插件详解
- 【POJ-3259】 Wormholes(判负环,spfa算法)
- 二级省市联动下拉菜单
- 从“在winform里打开网页功能”引发的问题探究
- Python Chemistry
- Cocos Creator学习のTiledMap
- Godot Label 节点
- win10电脑360调用不到JAVA,win10系统打不开360浏览器快捷方式的修复步骤
- 游戏中MD5加密的一些作用
- 上海企业英语培训机构排名
- 编程数学-∑(求和符号)-Sigma
- 超媒体是什么?Hypermedia(一种采用非线性网状结构对块状多媒体信息(包括文本、图像、视频等)进行组织和管理的技术)
- 只有程序员能听懂的笑话【关于TCP的链接的笑话】
- 数据分析01 - 规范化方法
- 基于Arduino的显示测量环境数据设计
- 机房集中监控中KVM的五大设计原则是哪些?
- 高质量 iOS 博客推荐(iOS界技术大牛)
- 计算机上m键mm代表什么意思,M与MM分别代表什么?What does M and MM stand for?
- 小米VR一体机开发及apk文件导入