Hi~朋友,点点关注不迷路
摘要
1. 寄存器
寄存器是一种物理存储原件,速度可以跟上CPU的速度,所以CPU内部使用各种类型的寄存器供读取数据来使用。这里可以看出寄存器的主要用途:
CPU中的寄存器大致分为两类:
实模式下默认用到的寄存器都是16位。
1.1 内部寄存器
内部寄存器虽然不可以直接使用,但是部分寄存器必须要通过我们的代码进行初始化。
1.2 可见寄存器
1.2.1 段寄存器
段寄存器是CPU用来寻址使用,CPU默认的寻址方式是"段基址":"段内偏移地址",段基址就是用段寄存器来进行存储。
在我们计算机加载我们的程序以后,会将我们的应用程序在内存大致分为三个部分:
段寄存器主要由以下分类:
可见寄存器CS:内部寄存器IP存储了CPU下一条待执行指令的地址。
1.2.2 通用寄存器
通用寄存器主要由以下几类组成:
2. 实模式下的CPU寻址
指令都是由操作码和操作数组成,操作数可以是源操作数、目的操作数,寻址就是寻找操作数的地址。
寻址的方式主要分为以下三类:
2.1 寄存器寻址
只要牵涉到寄存器的操作,无论是源操作数还是目的操作数,都是寄存器寻址。
; 将0x10存入ax寄存器
mov ax, 0x10
;将0x9存入dx寄存器
mov dx, 0x9
;求ax和dx的乘积,高16位在dx寄存器,低16位在ax寄存器
mul dx
这三条命令都属于寄存器寻址。
2.2 立即数寻址
指令都是由操作码和操作数组成,如果操作数可以直接存在指令中,拿过来即可使用,那么该数成为立即数。
mov ax, 0x10
mov dx, ax
第一条命令的源操作数是0x10,目的操作数是ax寄存器,所以第一条命令即是寄存器寻址又是立即数寻址。
第二条命令只涉及到寄存器,因此它只是寄存器寻址。
2.3 内存寻址
寄存器寻址和立即数寻址中,源操作数和目的操作数不在内存中。相反操作数在内存中的寻址方式则成为内存寻址。
实模式下CPU访问内存采用的是段基址:段内偏移的形式,计算方式是 物理地址 = 段基址*16(相当于左移4位) + 段内偏移地址,默认情况下,数据段寄存器是DS。
内存寻址的方式主要有:
2.3.1 直接寻址
直接寻址就是将操作数的内存地址在指令中直接给出。
mov ax, [0x1234]
mov ax, [fs:0x5678]
第一条指定是将内存地址为(DS*16 + 0x1234)的值写入ax寄存器。
第二条指定是将内存地址为(FS*16 + 0x5678)的值写入ax寄存器。
2.3.2 基址寻址
基址寻址是指操作数用BX寄存器或BP寄存器作为地址的开始,地址的变化都以其为基础。实模式下只能使用BX或BP寄存器作为基址,保护模式下则无这种限制。
BX寄存器的默认段寄存器为DS,BP寄存器的默认段寄存器为SS。
2.3.3 变址寻址
变址寄存器类似于基址寄存器,寄存器由BX、BP换成了SI、DI。SI是指源索引寄存器、DI是指目的索引寄存器。默认的端寄存器都是DS。
mov [di], ax
mov [si+0x1234], ax
第一条指令是将寄存器AX中的值存入DS:DI指向的内存地址处。
第二条指令是将寄存器AX中的值存入DS:(DI+0x1234)指向的内存地址处。
2.3.4 基址变址寻址
基址变址寻址就是采用基址变址+变址寻址的组合。如下:
mov [bx+di], ax
该条指令的含义就是将寄存器AX中的值存入DS:(BX+DI)指向的内存地址处。
3. 栈
栈是一种什么数据结构这里就不说了,我们这里讲的栈是一片内存区域,栈中的内存地址也是采用段寄存器SS中的值*16 + 栈指针寄存器SP来访问。
硬件提供了响应的方法来存取栈,即PUSH和POP指令。
栈是从高地址往低地址发展,因此栈顶的指针指向的地址会越来越低。
我们在访问栈的时候,访问的内存依然是从低地址到高地址,假设当前栈顶是0x1233E,栈顶数据如果占2字节的话,则范围是0x1233E~0x1233F。
PUSH指令压入数据的过程:
POP指令弹出数据的过程:
本期寄存器及实模式下CPU的寻址方式就介绍到这,我们下期再见!
感谢阅读,欢迎“点赞”+“关注”
赏个在看吧,你的点赞是对我最大的鼓励