动态线条
动态线条end

寄存器与内存

寄存器及数据存储

8086寄存器(寄存器都是16位的)

通用寄存器:AX、BX、CX、DX

变址寄存器:SI、DI

指针寄存器:SP、BP

指令指针寄存器:IP

段寄存器:CS、SS、DS、ES

标志寄存器:PSW

兼容性问题(16位寄存器兼容旧机器的8位寄存器)

由于兼容问题的产生,因此通用寄存器被分为两部分,如AX的高八位又被称作AH寄存器,低八位被称作AL寄存器。另外三个通用寄存器同理。

寄存器名称 高八位(8-15) 低八位(0-7)
AX AH AL
BX BH BL
CX CH CL
DX DH DL
8086是16位CPU,因此它的字长为16位,一个字可以存储在一个16位寄存器中

1)这个字的高位字节存储在这个寄存器的高八位寄存器

2)这个字的低位字节存储在这个寄存器的低八位寄存器

MOV和ADD指令

指令应用范例

汇编指令 控制CPU完成的操作 高级语言描述
mov ax,18 将18送入AX AX = 18
mov ah,78 将78送入AH AH = 78
add ax,8 将寄存器AX中的值加上8 AX = AX + 8
mov ax,bx 将寄存器BX中的数据送入寄存器AX AX = BX
add ax,bx 将AX,BX中的内容相加,结果存入AX中 AX = AX + BX

需要注意(如果执行下述两条命令,假设AX寄存器初始值为0000H)

add al,FFH

add al,FFH

其结果为EF,而不是1EF,而AX寄存器值为00EFH

mov指令操作数据(不需背诵)

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

确定物理地址的方法

物理地址

1)cpu访问内存单元时要给出内存单元的地址

2)所有的内存单元构成的存储空间是一个一位的线性空间

3)每一个内存单元在这个空间中都有唯一的地址,这个唯一的地址称为物理地址

8086的尴尬

1)8086有20根地址总线,寻址能力为1MB

2)8086是16位结构的cpu,一次性处理的数据最大宽度为16

3)因此在传递地址上,出现了矛盾

解决矛盾方法

利用两个16位的地址(段地址,偏移地址),合成一个20位的物理地址

地址转换公式

物理地址 = 段地址 * 16 + 偏移地址
实例:
20100H = 2000H * 16 + 0100H

根据上述公式,可以简单的理解到,段地址一定是16的倍数(废话),并且物理地址的确定可以通过不同的段地址与偏移地址构成,类似 6 = 1+5 与 6 = 2+4等,因此物理地址的计算过程不唯一。

内存的分段表示法

8086用“段地址 * 16 + 偏移地址”来计算物理地址的方法获取真实的物理地址。但是内存并没有真正的分段,段的划分来自于CPU

段划分

8086的地址线为20根,将二十个二进制转换为十六进制就是五位(下方横线代替五位十六进制)
_ _ _ _ _

由于物理地址的计算公式是“段地址 * 16 + 偏移地址”,因此每次分配段大小时,都要一次性分配四位二进制位,也就是一位十六进制位

如果我们将前一位当成段地址
_ | _ _ _ _
该情况下
段取值范围:  0-F
偏移取整范围:0000-FFFF

如果我们将前两位当成段地址
_ _ | _ _ _
该情况下
段取值范围:  00 - FF
偏移取值范围:000 - FFF

其余情况同上述规律,因此我们可以观察到,段的划分由我们或者说由cpu决定,真实的物理空间并没有它所代表的含义而变大或者变小。
在寻址过程中,段地址与偏移地址组合形成物理地址,但是偏移地址的最大值不能超过64K,因为寄存器是16位的寄存器

综上:我们经常应用情况一,来作为平时书写物理地址的格式:(2000:1F60)
	2 0 0 0    (段地址)
+	  1 F 6 0  (偏移地址)
---------------
	2 1 F 6 0  (物理地址)

段地址很重要,因此用专门存放段地址的寄存器

1)CS - 代码段寄存器

2)DS - 数据段寄存器

3)SS - 栈段寄存器

4)ES - 附加段寄存器

DEBUG的使用

Debug是什么?

debug是dos系统中著名的调试程序,也可以运行在windows系统模式下。可以查看cpu中的内容、内存情况,并且在机器指令级跟踪程序的运行。

DEBUG常用命令

命令 功能
R 查看、改变CPU寄存器的内容
D 查看内存中的内容
E 改变内存中的内容
U 将内存中的机器指令翻译成汇编指令
A 以汇编指令的格式在内存中写入机器指令
T 运行机器指令

启动debug

1)打开dosbox,输入指令,将masm文件夹挂载到C盘

mount c e:\masm

image-20220106175603950

e:\目录下存放编译汇编程序的文件,才会将这个文件夹挂载到dosbox的c盘

image-20220106175649781

2)直接输入debug,显示“-”符号,证明进入到了debug环境中,如下图

image-20220106175857574

3)尝试用r命令查看寄存器内容:

image-20220106175949552

更改寄存器内容

r 寄存器名称

image-20220106180220162

4)利用d命令查看内存中的内容,之前提到过的段地址与偏移地址的书写格式,是个人习惯,但是物理地址计算公式是恒定不变的

image-20220106180709007

查看指定位置的数据内容

d 段地址:偏移地址

image-20220106180916081

限定查看的数据范围,比如限定只显示偏移地址从 100 到 10F

d 段地址:偏移地址 结尾偏移地址

image-20220106181059249

注意:利用d查看指定地址之后,直接输入d命令执行,其显示的内容为,指定地址的后序地址内容,地址是连续的

image-20220107092424112

5)利用E命令,改变指定内存位置的数据内容,如下操作:

e 段地址:偏移地址 数据1 数据2 数据3 ...

image-20220106181436566

利用e的逐位询问的修改方法(如果旧数据比对成功,则进行修改)

逐个询问式修改:该模式下,每次修改数据前,系统会显示当前地址下的数据值大小

应用格式:
	e 段地址:偏移地址 

操作:
	空格:继续修改操作
	回车:结束修改

image-20220106182131605

6)用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 地址(查看代码)

image-20220107084107862

7)用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地址(查看代码)

image-20220107084954006

image-20220107085142763

8)T指令执行CS:IP处的指令,并且显示执行后寄存器的值

image-20220107085604776

9)Q命令退出debug

CS、IP与代码段

CS:代码段寄存器

IP:指令寄存器

8086PC工作过程的简要藐视

1)从cs:ip指向内存单元读取指令,读取的指令进入指令缓冲器

2)ip = ip + 所读取指令的长度,从而指向下一条指令

3)执行指令,转到步骤1,重复这个过程

     如下操作,改变cs、ip的地址指向,利用t命令进行指令的执行

image-20220107091922797

jmp指令

修改cs、ip的指令

执行何处的指令,取决于cs:ip

可以通过改变cs:ip中的内容,来控制cpu要执行的目标指令

改变IP的方法

1)通过调试r命令改变IP值

2)通过cpu自主运行,每执行完一条指令,ip值自行加刚刚执行指令长度值

3)通过jmp指令跳转指定地址,cpu更改cs:ip值

转移指令

1)同时修改cs:ip的内容

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

jmp 段地址:偏移地址

如:
jmp 2AE3:3
jmp 3:0B18

2)仅修改ip的内容,类似于:mov ip,ax

jmp 某一合法寄存器

如:
jmp ax
jmp bx

操作实验

1)准备两段代码

1000:0

mov ax,123
jmp ax

1000:123

mov bx,456
add ax,bx

2)利用a命令将两段代码写入

image-20220107100238780

3)改变cs:ip的值,设置代码执行的初始位置

image-20220107100406101

4)开始执行,观察跳转数据变化

image-20220107100516099

5)执行过程与代码内容相符,在发生跳转时,ip数据从0003变为了0123,ip值改变,下一条命令读取地址被改变

内存中字的存储

字概述

字是CPU一次所能处理的数据大小,32位CPU一次所能处理的数据为32位,因此其字大小为32位。同理,8086CPU是16位CPU,因此字大小为16位

16位的字如何在寄存器中存储

数据存储方式:高八位放在高字节,低八位放在低字节

观察mov ax,1234指令的存储方式

1)用a指令存储数值

2)用d指令读取指定内存地址的数据

3)观察1234在内存中的存储

image-20220107103741736

5)现象与原理相符

额外小知识:(存储模式)

小端存储:低位数据放在低位字节,高位数据放在高位字节(符合理论现象)

大端存储:低位数据放在高位字节,高位数据放在低位字节

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

要求

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

原理

在8086CPU中,内存地址由段地址和偏移地址组成(段地址:偏移地址)

解决方案

DS和[address]配合

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

需要注意的点

1)立即数(如1000H、1234H等数值被称作立即数) 可以直接赋值给通用寄存器,而不能直接赋值给ds寄存器,因此需要两次mov来对ds初始化

2)如果"[ ]"中没有明确段地址大小,那么默认使用ds中的数据当做段地址,因此[0]等同于[ds:0]

操作观察

1)设置1000:0位置的数据依次为11,22,33

2)利用下述命令操作观察

mov ax,1000
mov ds,ax
mov ax,[0]
mov bx,[2]
mov cx,[1]
add bx,[2]
add cx,[2]

image-20220107113108769

值的变化过程

image-20220107113651942

image-20220107113830744

栈操作的实现

栈结构

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

2)栈的基本操作

     入栈:将一个新的元素放置栈顶

     出栈:从栈顶取出一个元素

3)栈顶的元素总是最后入展,需要出栈时,有最先被去除

栈指令(针对字进行操作,不是字节操作)

push:入栈

     栈顶指针向低地址偏移,数据存入栈顶指针指向位置

pop: 出栈

     读取数据,栈顶指针向高位地址偏移

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

1)栈段寄存器(SS):存放栈顶的段地址

2)栈顶指针寄存器(SP):存放栈顶的偏移地址

汇编代码

mov ax,1000H
mov ss,ax
mov sp,0010H

mov ax,001AH
mov bx,001BH

push ax
push bx

pop ax
pop bx
posted @ 2022-01-16 13:08  v1v1v1  阅读(858)  评论(0)    收藏  举报