本文章内容将展开对寄存器和内存的深入理解,通过debug更好的理解计算机的内部以及汇编语言。还会深入讲汇编语言的一些指令以及代码段,数据段,栈段的相关内容。
运算器进行信息处理;
寄存器进行信息存储;
控制器协调各种器件进行工作;
内部总线实现CPU内各个器件之间的联系。
寄存器是CPU内部的信息存储单元
8086CPU 有14个寄存器:
通用寄存器:AX、BX、CX、DX
变址寄存器:SI、DI
指针寄存器:SP、BP
指令指针寄存器: IP
段寄存器:CS、SS、DS、ES
标志寄存器:PSW
共性:8086CPU所有的寄存器都是16位的,可以存放两个字节。
以AX为例:
一个16位寄存器存储一个16位的数据
问题一:最大值?
答案:2^16-1
在AX中存储18D
18D
12H
10010B
在AX中存储20000D
4E20H
0100111000100000B
问题二:8086上一代CPU中的寄存器都是8位的,如何保证程序的兼容性?
答案:通用寄存器均可以分为两个独立的8位寄存器使用
AX可以分为AH和AL
BX可以分为BH和BL
CX可以分为CH和CL
DX可以分为DH和DL
8086是16位CPU
8086的字长为16bit
一个字(word)可以存在一个16位寄存器中
这个字的高位字节存在这个寄存器的高8位寄存器
这个字的低位字节存在这个寄存器的低8位寄存器
汇编指令 | 控制CPU完成的操作 | 用高级语言描述 |
mov ax,78 | 将78送入AX | AX=78 |
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 |
注:汇编指令不区分大小写
例1:
程序段中的指令 | 指令执行后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中的值均为0000H
例2:
程序段中的指令 | 指令执行后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 |
设原AX、BX中的值均为0000H
CPU访问内存单元时要给出内存单元的地址。
所有的内存单元构成的存储空间是一个一维的线性空间。
每一个内存单元在这个空间中都有唯一的地址,这个唯一的地址称为物理地址。
8086有20位地址总线,可传送20位地址,寻址能力为1M。
8086是16位结构的CPU
运算器一次最多可以处理16位的数据,寄存器的最大宽度为16位。
在8086内部处理的、传输、暂存的地址也是16位,寻址能力也只有64KB!
问题:8086如何处理在寻址空间上的这个矛盾?!
解决方法:用两个16位地址(段地址、偏移地址)合成一个20位的物理地址。
地址加法器合成物理地址的方法:
物理地址=段地址×16+偏移地址
例:物理地址=段地址×16+偏移地址
段地址:1230
+偏移地址:00C8
物理地址:123C8
思考:物理地址为123C8,段地址是123CH可否?
答案是可以的此时的偏移地址为0008。
如果段地址是123B,此时偏移地址为0018。
“段地址×16+偏移地址=物理地址”的本质含义:
要解决的问题:用两个16位的地址(段地址、偏移地址),相加得到一个20位的物理地址。
本质含义:CPU在访问内存时,用一个基础地址(段 地址×16)和一个相对于基础地址的偏移 地址相加,给出内存单元的物理地址。
8086CPU用“(段地址×16)+偏移地址=物理地址”的方式给出内存单元的物理地址。
内存并没有分段,段的划分来自于CPU!!!
1)段地址*16必然是16的倍数,所以一个段的起始地址也一定是16的倍数;
2)偏移地址为16位,16位地址的寻址能力为64K,所以一个段的长度最大为64K;
偏移地址16位,变化范围为0~FFFFH,用偏移地址最多寻址64KB。
例:给定段地址2000H,用偏移地址寻址的范围是:20000H~2FFFFH,共64K。
物理地址 | 段地址 | 偏移地址 |
21F60H | 2000H | 1F60H |
2100H | 0F60H | |
21F0H | 0060H | |
21F6H | 0000H | |
1F00H | 2F60H |
在8086PC机中存储单元地址的表示方法:
数据在21F60H单元中,段地址是2000H,说法:
1)数据存在内存2000:1F60单元中;
2)数据存在内存2000H段中的1F60单元中;
段地址很重要!—用专门的寄存器存放段地址。
4个段寄存器:
CS:代码段寄存器
DS:数据段寄存器
SS:栈段寄存器
ES:附加段寄存器
偏移地址可以用多种方法提供——8086丰富的取址方式。我们之后会讲到。
debug 是什么?
debug是DOS系统中著名的调试程序,也可以在windows系统实模式下。
使用debug程序,可以查看CPU 各种寄存器中的内容,内存的情况,并且在机器指令级跟踪程序的运行!
debug能做什么?
用R命令查看、改变CPU寄存器的内容
用D命令查看内存中的内容
用E命令改变内存中的内容
用U命令将内存中的机器指令翻译成汇编指令
用A命令以汇编指令的格式在内存中写入机器指令
用T命令执行机器指令
启动debug:在DOS提示符下输入命令:debug
用R命令查看、改变CPU寄存器的内容
R-查看寄存器的内容
R 寄存器名-改变指定寄存器的内容
用D命令查看内存中的内容
D-列出地址内存处的128个字节内容。
D 段地址:偏移地址-列出指定地址处的内容。
D 段地址:偏移地址 结尾偏移地址-列出内存中指定地址范围的内容。
用E命令改变内存中的内容
E 段地址:偏移地址 数据1 数据2……
E 段地址:偏移地址
-逐个询问方式
-空格-接收,继续
-回车-结束
用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 地址 - 查看代码
用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 地址 - 查看代码
用T命令执行机器指令
t - 执行CS:IP处的指令
mov ax, 0123H
mov bx, 0003H
mov ax, bx
add ax, bx
q - 退出Debug
到这里大家赶紧练习一下使用debug吧!
两个关键寄存器:
CS:代码段寄存器
IP:指令指针寄存器
CS:IP -CPU将内存中CS:IP指向的内容当作指令执行。
8086工作过程简要描述:
1)从CS:IP指向内存单元读取指令,读取的指令进入指令缓存器;
2)IP=IP+所读指令的长度,从而指向下一条指令;
3)执行指令。跳转步骤
(1),重复这个过程。
问:内存中有数据 B8 23 01 BB 03 00 89 D8 01 D8,究竟用作一般数据,还是用作指令?
答:CPU将CS:IP指向的内存单元中的内容看作指令!
用debug程序执行下面的代码:
mov ax, 0123H
mov bx, 0003H
mov ax, bx
add ax, bx
a 地址 - 写入汇编指令
u 地址 - 查看代码
t - 执行CS:IP处代码
事实:执行何处的指令,取决于CS:IP
应用:可以通过改变CS、IP中的内容,来控制CPU要执行的目标指令
问题:如何改变CS、IP 的值?
方法1:Debug中的R命令可以改变寄存器的值—r cs,r ip
.Debug是调试手段,并非程序方式
方法2:用指令修改
mov cs,2000H(error)
mov ip,0000H(error)8086CPU不提供对CS和IP修改的指令
方法3:转移指令jmp
jmp 段地址:偏移地址
jmp 2AE3:3
jmp 3:0B16
功能:用指令中给出的段地址修改CS,偏移地址修改IP
jmp ax (类似于mov ip ax)
jmp bx
功能:用寄存器中的值修改IP
从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)步执行
可以通过分析完成上面各个寄存器的变化,在通过debug进行进一步检验。
事实:对8086CPU,16位作为一个字
问题:16位的字存储在一个16位的寄存器中,如何存储?
答案:高8位放在高字节,低8位放在低字节。
问题:16位的字在内存中需要2个连续字节存储,怎么存放?
答案:低位字节存在低地址单元,高位字节存在高地址单元。
例:20000D(4E20H)存放0,1两个单元,18D(0012H)存放在2,3两个单元
字单元:由两个地址连续的内存单元组成,存放一个字型数据(16位)
原理:在一个字单元中,低地址单元存放低位字节,高地址单元存放高位字节
在起始地址为0的单元中,存放的是4E20H
在起始地址为2的单元中,存放的是0012H
问题:
(1)0地址单元中存放的字节型数据是( 20H )
(2)0地址字单元中存放的字型数据是( 4E20H )
(3)2地址单元中存放的字节型数据是( 12H )
(4)2地址字单元中存放的字型数据是( 0012H )
要求:
CPU 要读取一个内存单元的时候,必须先给出这个内存单元的地址;
原理:
在8086 PC机中,内存地址由段地址和偏移地址组成(段地址:偏移地址)
解决方案:DS和[address]配合
DS寄存器存放要访问的数据的段地址
偏移地址用[…]形式直接给出
例1
mov bx,1000H
mov ds,bx
mov al, [0]
将10000H(1000:0)中的数据读到al中
例2
mov bx,1000H
mov ds,bx
mov [0],al
将al中的数据写到10000H(1000:0)中
8086CPU 可以一次性传送一个字(16位的数据)
例:
mov bx, 1000H
mov ds, bx
mov ax, [0] ;1000:0处的字型数据送入ax
mov [0], cx ;cx中的16位数据送到1000:0处
案例:
对于8086PC机,可以根据需要将一组内存单元定义为一个段。
物理地址=段地址×16+偏移地址
将一组长度为N(N≤64K)、地址连续、起始地址为16的倍数的内存单元当作专门存储数
据的内存空间,从而定义了一个数据段。
例:用123B0H~123B9H的空间来存放数据
段地址:123BH 起始偏移地址:0000H 长度:10字节
段地址:1230H 起始偏移地址:00B0H 长度:10字节
将哪段内存当作数据段,段地址如何定,在编程时安排。
处理方法:(DS):([address])
用DS存放数据段的段地址
用相关指令(mov、add、sub…)访问数据段中的具体单元,单元地址由[address]指出。
将123B0H~123BAH的内存单元定义为数据段
累加数据段中的前3个单元中的数据
mov ax, 123BH
mov ds, ax
mov al, 0
add al, [0]
add al, [1]
add al, [2]
累加数据段中的前3个字型数据
mov ax, 123BH
mov ds, ax
mov ax, 0
add ax, [0]
add ax, [2]
add ax, [4]
练习:给出00000H-0001F的数据,请写出下面代码的执行结果
完成:
(1)字在内存中存储时 ,要用两个地址连续的内存单元来存放,字的
低位字节存放在低地址单元中,高位字节存放再高地址单元中。
(2)用 mov 指令要访问内存单元,可以在mov指令中只给出单元的偏
移地址,此时,段地址默认在DS寄存器中。
(3)[address]表示一个偏移地址为address的内存单元。
(4)在内存和寄存器之间传送字型数据时,高地址单元和高8位寄存器、
低地址单元和低8位寄存器相对应。
(5)mov、add、sub是具有两个操作对象的指令,访问内存中的数据段
(对照:jmp是具有一个操作对象的指令,对应内存中的代码段)。
(6)可以根据自己的推测,在Debug中实验指令的新格式。
栈是一种只能在一端进行插入或删除操作的数据结构。
栈有两个基本的操作:入栈和出栈。
入栈:将一个新的元素放到栈顶;
出栈:从栈顶取出一个元素。
栈顶的元素总是最后入栈,需要出栈时,又最先被从栈中取出。
栈的操作规则:LIFO(Last In First Out,后进先出)
CPU提供的栈机制 现今的CPU中都有栈的设计。
8086CPU提供相关的指令,支持用栈的方式访问内存空间。
基于8086CPU的编程,可以将一段内存当作栈来使用。PUSH(入栈)和 POP(出栈)指令
push ax:将ax中的数据送入栈中
pop ax:从栈顶取出数据送入ax
(以字为单位对栈进行操作)
问题:
1、CPU如何知道一段内存空间被当作栈使用? 2、执行push和pop的时候,如何知道哪个单元是栈顶单元?回答:8086CPU中,有两个与栈相关的寄存器:
栈段寄存器SS - 存放栈顶的段地址
栈顶指针寄存器SP - 存放栈顶的偏移地址
——任意时刻,SS:SP指向栈顶元素
mov ax, 1000H
mov ss, ax
mov sp, 0010H
mov ax, 001AH
mov bx, 001BH
push ax
push bx
pop ax
pop bx
mov ax, 1000H
mov ss, ax
mov sp, 0010H
mov ax, 001AH
mov bx, 001BH
push ax
push bx
pop ax
pop bx
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指令出栈,将发生栈顶超界问题。
栈顶超界是危险的。
8086CPU不保证对栈的操作不会超界。
8086CPU 只知道栈顶在何处(由SS:SP指示),不知道程序安排的栈空间有多大。
我们在编程的时候要自己操心栈顶超界的问题 ,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致的超界;防止出栈时栈空了仍然继续出栈而导致的超界。
基础:物理地址=段地址*16+偏移地址
做法:
-编程时,可以根据需要将一组内存单元定义为一个段。
-可以将起始地址为16的倍数,长度为N(N<=64K)的一组地址连续的内存单元,定义为一个段。
-将一段内存定义为一个段,用一个段地址指示段,用偏移地址访问段内的单元—由程序员安排。
三种段:
数据段:
将段地址放在DS中
用mov ,add ,sub ,等访问内存单元的指令时,CPU将我们定义的数据段中的内容当做数据段来访问
代码段:
将段地址放在CS中,将段中第一条指令的偏移地址放在IP中
CPU将执行我们定义的代码段中的指令
栈段:
将段地址放在SS中,将栈顶单元的偏移地置放在 SP 中
CPU在需要进行栈操作(push、pop)时,就
将我们定义的栈段当作栈空间来用
可以根据要求执行代码。
段地址可以是一样的
到这里这篇文章的内容就结束了,谢谢大家的观看,如果有好的建议可以留言喔,谢谢大家啦!
文章浏览阅读3.5k次。redis6.2 使用 TLS 的部署"三种高可用模式"安装redis6.2 并启用TLS加密安装创建TLS证书编写配置文件systemd管理测试连接redis 主从 配置 tls安装拷贝master 证书 到 slave编写配置文件systemd管理验证主从服务sentinel 哨兵服务创建目录、配置文件systemd管理查看sentinel 状态redis cluster 分片集群TLS安装规划目录及证书编写配置文件创建cluster 集群验证cluster 集群安装redis6.2 并启用TLS加密_redis 6.2版本启用tls认证
文章浏览阅读378次。在上一篇博客中下载了Sentinel-2数据,他有13个波段的.jp2文件,下面选取需要使用的波段进行合成。导入了B2(蓝色)、B3(绿色)、B4(红色)、B8(近红外),直接存为TIFF会丢失坐标信息。最后将合成好的影像存为TIFF。得到下面这些.dat格式。_sentinel2 数据波段合成
文章浏览阅读516次,点赞7次,收藏10次。多模态脑影像融合旨在将来自不同成像方式的脑影像数据进行融合,以获得更全面的信息。然而,由于不同成像方式的图像特性差异较大,直接融合会导致误差纹理和显著特征丢失等问题。本文提出了一种基于误差纹理消除和显著特征检测的多模态脑影像融合方法。该方法首先通过误差纹理消除算法去除融合图像中的误差纹理,然后通过显著特征检测算法提取融合图像中的显著特征,最后将显著特征融合到误差纹理消除后的图像中,得到最终的融合图像。实验结果表明,该方法可以有效消除误差纹理,保留显著特征,获得高质量的融合图像。引言。
文章浏览阅读1k次。我无法将颜色条添加到我的三维散点图中,它的颜色范围是根据bifurWidth的值在min和{}之间。我尝试过stackoverflow上显示的各种尝试,但都没有成功。任何帮助都将是非常感谢,因为我在这方面是一个重大的损失。在我最近的一次尝试是从下面的代码中散列出来的。在我的代码:from glob import globfrom pylab import *import numpy as npfr..._bar3d 好看的颜色
文章浏览阅读1.7k次。文章目录*交集选择器作用格式注意点并集选择器作用格式注意点相邻兄弟选择器作用格式注意点通用兄弟选择器作用格式注意点*交集选择器作用给所有选择器选中的标签中,相交的那部分设置属性。格式选择器1 选择器2{ 属性:值;}注意点1.选择器和选择器之间没有任何连接符号;2.选择器可以使用标签名称/id名称/class名称;3.仅了解。并集选择器作用给所有选择器选中的标签设置属性。格式选择器1,选择器2{属性:值;}注意点1.并集选择器必须使用,来连接;2.选择器可以使用_交集选择器和并集选择器使用方式
文章浏览阅读79次。打开cmd快捷键 window键+RCMD命令锦集 1. gpedit.msc-----组策略 2. sndrec32-------录音机 3. Nslookup-------IP地址侦测器 ,是一个 监测网络中 DNS 服务器是否能正确实现域名解析的命令行工具。 它在 Windows NT/2000/XP 中均可使用 , 但在 Wi...
文章浏览阅读534次。摘要:笔者根据计算机图形图像处理课程与中职学生学习的特点,分析了目前中职学校计算图形图像处理课程教学中存在的问题,针对如何提高中职学生对计算机图形图像处理课程的学习兴趣和解决实际问题的能力,提出了案例教学法在该课程中的具体实施办法,并对其实践进行了进一步的讨论。关键词:计算机图形图像处理;案例教学;中职当今世界电子商务发展迅速,计算机平面设计这门技术在很多领域都得到广泛应用。《Photoshop图..._图像分类在教育中的应用
文章浏览阅读921次。在网上看了很多博客,终于找到了符合自己智商可理解的打包资源文件方法,现引用如下https://www.cnblogs.com/darcymei/p/9397173.htmlhttps://blog.csdn.net/sinat_27382047/article/details/81304065"""终于把资源文件加载进去了,就是当exe文件移植后,它运行的时候会产生一个临时文件夹,把资源文件存储到..._pyinstaller如何将_internal添加进exe
文章浏览阅读3.3k次,点赞4次,收藏7次。Valn 11组网需求• 交换机GE_2上的VLAN 5 和VLAN 10 为Primary VLAN,其上层端口GigabitEthernet1/0/1需要允许VLAN 5 和VLAN 10 的报文携带VLAN Tag 通过。• 交换机GE_2 的下行端口GigabitEthernet1/0/2 允许Secondary VLAN 2 通过,GigabitEthernet1/0/3 允许Sec..._新华3模拟器vlan配置
文章浏览阅读4.7w次,点赞8次,收藏15次。我有一个模板,想按常规做一个div里面放置一个img图片,并且让图片铺满容器,自适应容器大小。HTML结构代码如下(在这个盒模型上,我已经放置了一些不重要的样式)。div style="height:270px;width:400px;border:2px black solid;"> a href="http://www.paipk.com">img src="..." alt="拍_img 铺满
文章浏览阅读947次。UnicodeDecodeError: 'gbk' codec can't decode byte 0xfa in position 4669: illegal multibyte sequenceUnicodeDecodeError: 'utf-8' codec can't decode byte 0xb0 in position 5: invalid start bytewith open('进线汇总20201211.csv',encoding='utf8') as f: t = f._ebpf bcc unicodedecodeerror: 'utf-8' codec can't decode byte 0xb0 in positio
文章浏览阅读1.3k次。使用条件序列GAN改进NMT原文《Improving Neural Machine Translation with Conditional Sequence Generative Adversarial Nets》课程作业,因为要导出pdf所以粘贴到CSDN了,34章是笔者翻译的部分。当一篇post吧,求别喷,有问题请留言我一定改,一定改。摘要本文提出了一种将GANs应用于NMT领域的方..._improving neural machine translation with conditional sequence generative ad