汇编——寄存器的分类和功能

在汇编中,个人感觉最重要的部分其实就是寄存器了,这次我们了解一下寄存器的分类和功能。
先说一下寄存器是什么吧,其实就是一部分的空间,我们可以使用这些空间来存储内容
寄存器的空间都是16位的(80x86中,后来有增长),也就是1个字的空间。

堆栈则有一点不一样,我们的堆栈空间是在程序中定义的,可以存储很多个16位二进制数。
注意事项

  1. 堆栈的栈顶指针最开始是在栈顶的,栈顶为高位,也就是存储是从高到低的。
  2. 我们压栈出栈的过程本质上其实就是将我们寄存器的内容进行复制,而不是将寄存器就行移动(不会真的有人感觉是将寄存器拿走了吧,像数据结构那样)

我们一般将寄存器分为:通用寄存器、变址寄存器、指针寄存器和专用寄存器,最后还有一个段寄存器。

通用寄存器

就是我们经常拿来进行数据存放、数据使用的段,一共有四个:AX、BX、CX、DX。
AX:累加器,一般是用于计算
BX:基址寄存器,用来存放存储器地址
CX:计数器,循环操作中常用
DX:数据寄存器,在dos功能调用(比如输出显示)、乘除法中,都用来存储数据,作为默认项(乘除法的指令中我们默认的结果存放位置就有dx寄存器),还可以作为双字数据的高位。(比如一个32位数,我们就可以将16-31放在DX,低位习惯放在AX中)

(当然除了这些特殊性的行为,剩下的情况中这些寄存器基本上没有区别。)

上述的寄存器都是可以进行拆分的(其他的都不行),AX = AH+AL。
也就是我们可以将AH和AL当成两个8位的寄存器进行使用。

变址寄存器

比如数组,或者更具体的字符串,因为寄存器每次只能存储16位数据,所以一个字符串应当一位位的读取(尤其是字符串类型为 dw ),这里就涉及到了一个变址的问题,也就是在数组名这个地址基础上,我们当前的位置进行了多少的移动。
寄存器:SI(源寄存器)和DI(目的寄存器)

如果只有一个数组,两个寄存器用起来差不多,我们一般将SI/DI和DS联用(DS是后面讲的段寄存器),来确定数据段中某一个存储单元的地址。

如果是两个字符串操作,比如字符串的复制操作,我们就需要将原串放在SI,目的串放在DI,调用指令来处理。
而且一般我们将SI与DS段寄存器联用,用来确定源操作数的地址,DI与ES段寄存器联用,用来确定目的操作数的地址

程序:将mess2复制为mess1
在这里插入图片描述
这里我们使用的指令为lea,将数组的首地址给寄存器的意思。
cx寄存器放置的就是整个数组的大小,也就是我们需要移动的元素个数。
cld指令确定字符串是从左到右的顺序,rep movsb是循环指令,在字符串操作中常用的。

可以看出,我们并没有对si和di 的值进行修改,这是因为两者是可以自增的。

指针寄存器

之前提到的堆栈,我们所需要的指针就是存储在指针寄存器中。
指针寄存器分为两个,
一个是SP:堆栈指针寄存器,用于存放栈顶指针的位置
另一个是BP:基址指针寄存器,用于寻找栈内的元素。

比如我将几个元素都进行了压栈,然后发现自己需要栈内的一个元素,那么我们就可以修改SP指针,或者是使用SP指针来进行寻址,比如[SP+8]这样的方式。

专用寄存器

专用寄存器分为两大部分,首先是指令指针寄存器,然后是标志寄存器。

怎么还有指针寄存器?
我们的代码部分,如果在子程序或者循环部分进行单步调试查看IP寄存器的内容,可以发现在进行跳转的过程中IP指针发生了跳动,而正常情况下则是不断自增
我们要知道,其实在我们一行行的实现程序的过程中,我们的一条条指令都是有一个地址存放的,这样就需要有一个指针来指向当前的指令位置,方便我们取出,进行操作。这个寄存器就是IP寄存器。
IP寄存器在存储指令地址的时候,还有一个CS的段寄存器进行辅助,用来判断是哪一个代码段(我们可能不止一个代码段),这就和地址跳转扯上了关系,这里不多说,给出博客链接,感兴趣看一下,不看也不影响。

另一个标志寄存器FLAGS,存储了一些标志位,分为两种。
第一种:状态标志

  1. 进位标志CF
  2. 零标志ZF
  3. 符号标志SF
  4. 奇偶标志PF
  5. 溢出标志OF

其中CF又称为无符号数的溢出,而OF为有符号数的溢出。
几点前提:

  • 溢出只能发生在同类型相加或者不同类型相减
    如果是无符号数,那么就只可能是在相加时溢出。
  • a求补得到-a,再次求补为a

不论是有符号数还是无符号数,程序不需要知道,程序员知道就行;
程序员不需要知道结果是多少,只需要看数据类型对应的溢出标志位是0还是1,就能知道结果是否正确(虽然溢出了某种程度上也算正确)。

第二种是控制标志

  1. 方向标志DF
  2. 中断允许标志IF
  3. 陷阱标志TF

方向标志是在字符串操作中,我们通过这个标志位的数据来决定串的遍历方向,DF = 0则是从低到高。

中断允许标志控制外部可屏蔽中断是否可以被处理器响应,听起来有一点玄学,主要是用于中断的优先级问题上,这个开始还用不到,等到功能调用时中断会比较常见。(IF = 1,优需中断)

陷阱标志位TF
控制处理器是否进入单步操作方式,TF = 1,进入。
说白了其实就是单步调试的问题,单步过程中每运行一条指令就给一个单步中断,让处理器停止工作,等待下一条指令。

段寄存器

段寄存器主要就是确定该段在内存中的起始位置,感觉段寄存器和其他的寄存器就有一点像数组首地址和偏移地址的感觉。

主要原因还是8086的地址线为20条,但是我们的寄存器只有十六位,多的4位也不好不用,所以我们就采取了物理地址 = 段地址+偏移地址的寻址方式。
其中的段地址就在这些段寄存器中,而偏移地址的求法就千奇百怪了,在寻址的博客中有详细讲解,不影响我们的介绍。

段寄存器分为四个:

  • 代码段寄存器CS,和IP配合找到下一条指令的位置。
  • 数据段寄存器DS,能用来干很多事。
  • 堆栈段寄存器SS,和SP配合寻找栈顶。
  • 附加段寄存器ES,和DI配合用于串指令。

其中的CS和SS主要是针对多个代码段和堆栈段时,如何知道我们当前是哪个段的哪个位置。
DS就是万金油的感觉,在寻址过程中很多情况下的默认段寄存器都是DS。
ES用的会比较少,但是在串部分,我们会将es和di配合使用。

上面的寄存器肯定是不全,下面我们给出一个比较全的默认组合:

  1. CS IP
  2. SS SP or BP
  3. DS BX、DI、SI或一个16位数
  4. ES DI(用于串指令)

总结

这样我们就介绍了8086的寄存器种类,简单讲述了分工。
有一些确实只是在特定的情况下才会遇到,直接上去说就会显得很繁琐,碰到具体问题会进行详细阐述的。

  • 8
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值