当前位置: 首页 > 编程 > 正文

一.段寄存器 1.1 16位处理器能处理的最大数据范围是多少? 所谓的数据范围,就是能寻址的范围有多大.16位 […]

一.段寄存器

1.1 16位处理器能处理的最大数据范围是多少?

  • 所谓的数据范围,就是能寻址的范围有多大.16位处理器的地址总线为16根,寻址范围也就是2^16 = 65536(0~65535),也就是说,16位处理器可读取的内存地址最大为65535(64K).

  • 当年的64K可是土豪配置,而当年的1G内存就和如今的1T的内存一样不敢想像.贫穷限制了想象力.

1.2 16位处理器访问1M内存?

  • 计算机史,内存的发展远远超过CPU,当时市场条件是内存成本大大低于CPU,个人电脑完全有条件配置1M以上的内存空间.那么该如何解决0~65535的寻址限制呢?
    在谈解决方法之前,我们先假设下如果如果一栋楼层的电梯用1字节来存储,那么就有一个问题,这个电梯最多能上256层,如果超过256层怎么办?比如明年就出现了300层,这很尴尬,不上不下的.当然可以用两个字节来表示电梯层数,两个字节可以表示65535层,但用上两个字节成本也直线上升.
    这就如同我们遇到的问题,解决0~65535的寻址限制最便捷的方法是升级为32位CPU,线变成32根,寄存器也变成32位,成本很大,性价比低.

1.3 8086CPU给出物理地址的方法.

  • 8086CPU最终的解决方案是没升寄存器,而是加了4根地址总线,一共有20位地址总线,可以传送20位地址,达到1MB的寻址能力.8086CPU又是16位结构,在内部一次性处理,传输,暂存的地址位16位.如果从内部简单的看,它只能送出16位地址,表现出的寻址能力只有64KB.

  • 8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址.

如图2.6所示,当8086CPU要读写内存时:
1. CPU中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;
2. 段地址和偏移地址通过内部总线送入一个被称为地址加法器的部件;
3. 地址加法器将两个16位地址合成一个20位的物理地址;
4. 地址加法器通过内部总线将20位物理地址送入输入输出控制电路;
5. 输入输出控制电路将20位物理地址送上地址总线;
6. 20位物理地址北地址总线送到存储器.

  • 地址加法器采用物理地址 = 段地址x16 + 偏移地址的方法用段地址和偏移地址合成物理地址.如,8086CPU要 访问地址为123C8H的内存单元,此时,地址加法器的工作过程如图2.7(图中数据皆为16进制表示)

由段地址x16引发的讨论
* "段地址x16"有一个更常用的说法是左移4位.计算机中所有信息都是以二进制的形式存储的,段地址当然不例外.
* 一个数据的二进制形式左移1位,相当于该数据乘以2.
* 一个数据的二进制形式左移N位,相当于该数据乘以2的N次方.
* 地址加法器如何完成段地址x16的运算?就是将以二进制形式存放的段地址左移4位.
* 一个数据的十六进制左移1位,相当于乘以16;一个数据的十进制左移1位,相当于乘以10;一个X进制的数据左移1位,相当于乘以X.(进一位,补0).

1.4 "段地址x16+偏移地址=物理地址" 的本质含义

  • "段地址 x 16 + 偏移地址=物理地址"的本质含义是:CPU在访问内存时,用一个基础地址(段地址 x 16)和一个相对基础地址的偏移地址相加,给出内存单元的物理地址.

1.5 段的概念

  • 其实,内存并没有分段,段的划分来自于CPU.

  • 在编程中,将若干地址连续的内存单元看作一个段,用段地址x16定位段的起始地址(基础地址),用偏移地址定位段中的内存单元.段地址x16必然是16的倍数,所以,一个段的起始地址一定是16的倍数;偏移地址位位16位,16位的寻址能力位64KB,所以一个段长度最大为64KB.

1MB空间最多能分成多少个段?
* 每隔16个存储单元就可以开始一个段,因为段地址是16的倍数.
假设第一个段 - 段地址:偏移地址 = 1234:0 ,物理地址为 12340H.
第二个相邻的段 - 段地址:偏移 = 1235:0,物理地址为 12350H.
所以,1MB最多可以有:
20^20 / 16 = 2^16 = 64k 个段

1MB空间最少能分成多少个段?
每隔64K个存储单元开始一个段,
所以1MB最少可以有:
2^20 / 2^16 = 16个段

1.6 CS代码段寄存器

  • 代码段用来存放程序的指令序列.

  • 代码段寄存器 CS 存放代码段的段地址.

  • 指令指针寄存器 IP 指示下一条指令的偏移地址.

  • 处理器利用 CS:IP 取得下一条要执行的指令.

1.7 SS堆栈段寄存器(桟)

  • 堆栈段确定堆栈(桟)所在的主存区域.

  • 堆栈段寄存器SS存放堆栈段的段地址.

  • 堆栈指针寄存器SP指示堆栈栈顶的偏移地址.

  • 处理器利用 SS:SP 操作栈顶的数据.

1.8 DS数据段寄存器

  • 数据段存放运行程序所用的数据.

  • 数据段寄存器DS存放数据段的段地址.

  • 各种主存寻址方式(有效地址EA)得到存储器中操作数的偏移地址.

  • 处理器利用 DS:EA 存取数据段中的数据.

1.9 ES附加段寄存器

  • 附加段是附加的数据段,也用于数据的保存.

  • 附加段寄存器ES存放附加段的段地址.

  • 各种主寻址方式(有效地址EA)得到存储器中操作数的偏移地址.

  • 处理器利用 ES:EA 存取附加段中的数据.

  • 串操作指令将附加段作为其目的操作数的存放区域.

二.段超越前缀

2.1 什么是段超越?

  • 没有特定指明时,一般的数据访问在DS段;使用BP访问主存,则在SS段,例如 MOV AX,[BP] 则 AX = [SS:BP] 而不是 AX = [DS:BP].

  • 如果不想去DS段访问数据,就西药段超越前缀.

  • 默认的情况允许改变,需要使用段超越前缀指令.8086指令系统有4个:

  1. CS: ;代码段超越,使用代码段的数据
  2. SS: ;堆栈段超越,使用堆栈段的数据
  3. DS: ;数据段超越,使用数据段的数据
  4. ES: ;附加段超越,使用附加段的数据

2.2 段超越的示例

;没有使用段超越前缀
MOV AX,[2000H]  ; AX <- DS:[2000H]
; 从默认的DS数据段取出数据


;使用段超越前缀的指令实例示例:
MOV AX,ES:[2000H]  ; AX <- ES:[2000H]
; 从指定的ES附加段取出数据

;;;;;;;;;;;;;;;;;;;;;;;;;;;
;注意:某些编译器不能这么使用段超越前缀 ES:[2000H]
;而是先写前缀,后写指令,如:
ES:
MOV AX,[2000H]  ; AX <- ES:[2000H]
;并且,段超越前缀的指令只会生效一次,后面继续读取数据,就是变回了DS寄存器的段地址.
;;;;;;;;;;;;;;;;;;;;;;;;;;;

实例:




三.分段

之所以很难写出大软件,是因为我们虽然有段,但前面我们并没有使用.我们的代码,数据,桟并没有管理,都混在一起,代码没有管理,无法写出大型软件,更无法多人协作开发.

3.1 如何一个人写出大型软件

  • 要写出大型软件,那么代码得管理.那么我们必须分成三个段.
    代码段 : CS
    数据段 : DS
    堆栈段 : SS
    代码即数据,CS不好更改.但如果 CS:IP 能记到文件中,那么这个问题就可以得到了解决.于是提出了文件格式的概念.(COM文件并没有数据一说,数据即代码,所以很尴尬)

3.2 如何多人协作开发

  • 文件格式的概念使得一个人可以写出大型软件,但如何多人协作开发呢?将程序员A写的代码段与程序员B写的代码段合并,将程序员A写的数据段与程序员B写的数据段合并,将程序员A写的堆栈段与程序员B写的堆栈段合并,组合成新的EXE.这也是新的概念,链接器(LINK).但有一个问题,例如,两个代码段合并简单,但合并后地址变了,链接器还要负责修复代码地址.

  • 文件格式与系统相关,微软的编译器叫MASM,文件后缀名为ASM(看编译器).

  • 615是(16位汇编)(单独发布)最新版本,微软后期并没有更新.后期更新的方式是将ML.EXE集成在VS系列中(64位汇编).

  • 在文本编辑器中编辑代码,推荐用Notepad++.

3.3 分段


;数据段 MyData segment g_szMsg db "Hello World$" dw 1234H MyData ends ;堆栈段 MyStack segment stack db 256 dup(0) ;栈大小256,初始化为0 MyStack ends ;代码段 MyCode segment START: ;初始化数据段 mov ax, seg MyData mov ds,ax mov es,ax ;初始化堆栈段 mov ax, seg MyStack mov ss,ax mov ah,09H mov dx,offset g_szMsg ;偏移地址,取内容 int 21h ;EXIT mov ax,4c00H int 21h ret MyCode ends end START

本文固定链接: https://blog.050k.com/?p=162 | LseKit's Blog
标签:,

03_16汇编_段寄存器:等您坐沙发呢!

发表评论

快捷键:Ctrl+Enter