最近在学习汇编的时候,每次debug的时候对于小白来说真的是一头雾水,完全不明白这些个寄存器究竟是什么东西。之前没有记住,所以这篇文章就用来稍微记录一下。
8086CPU 有 14 个寄存器,寄存器是CPU中程序员可以用指令读写的部件,程序员通过改变各种寄存器中的内容来实现对CPU的控制。
这些寄存器是:AX, BX, CX, DX, SI, DI, SP, BP, IP, CS, SS, DS, ES, PSW。
个人建议(当然我们汇编老师也是这样建议的)赶紧背下来,贯穿了整本书。。。
首先呢,是存放数据,在c语言中会定义变量进行数据的存储,而8086机中使用的是通用寄存器:AX, BX, CX, DX
1 | 用于存放一般性的数据。注意:这些都是16位的寄存器。 |
8086CPU在访问内存时要由相关部件提供内存单元的段地址和偏移地址,送入地址加法器合成物理地址,那用什么来存放段地址呢?
没错!就是段寄存器啦~
请注意哦,8086CPU不支持将数据直接送入段寄存器的操作,请先将数据存放进通用寄存器后,如bx,再将bx中的内容送入段寄存器中~
(为什么8086CPU不支持将数据直接送入段寄存器的操作呢?嘻嘻,这属于8086CPU硬件设计的问题,我们不用管啦~)
先介绍用来__指示CPU当前要读取指令的地址__!他们是最关键的w
1 | CS为代码段寄存器,IP为指令指针寄存器。。用于指示CPU当前要读取指令的地址。 |
一个程序执行时,由 IP 存放具体的指令地址,当然这个地址应该在 CS 中,PS中的标志会随着指令的执行情况而变化。简单来说,就是任意时刻,8086机中,CPU将CS:IP指向的内容当作指令执行~
那么,要去找一个内存单元,往房间存放东西的时候,就需要知道它的门牌号呀,也就是它的地址。而内存地址由段地址和偏移地址(好像基本大家的物理地址都是由段地址和偏移地址做了玄妙的计算之后得出来的)而8086CPU使用DS寄存器来存放要访问数据的段地址。
1 | DS段寄存器,用于存放要访问数据的段地址。 |
在使用mov 寄存器名, 内存单元地址
的时候如果不显式指明,8086CPU会自动取ds中的数据为内存单元的段地址。
接下来就讲到了栈,那么CPU可以通过CS:IP知道当前要执行的指令所在的位置,那么!它怎么知道栈顶的位置呢!嘻嘻那么就是SS:SP发挥作用的时候了
1 | 栈顶的段地址存放在SS中,偏移地址存放在SP中。任意时刻,SS:SP指向栈顶元素。 |
push,pop指令实质上就是一种内存传送指令,可以在寄存器和内存之间传送数据,但是push和pop指令访问的内存单元的地址不是在指令中给出的,而是由SS:SP指出的,同时,push和pop指令还会改变SP中的内容。
1 | PS 用来存放程序的标志 |
对各个寄存器做一下总结
CPU对寄存器还是有比较多要求的,比如说loop的时候只能用cx计数。当有多重循环的时候,内层的循环可能会使cx的值发生改变,于是可以使用以下方法寄存cx的值:
- 将cx的值寄存在其他reg(寄存器)中。缺点:当寄存器不够用的时候怎么办呢?
- 数据段中dw一个数据,使用它来寄存cx的值。缺点:
关于debug
- 程序加载后,ds中存放着程序所在内存区的段地址,这个内存区的偏移地址是0,则程序所在的内存区的地址为ds:0
- 这个内存区的前256个字节中存放的是PSP,DOS用来和程序进行通信,从256字节处向后的空间存放的是程序。
请注意,在汇编源程序中,数据不能以字母开头,需要在前面加0。如0ffffH
PSP占256(100H)字节,
在debug中的时候,注意要使用P命令执行int 21。
1 | U 看一下其他命令 |
在dos中用debug test.exe
运行Debug对test.exe进行跟踪时,程序加载的顺序是:command加载Debug,Debug加载test.exe。返回的顺序是,从test.exe中的程序返回到Debug,从Debug返回到command。
在使用debug模式的时候,使用r检查当前各个寄存器的情况,DS和CS之间我一直想知道他们的关系。
1 | cs是值cpu执行的当前指令的段地址,ds是数据开始的段地址。 |
简单的实例学习
- 王爽汇编 P127, 将程序中给定的数据逆序存放
代码编写如下:
1 | assume cs:codesg |
masm以及link过后,进入debug模式,-r查看各寄存器的状态,请注意DS,CS之间的地址差距。正确理解~(大概是我不想写了,所以有空再解释)