赞
踩
文章中涉及的机器默认为8086CPU
和8086PC机
8086有14个寄存器,其中AX BX CX DX通常存放一般数据,可以简单认为他们就是变量。例如:mov ax,4E20H
就是将数据存入AX。add ax,1406H
就是将数据加到原有的值上。
8086的寄存器有16个比特位,他可以当作两个8比特位的寄存器使用。这两个寄存器分别叫AL,AH(我猜测是low和high的缩写)。mov al,78H
就是将78存入低位字节中。当使用al、ah时,ax就被视为分离的寄存器,al、ah之间独立不相互影响,比如al存入的数值过大,就将多余的比特忽略,而不是进位到ah中。
在汇编语言中,不区分大小写。
8086CPU是16位结构,有16根数据线,也就是说该CPU的运算器、寄存器、控制器一次性只能处理两个字节的数据。
8086CPU的地址总线宽度为20,也就是内存寻址大小为2^20=1MB。那么CPU在和内存交互的时候,比如CPU读取内存数据,寄存器保存内存物理地址,但是只能保存16位,那怎么凑出20位呢?
基于这个问题,8086自身设计了物理地址 = 段地址 * 16 + 偏移地址
的方式,将段寄存器中保存的段地址,传输到CPU中的地址加法器,在加法器中,段地址左移4位(这样就完成了20位的匹配)变为基础地址,再加上一个偏移地址,最终得到物理地址。偏移地址同样是16位比特组成,最大寻址范围为2^16=64KB。
例如:段寄存器中提供段地址为1230H,偏移地址为00C8H,那么物理地址为12300H + C8H = 123C8H。
8086中的段寄存器有CS DS SS ES,这里只拿CS进行介绍。
段地址放在CS中,偏移地址放在IP中,IP在8086中叫做指令指针寄存器。或许你听说过,有一个指针指向被执行的汇编指令,当指令被执行后,该指针自动下移至下一条命令开始位置。
没错,这个指针就是IP。
在内存中,一段连续的空间可以称为段,比如从20000H到2000AH,如图这段空间内存放的是汇编指令(二进制化的汇编指令),我们可以称这个段为代码段。
那么要想读取20000H到20001H这段空间,单纯用段寄存器中的2000H无法做到,必须将其乘16,变为基础地址。然后通过偏移量IP指针的移动,读取指向的内存单元。
所以你现在可以明白,偏移量最大为2^16,那么指针可移动的范围为64KB,这意味着一段就是64KB。
综上,8086CPU的工作过程:
怎么区分内存中存储的二进制是“数据“还是“指令“?
我们知道,存储于机器中的只有0和1,那么有的01组成的是一段常量,比如00111001011(瞎写的)就单纯的表示常量3.14;比如1110111011就表示指令mov。计算机是如何区分指令和普通数据的呢?
答案很简单,被CS:IP指向的内存空间,其中的01就表示指令。某一段信息被CPU执行过,那么它一定被CS:IP指向过。
怎么修改CS,IP中的值?
jmp命令可以修改。如果想同时修改CS和IP的值,可以使用jmp 2AE3:3
,这样CS中的值就为2AE3H,IP中的值就为3H,CPU将从2AE33H中读取数据。
如果只想修改IP中的数值,可以使用jmp <某个合法寄存器>
,比如现有一寄存器ax=1000H,CS=2000H,IP=0003H。执行jmp ax
后,ax=1000H,CS=2000H,IP=1000H。jmp ax
就好比mov IP,ax
。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。