CPU的实模式

实模式下分段内存寻址

Intel 8086有20条地址线,故其可以访问 1MB 内存空间,即 0x00000 ~ 0xFFFFF。
但其寄存器只有16位,如果用单一寄存器来寻址,只能访问到 2^16(64KB)空间。于是,工程师通过先把16位段基址寄存器左移4位后变成20位,再加段内偏移地址,这样便足够形成20位地址。
这样虽然突破了16位寄存器作为偏移地址无法访问1MB空间限制,但却引入了新的问题。拿CS和IP寄存器来说,0xFFFF:0xFFFF 能访问的最大地址是 0xFFFF0 + 0xFFFF = 0x10FFEF,这已经超过了1MB内存空间。但寄存器宽度有限,最后会丢掉最高的1位,变成了0x0FFEF,这就是地址回卷。比如 0XFFFFF + 2,理论上是0x100001,实际上成了0x00001。

CPU的实模式_第1张图片
实模式下高端内存回卷.png

·

实模式下内存布局

实模式下 1MB 内存分布。

起始地址 结束地址 大小 用途
FFFF0 FFFFF 16B BIOS入口地址,此地址也属于BIOS区域
F0000 FFFEF 64KB-16B BIOS区域
C8000 EFFFF 160KB 映射硬件适配器的ROM或内存映射式I/O
C0000 C7FFF 32KB 显示器适配BIOS
B8000 BFFFF 32KB 用于文本模式显示适配器
B0000 B7FFF 32KB 用于黑白显示器适配器
A0000 AFFFF 64KB 用于彩色显示器适配器
9FC00 9FFFF 1KB EBDA,扩展BIOS区域
07E00 9FBFF 约608KB 可用区域
07C00 7DFF 512B MBR被BIOS加载到此处
00500 07BFF 约30KB 可用区域
00400 004FF 256B BIOS Data Area (BIOS数据区)
00000 003FF 1KB Interrupt Vector Table(中断向量表)

地址总线的宽度决定了可以访问内存空间的大小,在计算机中,并不是只有主板上的内存条需要通过地址总线访问,还有些外设同样是通过地址总线来访问。(这里0 ~ 0x9FFFF处为物理内存)

CPU的实模式_第2张图片
地址映射.png
CPU工作原理:

CPU大体上可以划分为3个部分,它们是控制单元存储单元运算单元

控制单元要取下一条待运行的指令,该指令的地址在程序计数器PC中,意即CS:IP。读取IP寄存器后,将此地址送上地址总线,CPU根据此地址便得到了指令,放在指令寄存器中。

然后指令译码器确定操作码是什么,检查操作数类型,若是在内存中,就将相应操作数从内存中取回放入自己的存储单元,若操作数是在寄存器中,就直接用。

操作码和操作数都准备好了之后,操作控制器给运算单元下令,开工,于是运算单元一边开始运算,另一边指令IP寄存器的值被加上当前指令的大小,于是IP又指向了下一条指令的地址。

CPU的实模式_第3张图片
CPU工作原理示意图.png
实模式下的寄存器

在实模式下,默认寄存器都是16位的。

  • 段寄存器


    CPU的实模式_第4张图片
    段寄存器.png
  • 通用寄存器


    CPU的实模式_第5张图片
    通用寄存器.png
寄存器 助记名称 功能描述
ax 累加器
bx 基址寄存器 默认DS为段寄存器,用此地址为基址,遍历一块内存区域
cx 计数器 用于循环指令计数
dx 数据寄存器 保存外设控制器端口号
si 源变址寄存器 常用于字符串操作的数据源地址
di 目的变址寄存器 常用于字符串操作的目的地址
sp 栈指针寄存器 配合栈段寄存器SS,用来指向栈顶
bp 基址指针寄存器 默认SS为段寄存器,通过ss:bp把栈当成普通的数据段访问
  • 状态寄存器
实模式下CPU内存寻址方式

寻址方式,分为3大类:

  • 寄存器寻址
  • 立即数寻址
  • 内存寻址
    • 直接寻址
    • 基址寻址
    • 变址寻址
    • 基址变址寻址
寄存器寻址
mov ax, 0x10
mov dx, 0x9
mul dx

只要牵扯到寄存器的操作,无论是源操作数,还是目的操作数,都可以算作是寄存器寻址。

立即数寻址
mov ax, 0x18
内存寻址:直接寻址
mov ax, [0x1234]
mov ax, [fs:0x5678]
内存寻址:基址寻址

操作数中用 bx 寄存器或 bp 寄存器作为地址的起始,地址的变化以它为基础(实模式下必须用bx或bp,保护模式没有这个限制),bx 寄存器默认段寄存器是 ds,而 bp 寄存器的默认段寄存器是 ss(用来访问栈)。

内存寻址:变址寻址

变址寻址和基址寻址类似,只是寄存器由 bx,bp 换成了 si 和 di 。si 是指源寄存器,di 是指目的索引寄存器。两个寄存器的默认段寄存器也是 ds

mov [di], ax              ; 将寄存器ax的值存入ds:di指向的内存
mov [si+0x1234], ax       ; 变址中也可以加个偏移量

变址寻址主要用于字符搬运方面的指令,比如 movsb,movsw,movsd。

内存寻址: 基址变址

基址寻址和变址寻址的结合,即基址寄存器 bx 或 bp 加一个变址寄存器 si或 di。

mov [bx+di], ax  ; 将ax的值送入以 ds 为段基址,bx+di 为偏移地址的内存
mov [bx+si], ax
CPU的实模式_第6张图片
栈.png
  • push ax
    mov bp, sp  ; bp 默认段寄存器是SS
    sub bp, 2
    mov [bp], ax
    
  • pop
    
    
实模式下的 call 指令

在8086处理器中,有2个指令用于改变程序流程,一个是jmp,一个是call,它们的区别是 jmp 属于一去不回头的执行新的代码,而 call 指令用于执行一段代码之后再回来的情况。

  • 16位模式相对近调用
    call 指令所调用的目标函数和当前代码段是同一个段。
    call near 立即数地址    ; near 可以省略。
    
    指令中立即数地址可以是被调用的函数名,标号,立即数。
实模式下的 ret 和 retf 指令

call 指令只负责去,而返回用 retretf 指令,所以 call 指令需要配合 ret 使用。

  • ret 指令的功能是在栈顶弹出 2 个字节的内容来替换 IP 寄存器,所以ret用于近返回。
  • retf 指令的功能是从栈顶取出 4 字节,栈顶处的 2 字节用来替换 IP 寄存器,另外 2 字节用来替换 CS 寄存器,所以retf 用于远返回。
实模式下的 jmp 指令

jmp 指令就是更新 CS:IP 的值

  • 16位实模式相对短转移
    section call_test vstart = 0x900
    jmp short start    ; 机器码: ebfe  fe = 127
    times 127 db 0
    start:
      jmp $
    
    相对短转移的机器码大小是 2 字节,操作码是 eb,则操作数只有 1 字节,所以相对短转移范围只有 -128 ~ 127。
  • 16位模式相对近转移
    相对近转移和短转移相比,操作数的范围变为 16 位,即 -32768 ~ 32767,操作码是 e9。
    section call_test vstart = 0x900
    jmp near start    ; 机器码: e98000  8000 0x0080(小端字节序: 高字节存于高地址) = 128
    times 128 db 0
    start:
      mov ax, 0x1234
      jmp $
    
  • 16位模式间接绝对近转移
    相比于上面 2 种,这种模式下,其目标地址是绝对地址。并且未在指令中直接给出,存在寄存器或内存中。
    section call_test vstart=0x900
    mov ax, start        ; 机器码: b88509
    jmp near ax          ; 机器码: ffe0, ax 存的是start的绝对地址(不是偏移量),地址用寄存器给出。
    times 128 db 0
    start:               ; 绝对地址:0x985
      mov ax, 0x1234
      jmp $
    
  • 16位模式直接绝对远转移
    直接,操作数是立即数
    绝对,绝对地址。
    远,跨段。
    section call_test vstart=0x900
    jmp 0 start
    times 128 db 0
    start:
      mov ax, 0x1234
      jmp $
    
  • 16 位实模式间接绝对远转移
    间接,操作数在内存中。(需要段基址和偏移量,所以1个寄存器不可能)
    绝对,绝对地址。
    远,跨段。
    section call_test vstart=0x900
    jmp far [addr]            ; 机器码: ff2e8409  0x0984
    times 128 db 0
    addr dw start, 0        ; 地址: 0x984
    start:
      mov ax, 0x1234
      jmp $
    
    far 指示CPU在内存中取4个字节,前2个字节是段内偏移地址,后2个字节是段基址。
标志寄存器flags

实模式下是16位 flags 寄存器,保护模式下是32位 eflags 寄存器。

eflags.png
  • CF
    Carry Flag 意为进位,数值运算中最高位是进位,还是借位,CF位都会置为1。

  • PF
    Parity Flag 意为奇偶位,用于标记结果中低8位中1的个数。用于奇偶校验,判断数据是否传输出错。

  • AF

  • ZF
    Zero Flag,意为零标志位,计算结果为0标记为1,否则为0。

  • SF
    Sign Flag,意为符号标志位,若运算结果为负,则SF位为1,否则为0。

  • TF
    Trap Flag,意为陷阱标志位,此位为1,用于让CPU进入单步运行方式。

  • IF
    Interrupt Flag,意为中断标志位,若 IF 为1,表示中断开启,CPU 可以响应外部可屏蔽中断。为 0,表示中断关闭,CPU 不再响应来自 CPU 外部可屏蔽中断。

  • DF
    Direction Flag,意为方向标志位。用于字符串操作指令中,

  • OF
    Overflow Flag,意为溢出标志位

  • IOPL
    Input Output Privilege Level,CPU中4个任务特权级。

  • NT
    Nest Tak,意为任务嵌套标志位。

  • RF
    Resume Flag,恢复标志位,用于调试。

  • VM

  • AC

  • VIF

  • VIP

  • ID

有条件转移

你可能感兴趣的:(CPU的实模式)