寄存器及数据存储

CPU 的组成

  • 运算器进行信息处理
  • 寄存器进行信息存储
  • 控制器协调各种器件进行工作
  • 内部总线实现CPU 内各个器件之间的联系
CPU的组成

寄存器是CPU 内部的信息存储单元

8086 有14 个寄存器

  • 通用寄存器: AX, BX, CX, DX
  • 变址寄存器: SI, DI
  • 指针寄存器: SP, BP
  • 指令指针寄存器: IP
  • 段寄存器: CS, SS, DS, ES
  • 标志寄存器: PSW

它们的共性为都是16 位的, 可以存放两个字节

例如通用寄存器AX, 能存储一个16 位的数据, 最大值为2^{16} -1

如何保证对上一代的兼容? 将通用寄存器分为2 个独立的8 位寄存器使用, 例如将AX 分为AH, AL 高位和低位. 相应的8086 的字长为16bit, 高位存在高8 位寄存器, 低位存在低8 位寄存器

寄存器 寄存器中的数据 表示的值
AX 0100111000100000 20000(4E20H)
AH 01001110 78(4EH)
AL 00100000 32(20H)

mov 和add 指令

举例, AX 和BX 值默认是0000H

指令 执行后AX 中的数据 执行后BX 中的数据
mov ax, 4E20H 4E20H 0000H
add ax, 1406H 6226H 0000H
mov bx, 2000H 6226H 2000H
add ax, bx 8226H 2000H
mov bx, ax 8226H 8226H
add ax, bx 044CH 8226H
指令 执行后AX 中的数据 执行后BX 中的数据
mov ax, 001AH 001AH 0000H
mov bx, 0026H 001AH 0026H
add al, bl 0040H 0026H
add ah, bl 2640H 0026H
add bh, al 2640H 4026H
mov ah, 0 0040H 4026H
add al, 85H 00C5H 4026H
add al, 93H 0058H 4026H

物理地址确定的方法

物理地址

所有的内存单元构成的存储空间是一个一维的线性空间, CPU 访问内存单元时要给出内存单元地址, 每一个内存单元在这个空间中都有唯一的地址, 这个地址就被称为物理地址.

物理地址

但是8086 有20 位地址总线, 寻址能力为1M. 而8086 是16 位结构的CPU, 运算器以此最多可以处理16 位的数据, 寄存器的最大宽度为16 位, 在8086 内部处理的, 传输, 咱村的地址也是16 位, 寻址能力也只有64KB, 如何解决呢?

物理地址确定方法

用2 个16 位地址(段地址, 便宜地址) 合成一个20 位物理地址

物理地址 = 段地址 * 16 偏移地址

物理地址确定方法
通过加法器计算

本质含义为CPU 访问内存时, 用一个基地址(段地址 * 16) 和一个相对于基础地址的偏移地址相加, 给出内存单元的物理地址.

分段方式管理内存

实际中是没有分段, 段的划分来自于CPU

同一段内存, 可以有多中分段方案

但是, 1. 段地址 * 16 必然是16 的倍数, 所以一个段的起始地址也一定是16 的倍数. 2. 偏移地址为16 位, 16 位地址的寻址能力为64k, 所以一个段的长度最大为64k

例如

物理地址 段地址 偏移地址
21F60H 2000H 1F60H
2100H 0F60H
21F0H 0060H
21F60H 0000H
1F00H 2F60H

表示方法为2000:1F60H

专门的寄存器存放地址

  • CS 代码段寄存器
  • DS 数据段寄存器
  • SS 栈段寄存器
  • ES 附加段寄存器

debug 的使用

常见命令

用R命令查看、改变CPU寄存器的内容

用D命令查看内存中的内容

用E命令改变内存中的内容

用U命令将内存中的机器指令翻译成汇编指令

用A命令以汇编指令的格式在内存中写入机器指令

用T命令执行机器指令

用Q 命令退出debug

R 命令的使用

R命令查看和修改寄存器

D 命令查看内存内容

d命令查看内容
  • 默认128 个字节内容
  • 段地址:偏移地址, 列出内存中指定地址处的内容
  • 段地址:偏移地址 结尾偏移地址, 列出内存中指定地址范围内的内容

E 命令改变内存中的内容

E命令修改寄存器内容
  • 段地址:偏移地址 数据1 数据2 ...
  • 段地址: 偏移地址
    • 逐个询问修改
    • 空格, 接受 继续
    • 回车, 结束

U 命令, 将内存中的机器指令翻译成汇编指令

  • 汇编指令为

    mov ax, 0123H

    mov bx, 0003H

    mov ax, bx

    add ax, bx

  • 对应的汇编为

    B8 23 01

    BB 03 00

    89 D8

    01 D8

  • e 地址 数据, 写入

  • d 地址, 查看

  • u 地址, 查看代码

u命令查看代码

A 命令以汇编指令的格式在内存中写入机器指令

  • 汇编指令为

    mov ax, 0123H

    mov bx, 0003H

    mov ax, bx

    add ax, bx

  • 对应的汇编为

    B8 23 01

    BB 03 00

    89 D8

    01 D8

  • a 地址, 写入汇编指令

  • d 地址, 查看数据

  • u 地址, 查看代码

a命令修改内容
u命令查看代码

T 命令执行机器指令

mov ax, 0123H

mov bx, 0003H

mov ax, bx

add ax, bx

t命令逐步执行命令

CS 和IP 寄存器

CS: 代码段寄存器

IP: 指令指针寄存器

CS:IP, CPU 将内存中的CS:IP 指向的内容当做指令执行

以上代码的执行过程为

  • 从CS:IP 执行内存单元读取指令, 读取的指令进入指令缓冲器
  • IP = IP + 所读取指令的长度, 从而指向下一条指令
  • 指向指令, 重复第一步
cs:ip执行过程

而内存中有数据B8 23 01 BB 03 00 89 D8 01 D8 是一段数据还是指令呢?

CPU 将CS:IP 指向的内存单元中的内容看做指令

jmp 指令

使用jmp 来修改cs 和ip 指令

例如

jmp 段地址:偏移地址

jmp 2AE3:3

jmp 3:0B16

用指令中给出的段地址修改cs, 偏移地址修改ip

尽修改ip 内容

jmp 某一合法寄存器

jmp ax, 类似于mov IP,ax

jmp bx

用寄存器中的值修改IP

jmp指令应用

从20000H 开始, 执行序列:

  1. mov ax,6622
  2. jmp 1000:3
  3. mov ax,0000
  4. mov bx,ax
  5. jmp bx
  6. mov ax,0123H
  7. 转到第3 步继续执行

用DS 和[address] 实现字的传送

问题 CPU 从内存单元中要读取数据

要求: CPU 要读取一个内存单元的时候, 必须先给出这个内存单元的地址

原理: 在8086 中, 内存地址由段地址和偏移地址组成

解决: DS 和[address] 配合

  • 用ds 寄存器存放要访问的数据的段地址
  • 偏移地址用[...] 形式给出

mov bx,1000H

mov ds,bx

mov al,[0]

将10000H(1000:0) 中的数据读到al 中

mov bx,1000H

mov ds,bx

mov [0],al

将al 中的数据写到10000H(1000:0) 中

注意不可以使用mov ds,1000H, 8086 不支持将数据直接写入段寄存器

方法应为: 数据 -> 一般寄存器 -> 段寄存器

对内存单元中的数据访问

可以根据需要将一组内存单元定义为一个段

  • 物理地址 = 段地址 * 16 + 偏移地址
  • 将一组长度为N(N<= 64k) 地址连续, 起始地址为16 的倍数的内存单元当做专门存储数据的内存空间, 定义一个数据段

处理方式(DS):([address])

  • 用DS 存放数据段的段地址
  • 用相关指令访问数据段中的具体单元, 单元地址由[address] 指出

例如1: 累加数据段中的前3 个单元中的数据

mov ax,123BH
mov ds,ax
mov al,0
add al,[0]
add al,[1]
add al,[2]
累加前3个单元

例2: 累加数据段中的前3 个字型数据

mov ax, 123BH
mov ds,ax
mov ax,0
add ax,[0]
add ax,[2]
add ax,[4]

总结

用mov 指令操作数据

指令形式 示例
mov 寄存器,数据 mov ax,8
mov 寄存器,寄存器 mov ax,bx
mov 寄存器, 内存单元 mov ax,[0]
mov 内存单元, 寄存器 mov, [0],ax
段寄存器, 寄存器 mov ds,ax

加法add 和减法sub 指令

add 指令 示例
add 寄存器,数据 add ax,8
add 寄存器,寄存器 add ax,bx
add 寄存器,内存单元 add ax,[0]
add 内存单元,寄存器 add [0],ax
sub 指令 示例
sub 寄存器,数据 sub ax,8
sub 寄存器,寄存器 sub ax,bx
sub 寄存器,内存单元 sub ax,[0]
sub 内存单元,寄存器 sub [0],ax

DS 和[address] 访问内存中数据段方法总结

  1. 字在内存中存储时, 要用两个地址连续的内存单元来存放, 字的低位字节存放在低地址单元中, 高位字节存放再高地址单元中
  2. 用 mov 指令要访问内存单元, 可以在mov 指令中只给出单元的偏移地址, 此时, 段地址默认在DS寄存器中
  3. [address] 表示一个偏移地址为address 的内存单元
  4. 在内存和寄存器之间传送字型数据时, 高地址单元和高8位寄存器, 低地址单元和低8位寄存器相对应
  5. mov, add, sub 是具有两个操作对象的指令, 访问内存中的数据段(对照: jmp是具有一个操作对象的指令, 对应内存中的代码段)

栈及其操作

栈是一种只能在一端进行插入或删除操作的数据结构

  • 入栈, 将一个新的元素放到栈顶
  • 从栈顶取出一个元素
push ax; 将ax 中的数据送入栈中
pop ax; 从栈中取出数据送入ax 中
都是以字为单位对栈操作

规则: LIFO 后进先出

在8086 中可以将一段内存当做栈来使用

问题一, CPU 如何直到一段内存空间当做栈使用?

问题二, 执行push 和pop, 如何直到哪个单元是栈顶单元

8086 中, 有两个与栈相关的寄存器

  • 栈段寄存器SS, 存放栈顶的段地址
  • 栈顶制作寄存器SP, 存放栈顶偏移地址

任意时刻, SS:SP 指向栈顶元素

mov ax,1000H
mov ss,ax
mov sp,0010H
AX BX SS SP
1000H 1000H 0010
mov ax,001AH
mov bx,001BH
AX BX SS SP
001AH 001BH 1000H 0010
push ax
push bx
AX BX SS SP
001AH 001BH 1000H 000C
pop ax
pop bx
AX BX SS SP
001BH 001AH 1000H 0010
执行过程

push ax

  1. SP = SP - 2
  2. 将ax 中的内容送入SS:SP 指向的内存单元, SS:SP 此时指向新的栈顶

pop ax

  1. 将SS:SP 指向的内存单元的数据送入ax
  2. SP = SP + 2, SS:SP 指向当前栈顶下面的单元, 以当前栈顶下面的单元为新的栈顶

注意栈顶超界的问题

栈小结

  • push pop 实质上就是一种内存传送指令, 可以在寄存器和内存之间传送数据, 与mov 不同, push 和pop 指令访问的内存单元地址不是指令中给出的, 而是SS:SP 指出的
  • 执行push 和pop 时, SP 中的内容会自动改变
  • 8086 提供栈操作机制
    • 在SS, SP 中存放栈顶段地址和偏移地址, 入栈出栈指令根据SS:SP 指示的地址, 按照栈的方式访问内存单元
    • push 执行步骤
      • SP = SP - 2
      • 向SS:SP 指向的字单元中送入数据
    • pop 步骤
      • 从SS:SP 指向的字单元中读取数据
      • SP = SP - 2
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容