寄存器与代码段

汇编语言系列学习笔记:

  • 汇编语言初探
  • 寄存器与代码段(本文)
  • 寄存器与数据段(待完成)
  • 寄存器与栈段(待完成)

在上一篇博文中主要介绍了学习汇编语言的一些必备知识。其中和这篇文章联系比较紧密的是内存地址单元与 CPU 的概念,不熟悉的可以先行阅读上一篇博文。

在学习寄存器这两章内容的时候,首先要牢记一个观点:指令和数据在内存单元中没有任何区别,它们都是一些二进制信息

CPU 在读取内存中二进制信息的时候,将有的信息看作指令,有的信息看作数据。

在接下来的三篇博文中将具体介绍 CPU 到底是根据什么来做出的这种区分的。

一、寄存器的概念

寄存器是位于 CPU 内部的一种带有存储性质的器件。寄存器在汇编语言中有着举足轻重的地位,因为程序员可以通过改变寄存器中的内存来实现对 CPU 的控制

8086CPU 中总有有 14 种不同种类的寄存器,它们分别是:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。

它们最大能存储 16bit 的数据。

接下来的几篇文章将逐个的介绍这些寄存器的作用。

(一)通用寄存器

8086CPU 中的通用寄存器有下面四种:

  • AX(accumulator):累加寄存器,常用于运算。
  • BX(base):基址寄存器,常用于地址索引。
  • CX(count):计数寄存器。
  • DX(data):数据寄存器,常用于数据传递。

从上图可知,一个 16 位寄存器可以存储一个 16 位数据。由于 8086CPU 上一代的寄存器都是 8 位的,为了保证兼容性,一个 16 位通用寄存器通常还能当做两个独立的 8 位寄存器使用。

比如,AX 可以分为 AH 和 AL,见下图:

AX 的低 8 位(0 位 ~ 7 位)构成了 AL 寄存器,高 8 位(8 位 ~ 15 位)构成了 AH 寄存器。

8086CPU 可以一次性处理这两种不同长度的数据,分别称为:

  • 字(word):16 位
  • 字节(byte):8 位

(二)段寄存器和指针寄存器

8086CPU 中的段寄存器和指针寄存器有下面四种:

  • CS(code segment):代码段寄存器
  • DS(data segment):数据段寄存器
  • SS(stack segment):栈段寄存器
  • ES(extra segment):附加段寄存器
  • IP(instruction pointer):指令指针寄存器
  • SP(stack pointer):栈指针寄存器
  • BP(base pointer):基址指针寄存器

其中 CS 和 IP 是本文着重要介绍的,其余的将在后面学习到。

首先想一想 “ 段 ” 这个概念从何而来?这就要从 8086CPU 与内存之间的地址总线宽度说起了。

8086CPU 的地址总线宽度是 20 位,即一次性可以传送 20 位的地址,理论上能达到 1MB 的寻址能力。但是我们上面介绍的寄存器最高也只有 16 位,无法直接生成 20 位的地址。

为了不白白的浪费 4 位地址总线,在 8086CPU 中采用一种将两个 16 位地址合成一个 20 位地址的方法。

如图所示,在 8086 中是通过一个地址加法器来完成的这种转换:物理地址(20 bit) = 段地址(16 bit) × 16 + 偏移地址(16 bit)。其中段地址就存储在段寄存器中。而偏移地址则保存在指针寄存器中。

这个公式隐含着两个注意点:

  • 因为 段地址 × 16 的大小必然是 16 的倍数,所以一个段内存空间的起始地址必然也是 16 的倍数。
  • 因为偏移地址为 16 位,所以一个段的最大空间只有 216 B = 64 KB。

这里有一个因果关系要明确:首先是因为 CPU 与内存之间的地址总线的宽度(1MB)高于 CPU 一次性能处理、传输、暂存的最大宽度(64KB),为了不浪费 CPU 的寻址能力,才会有 物理地址(20 bit) = 段地址(16 bit) × 16 + 偏移地址(16bit) 这样的一个转换机制。

所以我在想,要是做个假设,CPU 中的寄存器都是 20 bit,或者地址总线只有 16 bit 的话,是不是也许就没有段地址这个说法了(这是我个人的思考,如果有不对的地方,烦请指正~)。

二、代码段

上面讲了一些比较常用的寄存器,其中 CS 和 IP 寄存器是两个最为关键的寄存器,它们这两个寄存器中的值组合起来 CS:IP 表示了 CPU 当前要读取指令的地址。

也就是说:在 8086PC 机中,任意时刻,CPU 将 CS:IP 指向的内容当做指令执行。

为了接下来的讲解,先学习几条会用到的汇编指令:

  • mov ax,4E20H:将 4E20H 这个数送入寄存器 AX。
  • add ax,1406H:将寄存器 AX 中的数值加上 1406H。

假设现在有下面四条汇编指令:

  • mov ax,0123H
  • mov bx,0003H
  • mov ax,bx
  • add ax,bx

对应的机器指令为:

  • B8H 23H 01H
  • BBH 03H 00H
  • 89H D8H
  • 01H D8H

现在的一个编程需要是想让 CPU 顺序执行上面四条指令,可以将这四条指令的机器码存放在一组连续的、起始地址为 16 的倍数的一组内存单元中,如下图:

这样我们就定义了一个所谓的代码段,这个代码段从内存的第 20000H 号单元开始,存放了 10 字节的指令。

要想让 CPU 执行这段代码,首先需要将 CS 的内容置为 2000H,IP 的内容置为 0000H。这样 CPU 就从内存单元的 20000H 处开始执行。

下面以一张动图来演示 CPU 执行第一条指令时 CPU 与内存的信息交互情况:

(动图演示)

                

这张动图清晰的展示了 CPU 是如何执行处于上面内存代码段中的第一条指令(隐藏了很多的细节)。由于指令的执行过程类似,加上制作动图比较耗费时间,就省略了剩余的三条指令的执行过程(- -!)。

三、总结

本篇博文首先介绍了 CPU 中的寄存器种类,通过一个地址转换公式引出了两个重要的寄存器 CS 和 IP。有了这两个寄存器的功能做支持,就可以定义一个存放代码的代码段,并让 CPU 去执行这个代码段。

最后还是引出文章开始的一句话:指令和数据在内存中没有区别,它们都是一些二进制信息,把这些二进制信息看作指令还是数据,是让编程人员通过控制 CPU 中的寄存器来完成的。

(完)

原文地址:https://www.cnblogs.com/KKSJS/p/9939908.html

时间: 2024-10-09 05:52:50

寄存器与代码段的相关文章

段寄存器(8086CPU)和代码段

1.段寄存器 8086CPU有4个段寄存器:CS.DS.SS.ES.当8086CPU访问内存时,由这4个段寄存器提供内存单元的段地址. CS和IP是8086中最关键的寄存器,他们指示了CPU当前要读取指令的地址.CS是代码段寄存器,IP为指令指针寄存器.在8086PC机中,任意时刻,设CS中的内容是M,IP中的内容是N,8086CPU将从内存地址:M*16+N处读取指令并执行.也可以这样表述,8086机中,任意时候,CPU将CS:IP指向的内容当做指令执行,.CPU将CS.IP中的内容当做指令的

代码段中存放数据

1.前面我们写的程序中,只有一个代码段,我们先来在代码段中使用数据,看看和单独一个数据段存放数据有什么差别. 考虑这样一个问题,编程计算以下8个数据的和,结果存放在ax寄存器中: 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H 我们希望循环进行累加,所以要将数据存放在一个连续内存当中,如何将这些数据存储在一组地址连续的内存单元中呢?我们可以用指令一个一个将他们送入地址连续的内存单元,可是这样又存在一个问题,到哪里去找这段内存空间? 从规范的角度讲,

一致代码段和非一致代码段

最近在自己动手写操作系统,计算机其实是一个非常复杂的系统.其中包含了很多历史性的问题,让人感到生僻难懂.在CSDN上看到一篇关于一致代码段和非一致代码段的文章,非常好,收藏起来. 原文链接:http://blog.csdn.net/feijj2002_/article/details/4597174 之所以出现这个定义是因为系统要安全:内核要和用户程序分开..内核一定要安全.不能被用户程序干涉.但是有时候用户程序也需要读取内核的某些数据,怎么办呢?操作系统就引入了访问特权等级(0-3)的机制.

【从头开始写操作系统系列】一致代码段与非一致代码段

上几篇文章,我们一直在讨论的都是 GDT 相关的一些问题,现在我们知道在系统在从实模式向保护模式跳转时,GDT 是必须要准备的结构.在介绍这一跳转之前,这篇文章我们来介绍两个概念:一致代码段和非一致代码段. 首先,我们先来看几个问题: 一致代码段和非一致代码段是什么? 为什么要有一致代码段和非一致代码段? 系统提供怎样的机制来使用户程序访问内核数据? 程序如何在段与段之间跳转? 接下来,我们将讨论上述这些问题. 特权级 为了更好的理解之后的问题,我们先来讨论一个概念:特权级. 特权级是一种机制来

《一个操作系统的实现》读书笔记--第三章---不同特权级代码段之间的跳转

http://blog.csdn.net/begginghard/article/details/7262901 1.特权级 2.一致代码段和非一致代码段 3.DPL.RPL.CPL分别代表的含义,存储在什么位置,以及它们之间的关系 4.不同特权级数据段之间的访问规则 5.不同特权级代码段之间的转移 6.代码段之间的转移对堆栈的影响 7.结合pmtest5.asm来见证不同特权级代码段之间的跳转 一.特权级在IA32的分段机制下,特权级总共有4个特权级别,从高到低分别是0.1.2.3.数字越小表

一站式linux0.11内核head.s代码段图表详解

阅读本文章需要的基础: 计算机组成原理:针对8086,80386CPU架构的计算机硬件体系要有清楚的认知,我们都知道操作系统是用来管理硬件的,那我们就要对本版本的操作系统所依赖的硬件体系有系统的了解,有了系统的了解后才能全面的管理它,我们对8086,80386CPU架构的计算机硬件体系如果有非常深刻的认识,我们看源代码内核的时候,就可以更可能的以一种开发者的角度去思考代码的作用,先从全局的角度去思考问题,而不是采用一种众人摸象的思维从头看到末尾. 计算机编程C语言基础:linux内核基本都是用C

《80X86汇编语言程序设计教程》十一 32位代码段和16位代码段切换实例

1.  演示32位代码段与16位代码段之间的切换.实现的功能是以十六进制和ASCII码字符两种形式显示从内存地址100000H开始的16个字节的内容. 2.  源代码如下: 1 ;DosTest.Asm 2 ;16位偏移的段间转移指令的宏定义 3 ;使用于16位段,用于跳转到32位目的段 4 ;注意:标号偏移必须在16位二进制符号数数能表示的范围之内 5 JUMP16 macro selector,offsetv 6 db 0eah ;操作码 7 dw offsetv ;16位偏移 8 dw s

操作系统学习(五) 、代码段和数据段描述符

一.代码段和数据段描述符格式 段描述符通用格式如下所示: 代码段和数据段描述符中各个位的含义如下所示: 二.代码段和数据段描述符类型 当段描述符中S标志位(描述符类型)被置位,则该描述符用于代码段或数据段.此时类型字段中最高比特位(第二个双字的位11)用于确定是数据段描述符(复位)还是代码段描述符(置位). 代码段和数据段描述符类型如下所示: 对于数据段描述符,类型字段的低3位(位8,9,10)分别用于表示已访问A,可写W,和扩展方向E,根据可写比特位W的设置,一个数据段可以是只读的,也可以是可

BSS段、数据段、代码段、堆与栈

BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域. BSS是英文Block Started by Symbol的简称.BSS段属于静态内存分配. 数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域. 数据段属于静态内存分配. 代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区 域.这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读