计算机 CPU 与寄存器知识

# 寄存器与物理地址

寄存器一般为 16 位,而地址总线可能大于 16
8086 处理器,寄存器为 16,地址总线为 20
如果我们想要寻址,该怎么办呢?
CPU 中存在好几个段寄存器 CS,DS,SS,ES 用于提供段地址。

段寄存器

CS 是代码段寄存器
DS 是数据地址
SS 是堆栈地址
ES 提供额外的地址 (什么都可以有)

我们需要理由 段地址偏移量 进行操作,这两个数据存储在两个寄存器中,段地址就是物理地址的头部,而偏移量是物理地址的尾部,通过将段地址左移再和偏移量相加,就可以得到完整地址。
举个栗子 段地址 16 进制若为 21F0H,偏移地址 0060H,此时段地址左移 1 位即 x16, 也是加 4 位的意思,此时共 20 位为 21F00H,这个时候加上偏移地址 0060H 可以得到 21F60H 这个 20 位地址
同一地址可以用不同组段地址 + 偏移量表示:
2000H + 1F60H ->21F60H
2100H + 0F60H ->21F60H
1F00H + 2F60H ->21F60H
以上都可表示为 段地址:偏移地址
IP 寄存器是指令指针寄存器,用于提供偏移地址。
CS 和 IP 最为关键,他们指示 CPU 要读取指令的地址,当 CS:IP 指向哪里,代码就执行到哪里

小测试

2AE3:3=?
3:0B16=?
答案是 2AE33 和 00B46

# CPU 执行指令过程

首次执行
CS:IP -> 地址加法器 -> CPU 输入输出线路 -> 存储器地址 -> 获取数据 (可能是多个字节) -> CPU 输入输出线路 -> CPU 执行控制器
第二次执行
CS:IP+(上次获取到的字节数) -> 地址加法器 -> CPU 输入 ......
新的指令执行IP=旧IP+指令读取长度

小知识

处理器通电后 CS 会被初始化为 FFFFH,IP 被初始化为 000H
即计算机开机会执行内存中 FFFF0H 的指令 (这是计算机执行第一条指令)

# debug 修改寄存器

Windows 打开 cmd 进入 debug

  • R 查看修改寄存器内容
  • D 查看内存内容
  • E 改写内存内容
  • U 将内存中机械指令翻译成汇编指令
  • T 执行一行机械指令 (从 CS:IP 开始)
  • A 以汇编语言在内存写入机械指令
    以上指令不区分大小写

# DS 寄存器和 [address]

获取指定地址的数据
将段地址存入 ds, 再通过偏移 [address] 获取数据

mov ax , 1000H
mov ds , ax
mov al , [0]

因为计算机 CPU 设计问题,不能直接使用 mov ds , 1000H
改写数据

mov ax , 1000H
mov ds , ax
mov [0], al

需要注意的是:如果你使用 16 位寄存器 (ax) 进行操作如 mov ax , [0] 那 ax 中将会存在 16 位数据,这些数据来自 [1] 和 [0], 如果你使用 8 位寄存器 (al) 进行操作如 mov al,[0] 那 al 中将会存在八位数据 (仅仅来自 [0])

# 栈与寄存器

栈是一段特殊内存,具有先进先出的规则,栈顶是栈的最高的存有数据的内存地址
段寄存器 SS 存放栈顶段地址
寄存器 SP 存放栈顶的偏移地址
任意时刻 SS:SP 指向栈顶地址
栈在代码编译的时候自动分配和销毁,每个函数都会有一个单独的栈,在函数执行时创建,执行完毕后销毁,栈的存在确保函数的相对封闭与数据的独立,当一个一个函数调用另一个函数时,调用者数据会进入栈中保存,被调用者执行完毕后,再从栈中读取数据继续执行,数据入栈和出栈顶顺序相反
用 push 命令入栈数据,pop 命令出栈数据
push 命令会根据当前的栈顶执行进行操作,数据入栈前会将偏移地址减去数据长度 (此处为 2, 因为寄存器为内存单元两倍), 然后再存入数据,而 pop 顺序则相反

如果要在10000H存入数据2266H
mov ax,1000H
mov ss,ax
mov sp,2
mov, ax,2266H
push ax

栈地址排列为上低下高,初始栈顶执行最高地址 + 1,CPU 只知道栈在哪,不会知道栈有多大,需要开发者注意越界

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

PangBai 微信支付

微信支付

PangBai 支付宝

支付宝

PangBai 贝宝

贝宝