8086所有寄存器简介

8086所有寄存器简介
8086所有寄存器简介

首先浅要介绍一下 Intel CPU 的发展史吧:

Intel CPU 系列,最初是 4 位微处理器 4004,然后到到 8 位微处理器的 8008 ,

再到 8 微微处理器 8080,以及稍后的 16 位微处理器 8086,

由 8086 开始,Intel 进入现在所谓的 x86 时代。

Intel 8086 为 16 位 CPU ,而因为在 8086 之前的 CPU 都是 8 位 CPU,这样也就造成了很多的外设也只支持 8 位,

因此 Intel 紧接着就退出了 8 位的 8088 CPU,因此 Intel 8088 也就可以看做是 8086 的 8 位版本;

如果是但从汇编语言的角度上来说,8086 和 8088 是没有区别的,即 8086 上跑的程序可以不加修改的移植到 8088 ,

8088 上跑的程序也可以不加修改的移植到 8086 上,

当然,还是有些特殊的地方是不同的,而这些基本上在这里可以忽略掉,

在 8088 CPU 之后,Intel 又推出了 80186 ,80286 ,这两款 CPU 均是 16 位 CPU ,

而对于 80186 来说,其与 8086 的区别可以简单的看做是 80186 多了几条指令而已,

而 80286 则不同,80286 的地址总线数目有了变化,

在 8086 , 8088 , 80186 上,CPU 的地址总线都是 20 根,即可最大寻址 220 即达到 1MB 的寻址能力,

而对于 80286 CPU 来说,其地址总线数目达到了 24 根,从而最大寻址能力为 224即 16MB,

由于支持更多的物理内存寻址,因此 80286 便开始成为了多任务,多用户系统的核心。

而后来,Intel 又推出了 80386 ,80386 为 32 位微处理器,Intel 80x86 家族的 32 位微处理器始于 80386;

同时 80386 也完全兼容先前的 8086/8088,80186,80286,并且 80386 全面支持 32 位数据类型和 32 位操作,

并且 80386 的数据总线根数和地址总线根数均达到了 32 根,从而可以最大物理寻址为 232 即 4GB 。

而之后的 80486 也是 32 位微处理器,而后又出来了 Pentium 和 Pentium Pro 等等第五代微处理器,

这些处理器虽然也是 32 位微处理器,但是他们的数据总线和地址总线都有所扩展,

比如 Pentium 的数据总线达到 64 位,而 Pentium Pro 的地址总线位数达到了 36 位。

好,关于 Intel CPU 的介绍就到这里了,下面就要开始回归中心,看 CPU 中的寄存器了,

首先,从学习的角度来说,从 8086/8088 CPU 下手是不错的选择,而我这里选择的也是 8086 CPU 而已,

说实在的,像 80386 CPU 我也还没有研究过,像奔腾这些,呵呵,扯更远了,

说到底也就只能拿 8086 出来晒晒而已,当然,从 8086 开始也是学习的最佳路径。

说了这么久,到底寄存器是什么呢?其实很简单,寄存器就是个存储信息的单元或者说是器件又或者说是容器而已,

就比如内存也是一个存储介质或者说是存储单元而已,其实寄存器从理解上来说和内存差不多,

只不过寄存器(这里讨论的寄存器都是 CPU 中的寄存器,不包括外设上的寄存器)位于 CPU 内部,而内存位于 CPU 外部,而且,寄存器比内存可是珍贵得多啊,就拿内存和硬盘来比,肯定是内存在使用上珍贵得多,是 PC 中的稀有资源,

而寄存器是 CPU 中的稀有资源,内存和寄存器相比就像硬盘和内存相比一样。

而对于一个汇编程序员来说,CPU 中主要可以使用的也就是寄存器而已,汇编程序员可以使用指令来读写 CPU 中的寄存器,从而可以实现对于 CPU 的控制,当然,不同的 CPU ,寄存器的个数和结构都是不一样的,

比如 8086 CPU 中,寄存器的个数也就 14 个而已,

并且 8086 CPU 中所有的寄存器的结构为 16 位,即一个寄存器中可以存放下 2B 即 2 个字节,

而到了 80386 CPU 中,寄存器的个数也比 8086 增多了,比如在 80386 中添加了系统地址寄存器等寄存器,

同时寄存器的结构也变了,比如在 80386 中绝大多数的寄存器为 32 位,而有些寄存器则是 16 位。

8086 CPU 中寄存器总共为 14 个,且均为 16 位。

即AX,BX,CX,DX,SP,BP,SI,DI,IP,FLAG,CS,DS,SS,ES共 14 个。

而这 14 个寄存器按照一定方式又分为了通用寄存器,控制寄存器和段寄存器。

通用寄存器:

AX,BX,CX,DX 称作为数据寄存器:

AX (Accumulator):累加寄存器,也称之为累加器;

BX (Base):基地址寄存器;

CX (Count):计数器寄存器;

DX (Data):数据寄存器;

SP 和 BP 又称作为指针寄存器:

SP (Stack Pointer):堆栈指针寄存器;

BP (Base Pointer):基指针寄存器;

SI 和 DI 又称作为变址寄存器:

SI (Source Index):源变址寄存器;

DI (Destination Index):目的变址寄存器;

控制寄存器:

IP (Instruction Pointer):指令指针寄存器;

FLAG:标志寄存器;

段寄存器:

CS (Code Segment):代码段寄存器;

DS (Data Segment):数据段寄存器;

SS (Stack Segment):堆栈段寄存器;

ES (Extra Segment):附加段寄存器;

通用寄存器

从上面可以知道,在 8086 CPU 中,通用寄存器有 8 个,分别是 AX,BX,CX,DX,SP,BP,SI,DI ,

至于为什么给它们取名做通用寄存器,那是因为,这些个寄存器每一个都有自己专门的用途,

比如 CX 作为计数寄存器,则是在使用 LOOP 指令循环时用来指定循环次数的寄存器,

如果它们每一个都只有一个专用的作用,那就它们只能称之为专用寄存器了,

正是因为这些个寄存器还可以用来传送数据和暂存数据,所以才称它们为通用寄存器。

下面就按顺序来一一介绍这几个通用寄存器了:

数据寄存器(AX,BX,CX,DX):

数据寄存器有 AX,BX,CX,DX 四个组成,

由于在 8086 之前的 CPU 为 8 位 CPU,所以为了兼容以前的 8 位程序,

在 8086 CPU 中,每一个数据寄存器都可以当做两个单独的寄存器来使用,

由此,每一个 16 位寄存器就可以当做 2 个独立的 8 位寄存器来使用了。

AX 寄存器可以分为两个独立的 8 位的 AH 和 AL 寄存器;

BX 寄存器可以分为两个独立的 8 位的 BH 和 BL 寄存器;

CX 寄存器可以分为两个独立的 8 位的 CH 和 CL 寄存器;

DX 寄存器可以分为两个独立的 8 位的 DH 和 DL 寄存器;

除了上面 4 个数据寄存器以外,其他寄存器均不可以分为两个独立的 8 位寄存器;

注意在上面标志中的“独立”二字,这两个字表明 AH 和 AL 作为 8 位寄存器使用时,

可以看做它们是互不相关的,也就是看做两个完全没有联系的寄存器 X 和 Y 即可,

比如指令 MOV AH , 12H ,CPU 在执行时根本就不会知道 AL 中是什么鬼东西,因为它只认识 AH 。

下面给出一幅 16 位数据寄存器的结构图:

表示 16 位寄存器 AX 可以表示成两个 8 位寄存器,

其中 AH 表示高位的 8 位寄存器,AL 表示低位的 8 位寄存器。

AX 寄存器:

如上所说,AX 的另外一个名字叫做累加寄存器或者简称为累加器,其可以分为 2 个独立的 8 位寄存器 AH 和 AL;

在写汇编程序时,AX 寄存器可以说是使用率最高的寄存器(不过,总共才那么 14 个寄存器,哪一个不经常使用咯?),

既然 AX 是数据寄存器的话,那么理所当然,其可以用来存放普通的数据,由于其是 16 位寄存器,

自然也就可以存放 16 位数据,但是因为其又可以分为 2 个独立的 8 位寄存器 AH 和 AL ,

所以,在 AH 和 AL 中又可以独立的存放 2 个 8 位的数据,

可以有以下代码(即将 AX 当做普通的寄存器使用,即可以用来暂存数据):

MOV AX,1234H ;向寄存器 AX 传入数据 1234H

MOV AH,56H ;向寄存器 AX 的高 8 位寄存器 AH 中传入数据 56H MOV AL,78H;向寄存器 AX 的低 8 位寄存器 AL 中传入数据 78H 3 条语句的执行过程如下:

而既然 AX 又被称作为累加器,自然其还有一点点特殊的地方的:

AX 寄存器还具有的特殊用途是在使用 DIV 和 MUL 指令时使用,

DIV 在 8086 CPU 中是除法指令,而在使用除法的时候有两种情况,即除数可以是 8 位或者是 16 位的,

而且除数可以存放在寄存器中或者是内存单元中,而至于被除数的话,自然,应该由 AX 来代替了,

当除数是 8 位时,被除数一定会是 16 位的,并且默认是放在 AX 寄存器中,

而当除数是 16 位时,被除数一定是 32 位的,因为 AX 是 16 位寄存器,自然,放不下 32 位的被除数,

所以,在这里还需要使用另一个 16 位寄存器 DX ,

其中 DX 存放 32 位的被除数的高 16 位,而 AX 则存放 32 位的被除数的低 16 位,

同时,AX 的作用还不仅仅是用来保存被除数的,当除法指令执行完成以后,

如果除数是 8 位的,则在 AL 中会保存此次除法操作的商,而在 AH 中则会保存此次除法操作的余数,

当然,如果除数是 16 位的话,则 AX 中会保存本次除法操作的商,而 DX 则保存本次除法操作的余数。

上面介绍的是 AX 寄存器在除法操作中的应用,下面还需要介绍一下 AX 在乘法操作中的应用,

当使用 MUL 做乘法运算时,两个相乘的数要么都是 8 位,要么都是 16 位,

如果两个相乘的数都是 8 位的话,则一个默认是放在 AL 中,

而另一个 8 位的乘数则位于其他的寄存器或者说是内存字节单元中,

而如果两个相乘的数都是 16 位的话,则一个默认存放在 AX 中,

另一个 16 位的则是位于 16 的寄存器中或者是某个内存字单元中。

同时,当 MUL 指令执行完毕后,如果是 8 位的乘法运算,则默认乘法运算的结果是保存在 AX 中,

而如果是 16 位的乘法运算的话,则默认乘法运算的结果有 32 位,

其中,高位默认保存在 DX 中,而低位则默认保存在 AX 中。

AX 寄存器在 DIV 指令中的使用:

MOV DX,0H ;设置 32 位被除数的高 16 位为 0H MOV AX,8H ;设置 32 位被除数的低 16 位为 8H MOV BX,2H ;设置 16 位除数为 2H

DIV BX ;执行计算

4 条语句的执行过程如下:

AX 寄存器在 MUL 指令中的使用:

MOV AX,800H ;设置 16 位乘数为 800H

MOV BX,100H ;设置 16 位乘数为 100H

MOV DX,0H ;清空用来保存乘法结果的高 16 位MUL BX ;执行计算

4 条语句的执行过程如下:

BX 寄存器:

首先可以明确的是,BX 作为数据寄存器,表明其是可以暂存一般的数据的,

即在某种程度上,它和 AX 可以暂存一般性数据的功能是一样的,

其同样为了适应以前的 8 位 CPU ,而可以将 BX 当做两个独立的 8 位寄存器使用,即有 BH 和 BL,

除了暂存一般性数据的功能外,BX 作为通用寄存器的一种,BX 主要还是用于其专属功能–寻址(寻址物理内存地址)上,BX 寄存器中存放的数据一般是用来作为偏移地址使用的,何为偏移地址呢?

既然是偏移地址的话,当然得有一个基地址了,而这个基地址其实就是段地址,这里就涉及到了段寄存器,

当然,在介绍 BX 寄存器的时候,我不会去介绍段寄存器,上面提到 BX 的主要功能是用在寻址上,

那么,其是如何寻址的呢?

对于寻址这个话题,我会在我的下一篇博文中作出详细的介绍,

而这里,我只点一下,在 8086 CPU 中,CPU 是根据 <段地址:偏移地址> 来进行寻址操作的,

而 BX 中存放的数据表示的是偏移地址的话,自然,便可以通过 <段地址:[BX]> 的方式来完成寻址操作了。

为了介绍 BX 在寻址当中的作用,下面我给出一副示意图:

上面的示意图表示:可以令 BX = 2,然后通过 DS : [BX] 来访问到内存中段地址为 DS,且偏移量为 2 的内存单元了。

上面介绍的这种寻址方式是 BX 在寻址中最最简单的应用了,而对于稍微复杂的寻址方式,

还可以依赖于 SI,DI,BP 等寄存器来一起完成,当然,这会是下一篇博文将要介绍的内容了。

BX寄存器在寻址中的使用:

MOV BX,5H

MOV AH,11H

MOV AH,[BX] ;设置 AX 的值为偏移地址为 BX 中的值时所代表的内存单元3 条语句的执行过程如下:

从上图可以看出,在偏移地址为 5 时的内存单元中的数据位 BBH,

而从这幅图上面就可以看出,确实通过 [BX] 找到了偏移地址为 5 处的内存单元,并且将内存单元移入了 AH 中。

CX 寄存器:

CX 寄存器作为数据寄存器的一种呢,其同样具有和 AX,BX 一样的特点,即可以暂存一般性的数据,

同时还可以将其当做两个独立的 8 位寄存器使用,即有 CH 和 CL 两个 8 位寄存器,

当然,CX 也是有其专门的用途的,CX 中的 C 被翻译为 Counting 也就是计数器的功能,

当在汇编指令中使用循环 LOOP 指令时,可以通过 CX 来指定需要循环的次数,

而 CPU 在每一次执行 LOOP 指令的时候,都会做两件事:

一件就是令 CX = CX – 1,即令 CX 计数器自动减去 1;

还有一件就是判断 CX 中的值,如果 CX 中的值为 0 则会跳出循环,而继续执行循环下面的指令,

当然如果 CX 中的值不为 0 ,则会继续执行循环中所指定的指令。

CX寄存器在循环中的使用(输出 5 个白底蓝字的 A):

MOV AX,0B800H

MOV DS,AX ;使用 80x25 彩色字符模式,内存地址 0xB8000 - 0xBFFFFF MOV BX,0 ;从 0xB8000 开始

MOV CX,5H ;循环 5 次

MOV DX,41H ;A 的16 进制为 41H

MOV AX,01110001B ;显示白底蓝字

s: MOV [BX],DX ;显示 ASCII 字符

ADD BX,1

MOV [BX],AX ;设置字符显示属性

ADD BX,1

LOOP s

语句的执行过程如下:

DX 寄存器:

DX 寄存器作为数据寄存器的一种,同样具有和 AX,BX,CX 一样的特点,即可以暂存一般性的数据,

同时还可以将其当做两个独立的 8 位寄存器使用,极有 DH 和 DL,

同时,DX 作为一个通用寄存器的话,自然其还有其他的用途,而关于 DX 在其他方面的用途,

其实在前面介绍 AX 寄存器时便已经有所介绍了,

即当在使用 DIV 指令进行除法运算时,如果除数为 16 位时,被除数将会是 32 位,而被除数的高 16 位就是存放在 DX 中,

而且执行完 DIV 指令后,本次除法运算所产生的余数将会保存在 DX 中,

同时,在执行 MUL 指令时,如果两个相乘的数都是 16 位的话,

那么相乘后产生的结果显然需要 32 位来保存,而这 32 位的结果的高 16 位就是存放在 DX 寄存器中。

DX 寄存器在 DIV 指令中的使用(即 2293812 / 256 = 8960 余数为 52):

MOV DX,0023H ;32 位被除数的高 16 位

MOV AX,0034H ;32 位被除数的低 16 位

MOV BX,100H ;16 的除数

DIV BX

语句的执行过程如下:

可以看到在语句结束以后,AX = 2300H 即十进制的 8960,而 DX = 34H即十进制的 52 和我们的结果是一致的。

DX 寄存器在 MUL 指令中的使用则各位可以参考在 AX 中 MUL 运算的使用,这里就不贴出来了。

指针寄存器(BP,SP):

BP 寄存器:

8086 CPU 中的指针寄存器包括两个,即 SP 和 BP ,在这里呢,我先只对 BP 寄存器做介绍,

因为 SP 寄存器实质上必须和 SS 段寄存器一起使用,所以,我将会把 SP 寄存器留到后面和 SS 段寄存器一起作介绍。

BP (Base Pointer)也就是基指针寄存器,它和其他的几个用来进行寻址操作所使用的寄存器(还有 BX,SI,DI)没有太大的区别,关于 SI 和 DI 寄存器的下面请见下文。

首先,BP 寄存器作为通用寄存器的一种,说明其是可以暂存数据的,而后,BP 又不是数据寄存器,

也就意味着其不能分割成 2 个独立的 8 位寄存器使用,

而后当以[…] 的方式访问内存单元而且在[…] 中使用了寄存器 BP 的话,

那么如果在指令中没有明确或者说是显示的给出段地址时,

段地址则使用默认的 SS 寄存器中的值(BX,SI,DI 会默认使用 DS 段寄存器),

比如 DS:[BP] 则在这里明确给出了段地址位于 DS 中,

所以,这里代表的内存单元即是段地址为 DS ,偏移量为 BP 寄存器中的值的内存单元,

而如果单单是使用 [BP] 的话,则代表的内存单元是段地址为 SS,偏移量为 BP 寄存器中的值的内存单元。

并且 BP 寄存器主要适用于给出堆栈中数据区的偏移,从而可以方便的实现直接存取堆栈中的数据,

至于堆栈的话,会在后面的博文中介绍。

在 8086 CPU 中,只有 4 个寄存器可以以[…]的方式使用,这四个寄存器分别是 BX,SI,DI,BP。

下面的 Demo 是BX寄存器在寻址中的使用:

MOV BP,0

MOV AX,[BP] ;将 SS:[BP] 代表的内存单元移入 AX 中

MOV AX,CS:[BP] ;将 CS:[BP] 代表的内存单元移入 AX 中

语句的执行过程如下:

变址寄存器(SI,DI):

首先,变址寄存器和上面介绍的指针寄存器(也就是 BP 和 SP),它们的功能其实都是用于存放某个存储单元地址的偏移,

或者是用于某组存储单元开始地址的偏移,即作为存储器指针使用,当然,由于变址寄存器和指针寄存器都是属于通用寄存器,

所以它们也可以保存算术结果或者说是具有暂存数据的功能,但是因为它们不是数据寄存器,所以无法分割成 2 个独立的 8 位寄存器使用,

关于变址寄存器和指针寄存器的详细使用,笔者将会在下一篇博文中作出最详细的介绍,

SI (Source Index) 是源变址寄存器,DI (Destination Index) 即是目的变址寄存器,

8086 CPU 中的 SI 寄存器和 DI 寄存器其实和 BX 寄存器的功能是差不多的,

只不过 SI 寄存器和 DI 寄存器均不是数据寄存器,所以它们不能够拆分为 2 个独立的 8 位寄存器,

而这也就是 SI 寄存器和 DI 寄存器与BX 寄存器所不同的地方,

既然,SI,DI 两个寄存器的功能和 BX 差不多,自然,SI 和 DI 中也是可以暂存一般性数据的,

同时,通过使用 SI 和 DI 寄存器也是可以用来完成寻址操作的。

比如下面的代码就是可行的:

MOV SI,0 ;初始化偏移地址为 0

MOV AX,[SI] ;将段地址为 DS 偏移地址为 SI 的内存单元中的值移入 AX 中MOV AX,DS:[SI] ;将段地址为 DS 偏移地址为 SI 的内存单元中的值移入 AX 中MOV AX,SS:[SI] ;将段地址为 SS 偏移地址为 SI 的内存单元中的值移入 AX 中

MOV DI,0 ;初始化偏移地址为 0

MOV AX,[DI] ;将段地址为 DS 偏移地址为 DI 的内存单元中的值移入 AX 中MOV AX,DS:[DI] ;将段地址为 DS 偏移地址为 DI 的内存单元中的值移入 AX 中MOV AX,SS:[DI] ;将段地址为 SS 偏移地址为 DI 的内存单元中的值移入 AX 中

其他寄存器(CS,IP,SS,SP,DS,ES)

由于段寄存器总是和其他一些像指针寄存器,变址寄存器,控制寄存器一起使用,

所以在这里,我并不会单独介绍段寄存器,而是将段寄存器和一些其他的常用寄存器搭配介绍。

由于下面的介绍中会涉及到很多关于段和栈的概念,而段和栈的介绍又都必须关系到物理内存,

所以在介绍段寄存器以及其他一些呈协作关系的寄存器之前,还是先来介绍一下这几个基本的概念比较好。

8086 CPU 访问内存(物理地址):

当 CPU 需要访问一个内存单元时,需要给出内存单元的地址,

而每一个内存单元在物理内存空间中都有一个唯一的地址,

即可以通过这个地址定位到内存单元,而这个地址即为物理地址。

CPU 通过地址总线将一个内存单元的物理地址送入存储器,

而后 CPU 便可以通过这个物理地址来访问这个物理地址所指向的内存单元了。

那么这个物理地址在 CPU 中是如何形成的呢?

首先,我们知道 8086 CPU 的地址总线是 20 根,

即每次都可以传输 20 位的地址,从而寻址能力有 220也就是 1MB 的大小,

但是 8086 CPU 的寄存器只有 16 位,也就是在 8086 CPU 的内部,

一次性处理,传输,暂存的地址都只能是 16 位,

即 8086 CPU 不能完整的保存下一个物理地址(物理地址为 20 位),

如果单单以最简单的方式(即直接用 16 位寄存器来保存物理地址)的话,那么,寻址能力只有 216,也就是 64KB,

如果真以如此简单的方式的话,那么地址总线还需要 20 根干嘛呢?而且,难不成我们以后的内存就是 64KB 了吗?

当然不是的,8086 CPU 在这里采取了一定的措施从而使其寻址能力达到 1MB 。

8086 CPU 在内部通过两个 16 位的地址进行合成从而形成一个 20 位的物理地址,由此,8086 CPU 的寻址能力便可以达到 1MB 。那么 8086 CPU 又是如何将两个 16 位的地址合成为一个20 位的物理地址的呢?

当 CPU 在访问内存时,其会使用一个 16 位的基地址,然后再使用一个 16 位的偏移地址,

通过将基地址和偏移地址传入 8086 CPU 的地址加法器中进行合成即可以构造出 20 位的物理地址。

至于合成的方式如下:

基地址其实是通过一个 16 位的段地址来形成的,将一个段地址左移 4 位即形成了基地址,

而至于偏移地址的话,自然不必多说,为 16 位,通过将基地址和偏移地址相加便形成了 20 位的物理地址。

下面给出一幅示意图来表示物理地址的合成:

段:

至于段的话,其实在物理内存中是没有段这一概念的,事实上,段的概念来自于 CPU ,

因为 CPU 拥有段寄存器,既然在 CPU 中拥有了段寄存器,自然,在 CPU 中就肯定有段的概念了,

其实段也就是在编程时,我们将若干个地址连续的内存单元看做是一个段,

然后通过将一个段地址左移 4 位形成基地址,再通过这个基地址来定位这个段的起始地址,

然后,再通过偏移地址便可以精确定位到段中的内存单元了,由于段的起始地址是一个段地址左移 4 位,

所以很明显,段的起始地址肯定是 16 的倍数,而且由于一个段内部,只能通过偏移地址来定位,

而偏移地址为 16 位,所以一个段的长度也就是 216也就是 64KB 的大小。

在编程时,可以讲一段内存定义成为一个段,而这里,我们又可以引出数据段,代码段,栈段这三种类型的段。

何为数据段呢?其实就是我们自个儿定义一段内存(当然段起始地址肯定是 16 的倍数,并且段长度 <= 64KB),

然后我们在这个段里头存放我们所需要使用的数据,这就是数据段;

何为代码段呢?其实也很简单,也是我们自己在编程的时候定义一段内存,然后这段内存用来存放我们的代码(也就是指令),

既然是存放的代码,自然就称之为代码段;

何为栈段呢?至于栈段的话,有接触过数据结构的朋友应该是很清楚栈的,而这里我们也就是在内存中分配出一个段,

然后将这个段当做栈来使用,对于栈的介绍,详见下文;

这里呢,顺便还点出几个关于段寄存器的内容,当然下文还会详细介绍的,

首先,对于任何一个段来说,均有段地址,而这些段地址是存放在段寄存器中(段寄存器的作用也在于此),

但是对于不同的段,它们默认的段地址存放在不同的段寄存器中,像

数据段来说,它的段地址存放在 DS (Data Segment)寄存器中,

代码段的段地址存放在 CS (Code Segment)寄存器中,

栈段的段地址存放在 SS (Stack Segment)寄存器中。

下面给出一幅在段中寻址的示意图:

上面的示意图中,通过将段地址左移四位,然后与偏移地址相加便可以得到 20 位的物理地址了。

栈:

8086 CPU 中提供了对栈的支持,并且其还提供了相应的指令来以栈的方式访问内存空间。

什么是栈?

通过上面在段中的介绍,栈其实就是一个段,再说白一点,也就是一块内存,当然,这块内存是一块连续的内存。既然栈是一个段的话,那么当然就可以以使用段的方式来使用栈,当然,除了像段一样的使用栈以外,

栈还提供了其特殊的访问方式(如果和段一模一样的话,那还需要栈干吗呢?),

众所周知,栈是先进后出类型的数据结构,在 8086 CPU 中也是如此,

可以通过”PUSH“指令将数据压入栈中,然后再通过”POP“指令将栈顶的元素取出来。

下面给出一幅示意图来描述栈:

即通过 PUSH 10 来将元素 10 放入栈中,因为,先前栈中没有任何数据,所以,10 就会作为栈顶元素存在,

然后再在栈中压入元素 20 ,此时,栈顶中的元素就是 20 了,然后再使用 POP 指令将栈顶元素取出,

此时取出的栈顶元素是 20 ,取出 20 后,栈中便只剩下 10 了,自然 10 就成为了栈顶,

最后再通过 POP 指令将栈顶 10 取出,此时,栈便变成了空栈了。

好了,在介绍段寄存器之前的基础知识介绍就到这里了,下面开始正式介绍段寄存器以及与它们协作使用的寄存器。CS 寄存器和 IP 寄存器:

经过前面对段的介绍,相信各位朋友对段寄存器应该也有一定的了解了,

下面将要介绍的是一组非常非常重要的寄存器,即 CS:IP 。

CS:IP 两个寄存器指示了 CPU 当前将要读取的指令的地址,其中 CS 为代码段寄存器,而 IP 为指令指针寄存器。

什么叫做指示了 CPU 当前将要读取的指令呢?在 8086 CPU 中,为什么 CPU 会自动的执行指令呢?

这些指令肯定是存放在内存中的,但是 CPU 怎么知道这些指令存放在内存的那个位置呢?

比如,我有下面的两条指令要执行:

MOV AX,1234H

MOV BX,AX

而假设这两条指令在内存中存放为:

很显然, 1000H:0000H 指向的是 MOV AX,1234H 的首地址,

如果 CPU 要读取到我的指令的话,很显然,必须要知道地址 1000H:0000H ,

然后 CPU 就可以根据这个首地址,将汇编指令 MOV AX,1234H所对应的机器码读入到 CPU 的指令寄存器中,

最后便可以在 CPU 中进行处理了。

但关键是 CPU 如何知道我的 1000H:0000H 这个首地址?

其实这就需要使用到 CS:IP 这个寄存器组了。

当我们运行一个可执行文件时,很明显,我们需要另外一个程序来将这个可执行文件加载到内存当中,

关于这个加载可执行文件的程序,我们在这里不管他,点一下即可,

一般是通过操作系统的外壳程序(也就是传说中的 Shell 程序),

Shell 将可执行文件加载到内存中以后,就会设置 CPU 中的两个寄存器,

即设置 CS:IP 两个寄存器指向可执行文件的起始地址,此后 CPU 便从这个起始地址开始读取内存中的指令,并且执行,

比如我们在写汇编程序时,通常会使用 START 标记,其实这个标记就是用来标记起始地址的,

当将一个汇编程序编译,连接成可执行文件以后,再通过操作系统的 Shell 程序将可执行文件加载到内存中以后,

这个 START 所标记处的地址就是整个可执行文件的起始地址了。

也就是说,当一个可执行文件加载到内存中以后,CS:IP 两个寄存器便指向了这个可执行文件的起始地址,

然后 CPU 就可以从这个起始地址开始往下读取指令,

当读取完指令后,CS:IP 将会自动的改变,基本上是改变 IP ,从而指向下一条要读取的指令,这样就可以执行这个可执行文件了。最后再对 CS:IP 总结一下:

1.你想让 CPU 执行哪行指令,你就让 CS:IP 指向保存有指令的那块内存即可。

2.任何时候,CS:IP 指向的地址中的内容都是 CPU 当前执行的指令。

下面我们来看一个 Demo,并详细观察其执行的过程:

ASSUME CS:CODES

CODES SEGMENT

START:

MOV AX,1234H

MOV BX,AX

MOV AH,4CH

INT 21H

CODES ENDS

END START

语句的执行过程如下:

从上面的截图中可以看出,当我使用 Shell (在 DOS 下也就是 Command 命令解释器)将可执行文件加载进内存后,可以看到,整个程序的起始地址为 0C54H : 0000 H ,并且,可以看到 CS 的地址为 0C54H ,IP 的地址为 0000H,这正好吻合我们上面对 CS:IP 的分析,很明显,CPU 将会读取 MOV AX ,1234H到 CPU 中并且执行,

然后我们继续向下看:

可以看到,我们单步执行后,AX 中的值编成了 1234H ,而 IP 寄存器中的值变成了 0003H,

对于 AX 中的值的改变,我们是能够理解的,但是 IP 中的值为什么会从 0000H 变到 0003H 呢?

从最上面的一幅关于指令在内存中的存放可以看出 MOV AX ,1234H在内存中需要 3 个内存单元存放,

也就是 CPU 为了执行 MOV AX ,1234H这条指令,已经将内存中相对应的 3 个内存单元读入内存中了,

执行完这条指令后,自然,CPU 就要将偏移地址向下移动 3 个单元,从而使得 CS:IP 指向下一条需要执行的指令了,为了更深刻的理解,我们再来继续看执行过程,

从最上面的一幅关于指令在内存中的存放可以看出 MOV BX ,AX在内存中只占 2 个内存单元,

这也就是为什么 IP 这一次只向下移动了 2 个单元的缘故。

关于 CS: IP 的遐想:

从上面关于 CS:IP 的介绍中,我们可以大胆的猜想,我们只需要通过手动的改变 CS:IP 所指向的内存地址,

让 CS:IP 指向我们另外的代码,那么我们就可以让 CPU 执行我们自己指定的代码了。

即可以通过修改 CS:IP 来达到我们想要让 CPU 干什么它就干什么的目的。

上面的虽然是遐想,但是大家要相信,我们写的是汇编,不是 JAVA 也不是 NET ,

所以我们还真的可以达到上面的目的,也就是说我们的遐想其实是可以实现的,当然这还是有一定的限制的,

关于这个遐想呢,可能会在我后续的博文中有所介绍,不过感兴趣的当然可以自己去尝试了,蛮有味的哦。

SS 寄存器和 SP 寄存器:

根据前面对栈的介绍,相信各位对栈也肯定是有一定了解了的,更何况,估计大家也是职场打滚多年的,

要是栈都没用过的话,那也确实蛮悲剧的,所以,我在这里也不会对栈做十分详细的介绍了,

但是,最基本的介绍还是要的,毕竟在底层的话,不像高级语言那么方便,可以直接一个 Stack 就 OK 的,

在底层涉及的是栈在内存中的具体实现。

不知道,大伙有没有注意笔者在本篇博文的上面介绍关于栈的知识时,我并没有提到如何找到这个栈,

我只提到了一个栈就是先进后出操作,同时可以使用”PUSH“和”POP“指令,

然后就是稍微带了一下 SS 这个寄存器的介绍,

我们虽然在内存中是可以方便的定义一个栈了,但是,我们为什么要定义这么一个栈呢?

自然,是为了操作方便,同时提供给 CPU 使用的,

既然 CPU 要使用的话,自然,CPU 又必须根据一定的方式找到这个栈,

而这就需要使用 SS 和 SP 寄存器了。

同时,一个栈也就是一块内存区域,通过上面的介绍,我们也知道了如果要在一块内存中精确地定位到内存单元的话(寻址),

我们必须要有基地址(也就是段地址左移 4 位)和偏移地址,自然,要在一个栈中寻址的话,也需要段地址和偏移地址,

而对于一个栈来说,我们使用的最多的是什么呢?

当然是栈顶了,因为只有栈顶可以用来存取数据,所以对于一个栈来说,我们只需要有栈顶的段地址和偏移地址即可,

而对于栈顶的段地址,其是存放在段寄存器 SS 中的,而对于栈顶的偏移地址,其则是存放在 SP 寄存器中的。

记住,在任何时刻,SS:SP 都是指向栈顶元素。

其实关于栈的使用还是比较简单的,但是要注意的是 8086 CPU 并不会保证我们对栈的操作会不会越界。

所以我们在使用栈的时候需要特别注意栈的越界问题。

当使用PUSH 指令向栈中压入 1 个字节单元时,SP = SP - 1;即栈顶元素会发生变化;

而当使用PUSH 指令向栈中压入 2 个字节的字单元时,SP = SP – 2 ;即栈顶元素也要发生变化;

当使用POP 指令从栈中弹出 1 个字节单元时, SP = SP + 1;即栈顶元素会发生变化;

当使用POP 指令从栈中弹出 2 个字节单元的字单元时, SP = SP + 2 ;即栈顶元素会发生变化;

下面通过一个 Demo 来介绍栈的使用:

ASSUME CS:CODES

CODES SEGMENT

START:

MOV AX,1000H ;首先是定义好栈的段地址

MOV SS,AX

MOV AX,10H ;再定义好栈的长度(初始时刻的栈顶偏移地址即栈的长度) MOV SP,AX

MOV AX,0001H

PUSH AX

MOV AX,0002H

PUSH AX

MOV AX,0003H PUSH AX

MOV AX,0004H PUSH AX

MOV AX,0005H PUSH AX

POP AX

POP AX

POP AX

POP AX

POP AX

MOV AH,4CH

INT 21H CODES ENDS

END START

然后我们来看栈在内存中的结构图:

语句的执行过程如下:

首先我们来看尚未执行上述任何指令时栈中的数据情况:

然后我们再来依次执行上述指令:

从上副截图中可以看出已经设置好了 SS:SP ,也就是栈已经设置 OK 了,

下面开始往栈中压入数据了,

由于我们压入栈中的数据为字数据,即占 2 个内存单元,所以,每次 SP = SP – 2 ;将 5 个字型数据压入栈中后,我们可以来查看栈中的数据了,

因此,在内存中的一个好看点的结构图如下所示:

下面开始进行出栈操作了

由于我们弹出栈时的数据为字数据,即占 2 个内存单元,所以,每次 SP = SP + 2 ;

将 5 个字型数据全部弹出栈中后,我们可以来查看栈中的数据了,

可以看到 SP 变成了初始状态了,也就是说栈中所有的数据已经全部弹出了,虽然我们查看内存时看到的不是 0 ,

但是我们看到的这些数据都是无效的,我们这里不理会。

DS 寄存器和 ES 寄存器:

DS 寄存器和 ES 寄存器都属于段寄存器,其实它们和 CS 寄存器以及 SS 寄存器用起来区别不大,

既然是段寄存器的话,自然它们存放的就是某个段地址了。

通过上面对基础知识的介绍呢,我们已经知道,如果 CPU 要访问一个内存单元时,

我们必须要提供一个指向这个内存单元的物理地址给 CPU ,

而我们也知道在 8086 CPU 中,物理地址是由段地址左移 4 位,然后加上偏移地址形成的,

所以,我们也就只需要提供段地址和偏移地址即 OK 。

8086 CPU 呢,提供了一个 DS 寄存器,并且通常都是通过这个 DS 段寄存器来存放要访问的数据的段地址。

DS(Data Segment):很显然,DS 中存放的是数据段的段地址。

但是这里不得不再点一下,那就是我们对段的支持是在 CPU 上体现的,而不是在内存中实现了段,

所以事实上我们使用的段其实是一个逻辑概念,即是我们自己定义的,

再说白了,我定义一个段,我说它是数据段那它就是数据段,我说它是代码段那么它就是代码段,

它们其实都是一块连续的内存而已,至于为什么要区分为数据段和代码段,

很明显,是用来给我们编程提供方便的,即我们在自己的思想上或者说是编码习惯上规定,

数据放数据段中,代码放代码段中。而我们在使用数据段的时候,为了方便或者说是代码的编写方便起见,

我们一般把数据段的段地址放在 DS 寄存器中,当然,如果你硬要觉得 DS 不顺眼,那你可以换个 ES 也是一样的,

至于 ES(Extra Segment)段寄存器的话,自然,是一个附加段寄存器,如果再说得过分点,

就当它是个扩展吧,当你发现,你几个段寄存器不够用的时候,你可以考虑使用 ES 段寄存器,

在使用方式上,则和其他的段寄存器没什么区别。

下面看一个介绍使用 DS 寄存器的 Demo:

ASSUME CS:CODES

CODES SEGMENT

START:

MOV AX,1000H

MOV DS,AX

MOV AL,1

MOV BX,0

MOV CX,5 ;设计一个循环,让其循环 5 次 s: MOV [BX],AL ;这里 [BX] 并没有指定段地址哦

INC AL

INC BX

LOOP s

MOV AH,4CH

INT 21H

CODES ENDS

END START

上面的代码所做的事情,就是循环将 1,2,3,4,5 写入到地址 1000H:0000H ,1000H:0001H,

1000H:0002H,1000H:0003H,1000H:0004H 中,

语句的执行过程如下:

首先我们来看尚未执行上述任何指令时栈中的数据情况:

而当循环执行完成以后,我们再来看内存 1000H:0000H 处的值:

在这里,我们可以看到确实达到了我们预期的效果,但是大家注意看代码:

s: MOV [BX],AL ;这里 [BX] 并没有指定段地址哦 INC AL

INC BX

LOOP s

这里可以看到,我们在[BX] 中并没有给其指定段地址,而只有一个偏移地址,

但是根据我们一开始的介绍,必须要有段地址和偏移地址才能够定位内存单元,

莫非这里出问题了?

其实不是的,因为我们在最前面定义了段地址 DS 为 1000H,

当我们定义好段地址后,每一次 CPU 执行到[BX]时,便会自动或者说是默认的从 DS 中取值,

并且将取得的值作为段地址,因此,当[BX]为 0001H 时,CPU 会从 DS 中取得一个 1000H ,

由这两个一合成即可以得到正确的物理地址 1000H:0000H 。

最后还提醒一点,那就是 8086 CPU 不支持直接将一个数据送入段寄存器中,

也就是下面的做法是错误的:

MOV DS,1000H

标志寄存器(FLAG):

前面呢,已经介绍了 8086 CPU 14 个寄存器中的 13 个了,下面我们将介绍最后一个寄存器也就是 FLAG 寄存器,FLAG 寄存器之所以放到最后一个介绍,是因为其和其他的一些寄存器不同,像 AX,BX,CX,DX 这些寄存器来说,它们都是用来存放数据的,当然 FLAG 中存放的也是数据啦,

呵呵,不过,AX,BX 这些寄存器中的数据是作为一个整体使用的,

最多也就分成一个 AL 和 AH 使用而已,但是在 FLAG 中,数据是按位起作用的,

也就是说,FLAG 中的每一个位都表示不同的状态,

由于一个位也就能表示 0 和 1 ,自然,FLAG 中的每一个位就是用来描述状态的,

而且 FLAG 寄存器中存储的信息通常又被称作程序状态字(PSW)。

下面我给出一幅 FLAG 寄存器中各个位的示意图:

从上面这幅图中可以看出,FLAG 的第 0 个位表示的是 CF ,第 2 个位表示的是 PF ,与此类推 . . . . 首先,我们来看一个列表:

上面的这个表怎么看呢?我们通过看下面一幅截图就知道了。

从上面的标记中可以看出,从左到右依次代表 OF,DF,SF,ZF,PF,CF 标志位的值,

再通过与上面的表格相对照可以知道:

OF = 0 ;

DF = 0 ;

SF = 0 ;

ZF = 0 ;

PF = 0 ;

CF = 0 ;

至于为什么我们在 Debug 模式下,使用 R 命令时,只会列出这几个标志位

寄存器简单理解

GPIOB_BASE是一个地址,这个地址是GPIOB一系列寄存器的首地址,后面地址依次是GPIOB 的寄存器,将这个地址转换为结构体形式,并将后面寄存器按顺序定义在结构体里面,这样访问寄存器就可以通过引用结构体的形式了而不必书写寄存器的地址来访问寄存器。 寄存器用途: 1.可将寄存器内的数据执行算术及逻辑运算; 2.存于寄存器内的地址可用来指向内存的某个位置,即寻址; 3.可以用来读写数据到电脑的周边设备。 AX 累加器,得名原因是最初常使用ADD AX,n这样的指令 CX 计数器,得名原因是最常使用CX的值作为重复操作的次数 BX 常用作地址寄存器,如MOV AX,[BX],把BX所指地址中的数取到AX中去 DX 通用寄存器 所讲的寄存器都是以x86为基础的,那么这种CPU内,寄存器可分为以下几种: 1.EAX、EBX、ECX、EDX等通用寄存器——从通用上来讲,它所存储的东西,只要它的容积所容许的话,什么都是可以存储的; 2.CS、SS、ES等段寄存器——它所存储的只能是地址,它的作用是从寻址上可以体现出来; 3.EIP,也称为指令指针 4.EFLAGS寄存器,俗称为标志寄存器——所存储的是与CPU的每一个执行的指令有关。是关系到CPU每一个指令的执行相关内容与特殊的关联,即CPU所执行的指令是否违规,它的指令是否有进位,它的指令是否有溢出,都是在标志寄存器中能表现与表达出来; 5.浮点单元,这里面之所以只浮点单元,是因为在它里面还有一些小的寄存分类,主要是数学上的浮点上的计算 6.MMX指令使用的8个64位寄存器 7.单指令、多数据操作(SIMD,single-instruction,multiple-data)使用的8个128位XMM寄存器

ARM寄存器详解

ARM 处理器有二十七个寄存器,其中一些是在一定条件下使用的,所以一次只能使用十六 个。 R0~R7:是通用寄存器并可以用做任何目的。 R8~R12:是通用寄存器,但是在切换到FIQ模式的时候,使用它们的影子(shadow)寄存器。 R13:被称为栈指针寄存器,常用来保存栈指针。 R14:链接寄存器,常用来保存函数返回地址 R15:是程序指针PC CPSR:(Current Program Status Register)当前程序状态寄存器,CPSR 寄存期保存当前程序运行的状态。 0 0 0 0 0 User26 模式 0 0 0 0 1 FIQ26 模式 0 0 0 1 0 IRQ26 模式 0 0 0 1 1 SVC26 模式 1 0 0 0 0 User 模式 1 0 0 0 1 FIQ 模式 1 0 0 1 0 IRQ 模式 1 0 0 1 1 SVC 模式 1 0 1 1 1 ABT 模式 1 1 0 1 1 UND 模式

ARM寻址方式 1.立即数寻址 ARM 指令的立即数寻址是一种特殊的寻址方式,操作数本身就在指令中给出,只要取出指令也就取到了操作数。这个操作数被称为立即数。ADD R0,R0,#1 ;R0←R0 + 1 ADD R0,R0,#0x3A ;R0←R0 + 0x3A 在以上 2 条指令中,第2个源操作数即为立即数,实际使用时以“#”符

号为前缀。 2.寄存器寻址 寄存器寻址就是利用寄存器中的数值作为操作数,这种寻址方式是各类微处理器经常采 用的一种方式,也是一种执行效率较高的寻址方式。如以下的指令。 ADD R0,R1,R2 ;R0←R1 + R2 该指令的执行效果是将寄存器R1和R2的内容相加,其结果存放在寄存器R0中。 3.寄存器间接寻址 寄存器间接寻址就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储器 中。例如以下指令。 ADD R0,R1,[R2] ;R0←R1 + [R2] LDR R0,[R1] ;R0←[R1] 在第1 条指令中,以寄存器R2 的内容作为操作数的地址,然后与R1相加,其结果存入 寄存器R0中。 第2条指令将以 R1 的值为地址的存储器中的内容送到寄存器R0中。 4.基址变址寻址 基址变址的寻址方式就是将寄存器(该寄存器一般称作基址寄存器)的内容与指令中给 出的地址偏移量相加,从而得到一个操作数的有效地址。如下面的几条指令所示。 LDR R0,[R1,#0x0A] ;R0←[R1 + 0x0A] LDR R0,[R1,#0x0A]!;R0←[R1 + 0x0A]、R1←R1 + 0x0A 在第1条指令中,将寄存器R1 的内容加上0x3A 形成操作数的有效地址,将该地址处的 操作数送到寄存器R0中。 在第2条指令中,将寄存器R1的内容加上0x0A形成操作数的有效地址,从而取得操作数存入寄存器R0中,然后,R1的内容自增0x0A个字节。 5.多寄存器寻址 采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送。这种寻址方式可以用 一条指令完成传送最多 16 个通用寄存器的值。比如下面的指令。LDMIA R0,{R1,R2,R3,R4} ;R1←[R0] ;R2←[R0 + 4]

实验二 通用寄存器实验

实验二通用寄存器实验 一、实验目的 1.熟悉通用寄存器的数据通路。 2.了解通用寄存器的构成和运用。 二、实验要求 掌握通用寄存器R3~R0的读写操作。 三、实验原理 实验中所用的通用寄存器数据通路如下图所示。由四片8位字长的74LS574组成R1 R0(CX)、R3 R2(DX)通用寄存器组。图中X2 X1 X0定义输出选通使能,SI、XP控制位为源选通控制。RWR为寄存器数据写入使能,DI、OP为目的寄存器写选通。DRCK信号为寄存器组打入脉冲,上升沿有效。准双向I/O输入输出端口用于置数操作,经2片74LS245三态门与数据总线相连。 图2-3-3 通用寄存器数据通路

四、实验内容 1. 实验连线 K23~K0置“1”,灭M23~M0控位显示灯。然后按下表要求“搭接”部件控制电路。 连线 信号孔 接入孔 作用 有效电平 1 DRCK CLOCK 单元手动实验状态的时钟来源 上升沿打入 2 X2 K10(M10) 源部件译码输入端X2 三八译码 八中选一 低电平有效 3 X1 K9(M9) 源部件译码输入端X1 4 X0 K8(M8) 源部件译码输入端X0 5 XP K7(M7) 源部件奇偶标志:0=偶寻址,1=奇寻址 6 SI K20(M20) 源寄存器地址:0=CX ,1=DX 7 RWR K18(M18) 通用寄存器写使能 低电平有效 8 DI K17(M17) 目标寄存器地址:0=CX ,1=DX 9 OP K16(M16) 目标部件奇偶标志:0=偶寻址,1=奇寻址 2. 寄存器的读写操作 ① 目的通路 当RWR=0时,由DI 、OP 编码产生目的寄存器地址,详见下表。 通用寄存器“手动/搭接”目的编码 目标使能 通用寄存器目的编址 功能说明 RW(K18) DI(K17) OP(K16) T 0 0 0 ↑ R0写 0 0 1 ↑ R1写 0 1 0 ↑ R2写 0 1 1 ↑ R3写 ② 通用寄存器的写入 通过“I/O 输入输出单元”向R0、R1寄存器分别置数27h 、37h ,操作步骤如下: 通过“I/O 输入输出单元”向R2、R3寄存器分别置数47h 、57h ,操作步骤如下: ③ 源通路 当X2~X0=001时,由SI 、XP 编码产生源寄存器,详见下表。 通用寄存器“手动/搭接”源编码 置数 I/O=XX01h 数据来源 I/O 单元 寄存器 R0=01h K10~K7=1000 按【单拍】按钮 置数 I/O=XX11h 寄存器 R1=11h 按【单拍】按钮 K18~K16=000 K18~K16=001 置数 I/O=XX21h 数据来源 I/O 单元 寄存器 R2=21h K10~K7=1000 按【单拍】按钮 置数 I/O=XX31h 寄存器 R3=31h 按【单拍】按钮 K18~K16=010 K18~K16=011

arm通用寄存器及其别名

AMR寄存器的别名+ APCS 默认情况下,arm处理器中的通用寄存器被称为:r0、r1...r14等,在APCS中为arm通用寄存器定义了别名。 在某些情况下(比如多人协作编辑汇编代码,或需要修改其它人所写的汇编代码时),使用APCS所定义的别名有助于提高代码的可读性和兼容性。 arm通用寄存器及其别名对照表:

The following register names are predeclared: r0-r15 and R0-R15 a1-a4 (argument, result, or scratch registers, synonyms for r0 to r3) v1-v8 (variable registers, r4 to r11) sb and SB (static base, r9) ip and IP (intra-procedure-call scratch register, r12) sp and SP (stack pointer, r13) lr and LR (link register, r14) pc and PC (program counter, r15). arm中r12的用途 原文作者在维护1个以前的程序,该程序包括应用、库文件以及linux device driver。该程序原来使用arm-linux-gcc 3.4.3编译,现在改用arm-linux-gcc 4.1.1进行编译时发现程序无法运行。 经原文作者测试,发现当使用shared library形式编译程序后无法运行,而使用static linking形式编译程序后可正常运行。

寄存器与7种寻址方式

一、寄存器 总共有14个16位寄存器,8个8位寄存器 通用寄存器: 数据寄存器: AH(8位) AL(8位) AX(16位) (AX和AL又称累加器) BH(8位) BL(8位) BX(16位) (BX又称基址寄存器,唯一作为存储器指针使用寄存器) CH(8位) CL(8位) CX(16位) (CX用于字符串操作,控制循环的次数,CL 用于移位) DH(8位) DL(8位) DX(16位) (DX一般用来做32位的乘除法时存放被除数或者保留余数) 指针寄存器: SP 堆栈指针(存放栈顶地址) BP 基址指针(存放堆栈基址偏移) 变址寄存器:主要用于存放某个存储单元地址的偏移,或某组存储单元开始地址的偏移, 即作为存储器(短)指针使用。作为通用寄存器,它们可以保存16位算术逻辑运算中的操 作数和运算结果,有时运算结果就是需要的存储单元地址的偏移. SI 源地址(源变址寄存器) DI 目的地址(目的变址寄存器) 控制寄存器: IP 指令指针 FLAG 标志寄存器 ①进位标志CF,记录运算时最高有效位产生的进位值。

②符号标志SF,记录运算结果的符号。结果为负时置1,否则置0。 ③零标志ZF,运算结果为0时ZF位置1,否则置0。 ④溢出标志OF,在运算过程中,如操作数超出了机器可表示数的范围称为溢出。溢出时OF位置1,否则置0。 ⑤辅助进位标志AF,记录运算时第3位(半个字节)产生的进位值。 ⑥奇偶标志PF,用来为机器中传送信息时可能产生的代码出错情况提供检验条件。当结果操作数中1的个数为偶数时置1,否则置0。 段寄存器 CS 代码段IP DS 数据段 SS 堆栈段SP BP ES 附加段 二、七种寻址方式: 1、立即寻址方式: 操作数就包含在指令中。作为指令的一部分,跟在操作码后存放在代码段。 这种操作数成为立即数。立即数可以是8位的,也可以是16位的。 例如: 指令: MOV AX,1234H 则: AX = 1234H 2、寄存器寻址方式: 操作数在CPU内部的寄存器中,指令指定寄存器号。 对于16位操作数,寄存器可以是:AX、BX、CX、DX、SI、DI、SP和BP等。对于8位操作数,寄存器可以是AL 、AH、BL、BH、CL、CH、DL、DH。 这种寻址方式由于操作数就在寄存器中,不需要访问存储器来取得操作数 因而可以取得较高的运算数度。

ARM处理器共有37个寄存器其中包括.

ARM处理器共有37个寄存器。其中包括: **31个通用寄存器,包括程序计数器(PC)在内。这些寄存器都是32位寄存器。 **6个状态寄存器。这些寄存器都是32位寄存器。 ARM处理器共有7种不同的处理器模式,每一种模式中都有一组相应的寄存器组。在任何时刻,可见的寄存器包括15个通用寄存器(R0-R14),一个或两个状态寄存器及程序计数器(PC)。在所有的寄存器中,有些是各模式公用一个物理寄存器,有一些寄存器各模式拥有自己独立的物理寄存器。 **************************************************** 通用寄存器 ***************************************************8 通用寄存器分为以下三类:备份寄存器、未备份寄存器、程序计数器PC 未备份寄存器 未备份寄存器包括R0-R7。对于每一个未备份寄存器来说,所有处理器模式下都是使用同一个物理寄存器。未备份寄存器没有被系统用于特别的用途,任何可采用通用寄存器的场合都可以使用未备份寄存器。 备份寄存器 对于R8-R12备份寄存器来说,每个寄存器对应两个不同的物理寄存器。系统为将备份寄存器用于任何的特殊用途,但是当中断处理非常简单,仅仅使用R8-R14寄存器时,FIQ处理程序可以不必执行保存和恢复中断现场的指令,从而可以使中断处理非常迅速。 对于R13,R14备份寄存器来说,每个寄存器对应六个不同的物理寄存器,其中的一个是系统模式和用户模式共用的;另外的五个对应于其他的五种处理器模式。采用下面的记号来区分各个物理寄存器: R13_ 其中MODE可以是下面几种模式之一:usr,svc,abt,und,irq,fiq 程序计数器PC 可以作为一般的通用寄存器使用,但有一些指令在使用R15时有一些限制。由于ARM采用了流水线处理器机制,当正确读取了PC的值时,该值为当前指令地址值加上8个字节。也就是说,对于ARM指令集来说,PC指向当前指令的下两条指令的地址。由于ARM指令是字对齐的,PC值的第0位和第一位总为0。

32位PowerPC构架通用寄存器分析及总结一

32位PowerPC构架通用寄存器分析及总结一 第一部分 32位 PowerPC构架下寄存器概述 32 位PowerPC构架寄存器模型可以分成三个类级别:UISA,VEA,OEA,我们根据这三个级别把PowerPC所使用的所有寄存器分为三类: 第一类:用户指令集构架(UISA-User Instruction Set Architecture)下所使用的寄存器;第二类:虚拟环境构架(VEA-Virtual Environment Architecture)下所使用的寄存器;第三类:操作系统环境(OEA-Operating Environment Architecture)下所使用的寄存器;PowerPC指令集构架为所有的算术逻辑运算指令定义了“寄存器到寄存器”格式的指令,这些指令的操作数来自或者来自于寄存器,或者来自于指令中的立即数。而对于“三寄存器”格式的指令,PowerPC指令集定义其中一个寄存器用来存目的操作数,另外两个寄存器用来存放源操作数。这样的话,存放源操作数的寄存器还可以被其它指令使用,从而减少了某些操作的指令数目。并且对于访问寄存器,PowerPC构架定义了明确的load和store访存指令(这是RISC指令集的典型特点)。 备注:寄存器中的保留位允许软件写任何值(其实就是0或者1),但是读出来的值,未必是我们写出来的值。它的值依赖于具体的执行系统。 接下来,我们分别来介绍这三类寄存器。 第二部分 UISA寄存器集合 用户模式下的寄存器可以被所有的用户级软件和特权级软件所使用,它包含以下的寄存器:32个通用寄存器GPRs(General-purpose registers):GPR0-GPR31; 32个浮点寄存器FRPs(Floating-point registers):FPR0-FPR31; 1个条件寄存器:CR(Condition register); 1个XER寄存器; 1个LR(Link register)寄存器; 1个CTR(Count register)寄存器; 1个浮点状态控制寄存器:FPSCR(Floating-point status and control register); 备注:不管是单精度数还是双精度数,在浮点寄存器中都是以双精度格式存储。 示意图如下:

汇编语言学习笔记之通用寄存器

汇编语言学习笔记之通用寄存器 从昨天开始,正式拉开了学习汇编语言的序幕,对于汇编语言的一些特点以及数据的表示及类型做了一番了解,由于这些东西每一种语言里都要介绍,而且一时半会也真弄不太明白它们的具体使用,也就粗略的看了一下,留待在今后的学习中结合实例加以体会吧。 而通用寄存器应该说是CPU内部重要的数据存储资源,学习汇编语言必须要掌握清它们的功能。因此汇编语言学习的第一篇学习笔记就从通用寄存器开始了。以下内容摘自汇编教程中。 寄存器是CPU内部重要的数据存储资源,是汇编程序员能直接使用的硬件资源之一。由于寄存器的存取速度比内存快,所以,在用汇编语言编写程序时,要尽可能充分利用寄存器的存储功能。 寄存器一般用来保存程序的中间结果,为随后的指令快速提供操作数,从而避免把中间结果存入内存,再读取内存的操作。在高级语言(如:C/C++语言)中,也有定义变量为寄存器类型的,这就是提高寄存器利用率的一种可行的方法。 另外,由于寄存器的个数和容量都有限,不可能把所有中间结果都存储在寄存器中,所以,要对寄存器进行适当的调度。根据指令的要求,如何安排适当的寄存器,避免操作数过多的传送操作是一项细致而又周密的工作。有关“寄存器的分配策略”在后续课程《编译原理》中会有详细的介绍。 由于16位/32位CPU是微机CPU的两个重要代表,所以,在此只介绍它们内部寄存器的名称及其主要功能。 1、16位寄存器组 16位CPU所含有的寄存器有: 4个数据寄存器(AX、BX、CX和DX), 2个变址和指针寄存器(SI和DI), 2个指针寄存器(SP和BP) 4个段寄存器(ES、CS、SS和DS), 1个指令指针寄存器(IP), 1个标志寄存器(Flags) 2、32位寄存器组 32位CPU除了包含了先前CPU的所有寄存器,并把通用寄存器、指令指针和标志寄存器从16位扩充成32位之外,还增加了2个16位的段寄存器:FS 和GS。 32位CPU所含有的寄存器有: 4个数据寄存器(EAX、EBX、ECX和EDX), 2个变址和指针寄存器(ESI和EDI), 2个指针寄存器(ESP和EBP) 6个段寄存器(ES、CS、SS、DS、FS和GS),

通用寄存器实验报告

6.9 通用寄存器实验报告 一、实验目的: 1、了解通用寄存器组的用途及对CPU的重要性。 2、掌握通用寄存器组的设计方法。 二、实验内容: 1、通用寄存器组的作用 通用寄存器组是CPU的重要组成部分。 (1)从存储器和外部设备(除DMA方式外)取来的数据要放在通用寄存器中; (2)向存储器和外部设备(除DMA方式外)输出的数据从通用寄存器中取出; (3)参加算术运算和逻辑运算的数据从通用寄存器组中取出,同时通用寄存器也是运算结果的暂存地。 (4)通用寄存器组有两个读端口,负责提供进行算术逻辑单元需要的源操作数和目的操作数;有一个写端口,负责将运算结果保存到指定的寄存器内。 2、通用寄存器组功能实现 根据通用寄存器组的功能要求,一个只有四个16位寄存器的通用寄存器组的框图如下图所示: ⑴寄存器部分: 当reset为低电平时,将四个16位寄存器R0-R3复位为0;当寄存器的write和sel

为高电平时,在时钟信号clk的上升沿将D端的输入D[15-0]写入寄存器,然后送到寄存器的输出Q[15-0]。4个寄存器的允许写信号write和外部产生的目的寄存器写信号DRWr 直接相连。每个寄存器还有另一个选择信号sel,它决定哪一个寄存器进行写操作。4个寄存器的选择信号分别和2-4译码器产生的sel00、sel01、sel10、sel11相连。只有当一个寄存器被选中(sel为高电平时),才允许对该寄存器进行写操作。 ⑵ 2-4译码器: 2-4译码器的输入sel[1-0]接DR[1-0],2-4译码器对2位的输入信号sel[1-0]进行2-4译码,产生4个输出sel00、sel01、sel10、sel11,分别送往4个寄存器R0、R1、R2和R3的选择端sel。 ⑶ 4选1多路器 4选1多路选择器1从4个寄存器R0、R1、R2和R3的输出Q[15-0]选择1路送到DR_data[15-0],给算术逻辑单元提供目的操作数;选择信号sel[1-0]接DR[1-0]。4选1多路选择器2从4个寄存器R0、R1、R2和R3的输出Q[15-0]选择1路送到SR_data[15-0],给算术逻辑单元提供源操作数;选择信号sel[1-0]接SR[1-0]。 三、实验要求: 1、实验设计目标 设计一个通用寄存器组满足以下要求: (1)通用寄存器组中有4个16位的寄存器。 (2)当复位信号reset=0时,将通用寄存器组中的4个寄存器清零。 (3)通用寄存器组中有1个写入信号,当DRWr=1时,在时钟clk的上升沿将数据总线上的数写入DR[1-0]指定的寄存器。 (4)通用寄存器组中有两个读出端口,一个对应算术逻辑单元的目的操作数DR,另一个对应算术逻辑单元的源操作数SR。DR[1-0]选择目的操作数;SR[1-0]选择源操作数。 (5)设计要求层次设计。底层的设计实体有三个:16位寄存器,具有复位功能和允许写功能;一个2-4译码器,对应寄存器写选择;一个4选1多路开关,负责选择寄存器的读出。顶层设计构成一个完整的通用寄存器组。 2、顶层设计实体的引脚要求 引脚要求对应关系如下: (1)clk对应试验台上的时钟(单脉冲)。 (2)reset对应实验台上的CPU复位信号CPU_RST。 (3)SR[1-0]对应实验台开关SA1,SA0。

实验CPU通用寄存器组 计算机组成原理

实验CPU 通用寄存器组 一、实验目的 (1)了解通用寄存器组的用途及对CPU的重要性。 (2)掌握通用寄存器组的设计方法。 二、实验原理 通用寄存器组是CPU的重要组成部分。从存储器取来的数据要放在通用寄存器中;从外部设备取来的数据除DMA方式外,要放在通用寄存器中。向存储器输出的数据也是从通用寄存器中取出;向外部设备输出的数据除DMA方式外也是从通用寄存器中取出来的。由于从通用寄存器组中取数据比从存储器或者外部设备取数据快得多,因此参加算术运算和逻辑运算的数据一般是从通用寄存器组中取出,它向算术逻辑单元ALU提供了进行算术运算和逻辑运算所需要的两个操作数,同时又是运算结果的暂存地。通用寄存器组内寄存器的数目与CPU性能有关,CPU性能预告,通用寄存器组内的寄存器数目越多。由于算术逻辑运算需要两个操作数,因此通用寄存器组有两个读端口,负责提供进行算术逻辑单元需要的源操作数和目的操作数。通用寄存器组有1个写端口,负责将运算结果保存到指定的寄存器内。根据通用寄存器组的功能要求,一个只有4个16位寄存器的通用寄存器组的框图如下图所示。 在上图所示的电路中,当reset为低电平时,将4个16位寄存器R0~R3复位为0。当寄存器的write和sel为高电平时,在时钟信号clk的上升沿将D端的输入D[15..0]写入寄存器,然后送到寄存器的输出Q[15..0]。4个寄存器的允许写信号write和外部产生的目的寄存器写信号DRWr直接相连。每个寄存器还有另一个选择信号sel,它决定哪一个寄存器进行写操作。4个寄存器的选择信号分别和2-4译码器产生的sel00、sel01、sel10和sel11相连。只有当1个寄存器被选中时,才允许对该寄存器进行写操作。2-4译码器的输入sel[1..0]接DR[1..0],

通用寄存器的作用

通用寄存器的作用 数据寄存器不讲,简单的说,段寄存器(ES,CS,SS,DS,FS,GS)和变址寄存器(SI,DI)是配合使用访问段数据的,指针寄存器(BP,SP)是用来操作堆栈的,BP指向栈的基址,SP则永远指向栈顶。 另外指令指针EIP存放的是要执行的下一条指令在代码段里的偏移量,在实方式下,每个段的最大范围都是64K,所以EIP的高16位都是0。 寄存器的分类寄存器主要用途 通用寄存器 数据 寄存器 AX 乘、除运算,字的输入输出,中间结果的缓存 AL 字节的乘、除运算,字节的输入输出,十进制算术运算 AH 字节的乘、除运算,存放中断的功能号 BX 存储器指针 CX 串操作、循环控制的计数器 CL 移位操作的计数器 DX 字的乘、除运算,间接的输入输出 变址 寄存器 SI 存储器指针、串指令中的源操作数指针 DI 存储器指针、串指令中的目的操作数指针 变址 寄存器 BP 存储器指针、存取堆栈的指针 SP 堆栈的栈顶指针 指令指针IP/EIP 标志位寄存器Flag/EFlag 32位CPU的段寄存器16位CPU的 段寄存器 ES 附加段寄存器 CS 代码段寄存器 SS 堆栈段寄存器 DS 数据段寄存器新增加的 段寄存器 FS 附加段寄存器 GS 附加段寄存器

--------------------------------- 1、数据寄存器 数据寄存器主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问存储器的时间。 32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。对低16位数据的存取,不会影响高16位的数据。这些低16位寄存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。 4个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每个寄存器都有自己的名称,可独立存取。程序员可利用数据寄存器的这种“可分可合”的特性,灵活地处理字/字节的信息。 寄存器AX和AL通常称为累加器(Accumulator),用累加器进行的操作可能需要更少时间。 累加器可用于乘、除、输入/输出等操作,它们的使用频率很高; 寄存器BX称为基地址寄存器(Base Register)。它可作为存储器指针来使用; 寄存器CX称为计数寄存器(Count Register)。在循环和字符串操作时,要用它来控制循环次 数;在位操作中,当移多位时,要用CL来指明移位的位数; 寄存器DX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数 参与运算,也可用于存放I/O的端口地址。 在16位CPU中,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址,但在32位CPU中,其32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果,而且也可作为指针寄存器,所以,这些32位寄存器更具有通用性。详细内容请见第3.8节——32位地址的寻址方式。 2、变址寄存器 32位CPU有2个32位通用寄存器ESI和EDI。其低16位对应先前CPU中的SI 和DI,对低16位数据的存取,不影响高16位的数据。 寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register),它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式(在第3章有详细介绍),为以不同的地址形式访问存储单元提供方便。 变址寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。 它们可作一般的存储器指针使用。在字符串操作指令的执行过程中,对它们有特定的要求,而且还具有特殊的功能。具体描述请见第5.2.11节。 3、指针寄存器 32位CPU有2个32位通用寄存器EBP和ESP。其低16位对应先前CPU中的SBP 和SP,对低16位数据的存取,不影响高16位的数据。 寄存器EBP、ESP、BP和SP称为指针寄存器(Pointer Register),主要用于存放堆栈内存储单元的偏移量,用它们可实现多种存储器操作数的寻址方式(在第3章有详细介绍),为以不同的地址形式访问存储单元提供方便。

通用寄存器组

计算机组成原理实验报告题目:运算器部件实验:通用寄存器组 学院数学与信息学院 学科门类工学 专业12软件工程 学号2012436138 姓名王赛赛 指导教师王兵

计算机组成原理实验报告 一、实验目的 1.了解通用寄存器组的用途及对CPU的重要性。 2.掌握通用寄存器的设计方法。 二、实验原理 通用寄存器组是CPU的重要组成部分。通用寄存器组中的寄存器的数目与CPU性能有关,CPU性能越高,通用寄存器组内的寄存器数目越多。由于计算逻辑运算需要两个操作数,因此通用寄存器组有两个读入端口,负责提供进行算术逻辑单元需要的元操作数和目的操作数。通用寄存器组有1个写端口,负责将运算结构保存到指定的寄存器内。 三、实验要求 1.实验设计目标 设计一个通用寄存器组,满足以下要求: (1)通用寄存器组中有4个16位的寄存器。 (2)当复位信号reset=0时,将通用寄存器组中的4个寄存器清零。 (3)通用寄存器组中有两个读出端口,当DRWr=1时,在始终clk的上升沿将数据总线上的数写入DR[1..0]指定的寄存器。 (4)通用寄存器组有两个读出接口,一个对应算术逻辑单元的目的的操作数DR,另一个对应算术逻辑单元的源操作数SR。DR[1..0]选择目的的操作数;SR[1..0]选择源操作数。 (5)设计要求层次设计。底层的设计实体有3个:16位寄存器,具有复位功能和允许写功能;一个2-4译码器,对应寄存器写选择;一个4选1多路开光,负责选择寄存器的读出。顶层设计构成一个完整的通用寄存器组。 2.顶层设计实体的引脚要求 引脚要求对应关系如下: (1)clk对应实验台上的时钟(单脉冲)。 (2)reset对应实验台上的CPU复位信号CPU_RST. (3)SR[1..0]对应试验台开关SA1,SA0。 (4)DR[1..0]对应试验台开关SR3,SR2。 (5)DRWr对应实验台上开关SA5。 (6)目的操作数用试验台上的指示灯A~A显示,源操作数用试验台上的指示灯 R15~R0显示。 四、实验步骤 1.将试验台设置成FPGA-CPU独立调试模式,REGSEL=0,CLKSEL=1,FDSEL=0,使 用试验台上的单脉冲,即STEP_CLK段路子短接,短路子RUN_CLK断开。 2.将设计在Quartus2下输入,编译后下载到TEC-CA上的FPGA。 3.将下列数据存入寄存器: R0OX3333 R1OX5555 R2OXAAAA R3OXFFFF

通用寄存器组实验报告

通用寄存器组 学号:201207030 姓名:叶利钦专业:计算121 一、实验目的 (1)了解通用寄存器组的用途及对CPU的重要性。 (2)掌握通用寄存器组的设计方法。 二、实验原理 通用寄存器组是CPU的重要组成部分。从存储器取来的数据要放在通用寄存器中;从外部设备取来的数据除DMA方式外,要放在通用寄存器中。向存储器输出的数据也是从通用寄存器中取出;向外部设备输出的数据除DMA方式外也是从通用寄存器中取出来的。由于从通用寄存器组中取数据比从存储器或者外部设备取数据快得多,因此参加算术运算和逻辑运算的数据一般是从通用寄存器组中取出,它向算术逻辑单元ALU提供了进行算术运算和逻辑运算所需要的两个操作数,同时又是运算结果的暂存地。通用寄存器组内寄存器的数目与CPU性能有关,CPU性能预告,通用寄存器组内的寄存器数目越多。由于算术逻辑运算需要两个操作数,因此通用寄存器组有两个读端口,负责提供进行算术逻辑单元需要的源操作数和目的操作数。通用寄存器组有1个写端口,负责将运算结果保存到指定的寄存器内。根据通用寄存器组的功能要求,一个只有4个16位寄存器的通用寄存器组的框图如下图所示。 在上图所示的电路中,当reset为低电平时,将4个16位寄存器R0~R3复位为0。当寄存器的write和sel为高电平时,在时钟信号clk的上升沿将D端的输入D[15..0]写入寄存器,然后送到寄存器的输出Q[15..0]。4个寄存器的允许写信号write和外部产生的目的寄存器写信号DRWr直接相连。每个寄存器还有另一个选择信号sel,它决定哪一个寄存器进行写操作。

4个寄存器的选择信号分别和2-4译码器产生的sel00、sel01、sel10和sel11相连。只有当1个寄存器被选中时,才允许对该寄存器进行写操作。2-4译码器的输入sel[1..0]接DR[1..0],2-4译码器对2位的输入信号sel[1..0]进行2-4译码,产生4个输出sel00、sel01、sel10和sel11,分别送往4个寄存器R0、R1、R2、R3的选择端4选1多路选择器1从4个寄存器R0、R1、R2、R3的输出Q[15..0]选择1路送到DR_data[1..0],给算术逻辑单元提供目的操作数;选择信号sel[1..0]接DR[1..0]。4选1多路选择器2从4个寄存器R0、R1、R2、R3的输出Q[15..0]选择一路送到SR_data[1..0],给算术逻辑单元提供源操作数;选择信号sel[1..0]接SR[1..0]。 三、实验要求 1、实验设计目标 设计一个通用寄存器组,满足以下要求: (1) 通用寄存器组有4个16位的寄存器。 (2) 当复位信号reset=0时,将通用寄存器组中的4个寄存器清零。 (3) 通用寄存器组中有1个写入端口,当DRWr=1时,在时钟clk的上升沿将数据总线上的数写入DR[1..0]指定的寄存器。 (4) 通用寄存器组中有两个读出端口,一个对应算术逻辑单元的目的操作数DR,另一个对应算术逻辑单元的源操作数SR。DR[1..0]选择目的操作数;SR[1..0]选择源操作数。 (5) 设计要求层次设计。底层的设计实体有3个:16位寄存器,具有复位功能和允许写功能;一个2-4译码器,对应寄存器写选择;一个4选1多路开关,负责选择寄存器的读出。顶层设计构成一个完整的通用寄存器组。 2、顶层设计实体的引脚要求 引脚要求对应关系如下 (1)clk对应实验台上的时钟(单脉冲)。 (2)reset对应试验台上的CPU复位信号CPU-RST。 (3)SR[1...0]对应试验台开关SA1,SA0。 (4)DR[1..0]对应试验台开关SA3,SA2。 (5)DRWr对应试验台开关SA5。 (6)目的操作数用实验台上的指示灯A15~A0显示,源操作数用试验台上的指示灯R15~R0显示。 (7)d-input接开关SD15~SD0。 四、实验主要代码 library ieee; use ieee.std_logic_1164.all; USE IEEE.STD_LOGIC_UNSIGNED.ALL; entity to2_4 is port ( sel:in std_logic_vector(1 downto 0); sel00,sel01,sel02,sel03: out std_logic ); end entity; architecture rtl of to2_4 is begin sel00<=(not sel(1))and(not sel(0)); sel01<=(not sel(1))and sel(0) ;

2.4通用寄存器下

2.4通用寄存器下 本节必须掌握的知识点: ◆掌握DTDebug界面、并熟练使用 ◆熟记汇编窗口的组成及寄存器窗口的组成 ◆ MOV指令的熟练使用 ◆掌握字节、字、双字的知识 ◆使用汇编指令对8位、16位、32位寄存器数据的存储 在2.3节中介绍通用寄存器的知识,并且知道了寄存器是处理器(CPU)中用来存储数据的地方。接下来我们借用软件了解2.3节中的知识点。 2.4.1【DTDebug软件】 DTDebug.exe是供程序员使用的程序调试工具。【本节只简单介绍DTDebug的使用,详细说明书请到官网去下载相关文档】 在2.1节中介绍DTDebug软件的安装步骤,相信大家已经安装好这个软件。接下来介绍这个软件的使用。 双击DTDebug.exe软件图标如图2-4-1所示,打开界面如图2-4-2所示。 图2-4-2是软件的原始界面,没有任何记录。那该怎么把将要被调试的程序打开哪? 有四种方式: 1、在如图2-4-2程序窗口中找到File -> Open ->找到调试程序; 2、直接将要被调试的程序拖拽到如图2-4-2程序窗口中。 3、关闭如图2-4-2窗口,把将要被调试的程序拖到如图2-4-1DTDebug图标上。 4、在如图2-4-2程序窗口中找到File -> Attach ->找到将要被调试的程序(正在运行的软件)。 以IPMGS.exe为例,介绍DTDebug界面,如图2-4-3,图2-4-4所示。

图2-4-4中标注的4个窗口,分别为汇编窗口、寄存器窗口、内存窗口、堆栈窗口。【本节中只是简单介绍,更深入的操作以后课程会介绍】 2.4.2【汇编窗口】 简单介绍汇编窗口,汇编窗口由内存、特征码、汇编(从左向右)这三块组成。【在本节这三块不做介绍】 一个程序运行以后,处理器会一行行的执行它的代码,如图2-4-4处理器会沿着汇编窗口从上往下一行行执行代码,直至结束。跟着操作时肯定会有以下疑问,首先没有看到被调试的程序运行,其次汇编窗口并没有从上往下一行行执行代码。接下来解答一下,DTDebug 软件是可以中断当前运行的程序的,如图2-4-4黄色区域中写着Paused表示当前程序是被中断的,其次接着看图2-4-4汇编窗口中有黑色区域表示当前被调试的程序被中断在这块内存区域。该块区域是被调试程序的入口点。【文中讲到的中断指,处理器运行到该段程序时,让该程序停止运行了】。那怎么让程序一行行往下执行哪?看图2-4-4中有 一个三角符号,按下程序将会一行行往下执行,此时被调试的程序就会运行起来的。接下来介绍寄存器窗口。如图2-4-4寄存器窗口所示。

PLC通用数据寄存器D

PLC通用数据寄存器D 数据寄存器(D)在模拟量检测与控制以及位置控制等场合用来储存数据和参数,数据寄存器可储存16位二进制数或一个字,两个数据寄存器合并起来可以存放32位数据(双字),在:D0和D1组成的双字中,D0存放低16位,D1存放高16位。字或双字的最高位为符号位,该位为0时数据为正,为1时数据为负。 将数据写入通用数据寄存器后,其值将保持不变,直到下一次被改写。PLC从RUN状态进入STOP状态时,所有的通用数据寄存器的值被改写为0。 如果特殊辅助继电器M8033为ON,PLC从RUN状态进入STOP状态时,通用数据寄存器的值保持不变 PLC在进行输入输出处理、模拟量控制、位置控制时,需要许多数据寄存器存储数据和参数。数据寄存器为16位,最高位为符号位。可用两个数据寄存器来存储32位数据,最高位仍为符号位。数据寄存器有以下几种类型: 1.通用数据寄存器(D0~D199) 共200点。当M8033为ON时,D0~D199有断电保护功能;当M8033为OFF时则它们无断电保护,这种情况PLC由RUN →STOP或停电时,数据全部清零。 2.断电保持数据寄存器(D200~D7999) 共7800点,其中D200~D511(共12点)有断电保持功能,可以利用外部设备的参数设定改变通用数据寄存器与有断电保持功能数据寄存器的分配;D490~D509供通信用;D512~D7999的断电保持功能不能用软件改变,但可用指令清除它们的内容。根据参数设定可以将D1000以上做为文件寄存器。 3.特殊数据寄存器(D8000~D8255)

共256点。特殊数据寄存器的作用是用来监控PLC的运行状态。如扫描时间、电池电压等。未加定义的特殊数据寄存器,用户不能使用。具体可参见用户手册。 4.变址寄存器(V/Z) FX2N系列PLC有V0~V7和Z0~Z7共16个变址寄存器,它们都是16位的寄存器。变址寄存器V/Z实际上是一种特殊用途的数据寄存器,其作用相当于微机中的变址寄存器变,用于改变元件的编号(变址),例如V0=5,则执行D20V0时,被执行的编号为D25(D20+5)。变址寄存器可以象其它数据寄存器一样进行读写,需要进行32位操作时,可将V、Z串联使用(Z为低位,V为高位) 案列分析 1.三菱PLC编程MOV K2 K1Y000表示什么意思 K1Y000表示Y000~Y003(4个),如果是K2Y000则表示Y000~Y007(8个)以此类推。 指令意思:k2变成0010然后放入Y003~Y000,即Y003=Y002=Y000=0,Y001=1 2.PLC中 MOVP K21845 K4Y0的意思 就是把十进制数21845(二进制101010101010101)给到Y0开始到Y17的十六位寄存器中,即是Y0,Y2....Y14有输出

青岛理工大学通用寄存器组设计

青岛理工大学 实验报告 实验课程:计算机组成原理I Array实验日期:2014年10月15日,交报告日期:2014年11月日,成绩: 实验地点:现代教育技术中心305(计算机实验室) 计算机工程学院,计算机科学与技术专业,班级:计算122班 实验指导教师:龚玉玺批阅教师:龚玉玺 一、实验课题 一、主要元件设计 1.16位寄存器 功能要求:同步并行置数,异步复位(清零),三态输出,片选信号,读/写控制。 2.地址译码器 功能要求:3-8译码器 二、顶层设计 用层次结构设计的方法设计一个通用寄存器组。包括8个16位寄存器,1个地址译码器等元件。 功能要求:每个寄存器能够同步并行置数,异步复位(清零),三态输出。每个都可以(用地址)独立访问 三、仿真 设计仿真波形数据,要考虑到所有可能的情况。在实验报告中必须清楚说明仿真波形数据是怎样设计的。 四、深入的课题 ①上面设计的通用寄存器组,每次只能访问一个寄存器。如果想同时访问两个寄存器, 应该怎样设计? ②16位的寄存器每次读/写都是一个16位字,如果需要写入的是8位的字,即将8 位的字写到16位寄存器的高8位或低8位(例如,16位寄存器A由AH和AL两个8位的寄存器组成),读出时,可一次读16位。应该怎样设计 二、逻辑设计

端口说明:A(1-3):输入信号 S(1-3):使能端 Y(0-7):输出端口 功能表: 321逻辑函数:S A A A Y ???=)(0120, S A A A Y ???=)(0121,S A A A Y ???=)(0122 S A A A Y ???=)(0123,S A A A Y ???=)(0124,S A A A Y ???=)(0125 S A A A Y ???=)(0126,S A A A Y ???=)(0127 十六位寄存器系统框图 端口说明: A(0-15):输入 D(0-15):输出 Clk:时钟信号 r,chip,z:分别是异步清零信号,片选信号,三态输出 rw,:分别是读写控制信号

寄存器的使用

一般说来,处理器拥有对整个系统的所有总线的控制权。对于Intel平台而言,处理器拥有对数据、内存和控制总线的控制权,根据指令控制整个计算机的运行。在以后的章节中,我们还将讨论系统中同时存在多个处理器的情况。处理器中有一些寄存器,可以保存特定长度的数据。 第二章认识处理器 中央处理器(CPU)在微机系统处于“领导核心”的地位。汇编语言被编译成机器语言之后,将由处理器来执行。那么,首先让我们来了解一下处理器的主要作用,这将帮助你更好地驾驭它。 典型的处理器的主要任务包括 ?从内存中获取机器语言指令,译码,执行 ?根据指令代码管理它自己的寄存器 ?根据指令或自己的的需要修改内存的内容 ?响应其他硬件的中断请求 一般说来,处理器拥有对整个系统的所有总线的控制权。对于Intel平台而言,处理器拥有对数据、内存和控制总线的控制权,根据指令控制整个计算机的运行。在以后的章节中,我们还将讨论系统中同时存在多个处理器的情况。 处理器中有一些寄存器,这些寄存器可以保存特定长度的数据。某些寄存器中保存的数据对于系统的运行有特殊的意义。 新的处理器往往拥有更多、具有更大字长的寄存器,提供更灵活的取指、寻址方式。 寄存器 如前所述,处理器中有一些可以保存数据的地方被称作寄存器。 寄存器可以被装入数据,你也可以在不同的寄存器之间移动这些数据,或者做类似的事情。基本上,像四则运算、位运算等这些计算操作,都主要是针对寄存器进行的。 首先让我来介绍一下80386上最常用的4个通用寄存器。先瞧瞧下面的图形,试着理解一下:

上图中,数字表示的是位。我们可以看出,EAX是一个32-bit寄存器。同时,它的低16-bit又可以通过AX这个名字来访问;AX又被分为高、低8bit两部分,分别由AH和AL来表示。 对于EAX、AX、AH、AL的改变同时也会影响与被修改的那些寄存器的值。从而事实上只存在一个32-bit的寄存器EAX,而它可以通过4种不同的途径访问。 也许通过名字能够更容易地理解这些寄存器之间的关系。EAX中的E的意思是“扩展的”,整个EAX的意思是扩展的AX。X的意思Intel没有明示,我个人认为表示它是一个可变的量。而AH、AL中的H和L分别代表高和低。 为什么要这么做呢?主要由于历史原因。早期的计算机是8位的,8086是第一个16位处理器,其通用寄存器的名字是AX,BX等等;80386是Intel推出的第一款IA-32系列处理器,所有的寄存器都被扩充为32位。为了能够兼容以前的16位应用程序,80386不能将这些寄存器依旧命名为AX、BX,并且简单地将他们扩充为32位——这将增加处理器在处理指令方面的成本。 Intel微处理器的寄存器列表(在本章先只介绍80386的寄存器,MMX寄存器以及其他新一代处理器的新寄存器将在以后的章节介绍) 通用寄存器 下面介绍通用寄存器及其习惯用法。顾名思义,通用寄存器是那些你可以根据自己的意愿使用的寄存器,修改他们的值通常不会对计算机的运行造成很大的影响。通用寄存器最多的用途是计算。 上述寄存器同EAX一样包括对应的16-bit和8-bit分组。 用作内存指针的特殊寄存器

相关主题
相关文档
最新文档