汇编语言——寄存器

软件开发大郭
0 评论
/
29 阅读
/
3879 字
30 2022-09

接下来我们来介绍寄存器,同时会介绍一些基本的语句(mov,add等),好了,就让我们进入今天的学习吧!同时,我们以8086为例子来介绍,参考来自王爽老师的书。


说起寄存器,我们可不陌生,在单片机中我们已经接触过了。但是这个地方的寄存器要比单片机中有点不一样,以8086为例子,一共有14个寄存器:

  • 通用寄存器:AX、BX、CX、DX;

  • 变址寄存器:SI、DI;

  • 指针寄存器:SP、BP;

  • 指令指针寄存器:IP;

  • 段寄存器:CS、SS、DS、ES;

  • 标志寄存器:PSW

    这些我们在后面都会一一介绍,不过首先,我们来介绍一下通用寄存器。

通用寄存器

8086所有的寄存器都是16位的,所以最大可以存放2^16 – 1,但是目前有个问题,就是8080是8位的,那么两种是否是否是完全不同的两个东西,答案是否定的,这是因为8086的寄存器,分为高位(H)和低位(L),这就相当于两个8位,不得不说,还是满巧妙地,这样也解决了我的疑问,为什么在单片机里面寄存器可以拆开来用。

汇编指令

接下来我们来简单介绍三个汇编指令:mov、 add和sub,主要就是用来移动数据和加减数据(add是加,sub是减)。

可以说非常简单了 ,就不再赘述。唯一需要注意的就是,当加法溢出之后,溢出位是直接没有的,比如16位数据相加溢出,17位的1直接消失,而如果是8位,也不会向高位溢出,也是直接舍弃。

(二)汇编语言——寄存器

就像这里红色圈起来的0058,当执行add al, 93,之后,相当于,c5+93=158,然后1溢出,不会向高位进位。

(二)汇编语言——寄存器

物理地址

我们知道,8086有20位地址总线,所以寻址能力应该为1M。但是有个问题,就是8086是16位的机器,并不能一次传输20位的数据,这可怎么办呢?

解决办法就是用两个16位寄存器合成20位数据,这样就解决了问题,也就是:物理地址=段地址×16+偏移地址,接下来我们来看一看。

这样,我们表示123C8就可以直接用1230:00C8来表示,当然也可以用其他的,在此不再赘述。

(二)汇编语言——寄存器

段寄存器

8086一共有4个段寄存器,分别是CS、DS、SS、ES,我们接下来将讲解一下有关CS、DS以及SS。

CS:IP

  • CS:代码段寄存器

  • IP:指令指针寄存器

  • CS:IP:CPU将内存中CS:IP指向的内容当作指令执行。

    CS是代码段寄存器,也就是说CS:IP,就代表着这个地址后面的数据当作代码去执行,具体执行过程如下所示。

  1. 从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲器;
  2. IP=IP+所读取指令的长度,从而指向下一条指令;
  3. 执行指令。转到步骤1,重复这个过程。

但是有个问题,就是如何去修改CS段寄存器的值,经过测试,我们发现无法直接赋值,所以只能通过R命令去修改。但是这样过于繁琐,所以我们要学习一个新的指令:JMP。

JMP

这个主要就是用来修改CS的地址的,也叫转移指令。如果需要同时修改CS、IP的内容比如:jmp2AE3:3,jmp3:0B16。

jmp 段地址:偏移地址

仅修改IP的内容jmp某一合法寄存器

jmp ax(类似于mov IP,ax)

(二)汇编语言——寄存器(二)汇编语言——寄存器

字的存储

CPU中,低位字节存在低地址单元,高位字节存在高地址单元,高8位放高字节,低8位放低字节。千万要小心,下图数据为4E20和0012,不要读反了,注意高位和低位,千万小心!!!!

(二)汇编语言——寄存器

字单元

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

DS

接下来,如果CPU需要从内存单元中要读取数据,这应该这么操作呢?答案是用DS和[address]配合。

  • 用DS寄存器存放要访问的数据的段地址
  • 偏移地址用[…]形式直接给出
mov bx,1000H
mov ds,bx
mov al,[0]
  1. 字在内存中存储时,要用两个地址连续的内存单元来存放,字的低位字节存放在低地址单元中,高位字节存放再高地址单元中。
  2. 用mov指令要访问内存单元,可以在mov指令中只给出单元的偏移地址,此时,段地址默认在DS寄存器中。
  3. [address]表示一个偏移地址为address的内存单元。
  4. 在内存和寄存器之间传送字型数据时,高地址单元和高8位寄存器、低地址单元和低8位寄存器相对应。
  5. mov、add、sub是具有两个操作对象的指令,访问内存中的数据段(对照:jmp是具有一个操作对象的指令,对应内存中的代码段)。

栈就简单简单介绍一下,因为大家都熟悉。

栈是一种只能在一端进行插入或删除操作的数据结构。

栈有两个基本的操作:入栈和出栈。

入栈:将一个新的元素放到栈顶;

出栈:从栈顶取出一个元素。

栈顶的元素总是最后入栈,需要出栈时,又最先被从栈中取出。

栈的操作规则:LIFO(LastInFirstOut,后进先出)。

PUSH(入栈)和POP(出栈)指令(以字为单位对栈进行操作),其实和C语言很像,比较简单。唯一就是可能越界和栈空,千万注意,因为CPU不会帮你检查,一旦出问题,很有可能修改其他地方的数据。

push ax:将ax中的数据送入栈中

pop ax:从栈顶取出数据送入ax

现在就是有个问题,一段内存如何当作内存来使用啊?答案是SS段地址。

SS:SP

  • 栈段寄存器SS-存放栈顶的段地
  • 址栈顶指针寄存器SP-存放栈顶的偏移地址
  • 任意时刻,SS:SP指向栈顶元素。

过程

push ax

  1. SP=SP–2;
  2. 将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶。

pop ax

  1. 将SS:SP指向的内存单元处的数据送入ax中;
  2. SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。

总结

关于寄存器部分就讲完了,继续学习。

    暂无数据