Intel8086处理器-段寄存器ES/DS/CS/SS与寻址

2024-06-13 12:48

本文主要是介绍Intel8086处理器-段寄存器ES/DS/CS/SS与寻址,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

注意:本文代码在微软visual studio 2019下完成

一:段的概念
比方说有这样一段汇编程序

.data
abc DWORD 666
.code
call abcdef

可以肤浅的理解为abc DWORD 666这句代码存在的内存区域,叫做数据段,call abcdef这句代码存在的内存区域,叫做代码段,调用call指令的时候,还需要堆栈,而堆栈占用的那片内存区域,叫做堆栈段,那么大致的内存图如下,从图中可以看出,每个程序都有自己的段,而且代码段,堆栈段,数据段之间有可能连续,也有可能不连续
在这里插入图片描述

二:基址(段的起始位置)与段长度
段的起始位置也叫基址,与长度一样,是段的属性之一,从上图中可以看到
程序1的数据段,基址是10004,程序1的数据段长度是2
程序2的堆栈段,基址是10014,程序2的堆栈段长度是3

注意,上述只是举例子,实际情况是段起始地址必须是以0x00结尾的地址

三:地址总线的寻址能力
CPU如果要想获取某个内存处的地址,比如上图中,CPU想获取10003处的值,则CPU会将10003放到地址总线中,这样内存中的33这个数据,就会通过数据总线传递给CPU,这有个前提,就是地址总线中必须能放得下10003这个数才行,比方说,地址总线只有两条,每条线肯定只有高电平(1)或者低电平(0)两种选择,那么这个地址总线的表达能力最多是3,只能获取内存中0-3之间的数据,而8086CPU有20条地址总线,它的表达能力是220,内存中0-220之间位置都能获取到,也就是1MB,这种能力,叫做地址总线的寻址能力,8086的地址总线寻址能力是1MB

四:CPU的寻址能力,段地址,偏移地址
8086CPU是16位CPU,定义为一次处理,传输,暂存的数据最大值是216,也就是64KB,如果这样,那么8086的CPU寻址能力将是64KB

CPU的寻址能力导致的问题
从上文可以看出,CPU的寻址能力可以说是远远不如地址总线的寻址能力,这就好比地址总线是一个很宽的高速公路,而CPU却是一台特别慢的汽车,根本配不上这条高速公路,假如现在要获取内存位置65KB处的数据,CPU根本无法表达65KB这个信息给地址总线,这就很尴尬,因为这个原因,CPU使用地址加法器,让自己的输出从16位变成了20为,从而使CPU的寻址达到最大化,地址加法器的做法是取1个16位寄存器,将每个bit值,依次放到16跟地址总线中,这个寄存器里的值,就叫做段地址
取另外一个16为寄存器中的四个数据,放到剩下的4跟地址总线中,这叫做偏移地址(理解偏移长度更好一些)
说白了就是用两个16位寄存器,来表达20位地址总线中的数据

五:地址加法器
假设段地址16进制是:2000H
假设偏移长度16进制是:1H
经过地址加法器合成之后,CPU实际查询的内存是:20001H,该结果可以用以下公式计算
真实地址=段地址乘以16+偏移长度
注意:段地址乘以16,就是上文的基址(段的起始位置)
所以也可以说真实地址=基址(段的起始位置)+偏移长度
在8086架构中

CS寄存器存储代码段的段地址,IP寄存器存放代码段的偏移长度
DS寄存器存储数据段的段地址,多数情况下用DX存放数据段的偏移长度
SS寄存器存储堆栈段的段地址,SP寄存器存放堆栈段的偏移长度

CPU运行过程如下图
在这里插入图片描述

在8086中,设CS中的内容为M,IP中的内容为N,则CPU从M*16+N单元开始读取一条指令并执行,任意时刻,CPU都将CS:IP指向的内容当做指令执行
CS+IP通过地址加法器,合成一个内存地址,这个内存地址中的内容,就是CPU要执行的指令

注:8086中加电启动或复位后,CS和IP被设置成CS=FFFF,IP=0000,所以8086电脑开机之后执行的第一条指令是:FFFF0H存储单元的指令

四个段寄存器:CS/DS/SS/ES

语法:

mov 段寄存器,通用寄存器
mov 段寄存器,[address]

下面的写法是错误的

mov 段寄存器,666

CS代码段寄存器
CS寄存器总是和IP寄存器配合使用的,在CS与IP中已经提到过,mov指令叫做传送指令,传送指令不可以修改cs寄存器,因为CPU就不提供这种功能,需要使用转移指令进行修改,一个典型转移指令就是jmp指令
jmp 段地址:偏移地址

//执行这条指令之后,CS=2AE3,IP=0003,接下来CPU将执行2AE33存储单元内的指令
jmp 2AE3:3

jmp 某一寄存器

// 将ax中的值放到ip寄存器中
jmp ax

日记:使用CALL指令将EIP内容读取到栈,这样我们就能获取到EIP中的内容了,然后使用RET/IRET指令修改栈,这样就实现了函数注入

七:DS数据段寄存器
汇编代码有时候会遇见中括号的写法,这种写法叫做[address],这种方式是以字为单位进行操作的,千万要注意,"以字为单位"这句话,并且address只能是一个常量,或者一些指定的寄存器,它们分别是bx,bp,si,di,例如下面的汇编代码是正确的

mov ax,[666];使用ds作为段寄存器,默认就是ds
mov ax,[bx];使用ds作为段寄存器,因为中括号[]中有bx寄存器
mov ax,[bx+si];使用ds作为段寄存器,因为中括号[]中有bx寄存器
mov ax,[bx+di];使用ds作为段寄存器,因为中括号[]中有bx寄存器
mov ax,[bp];使用ss作为段寄存器,因为中括号[]中有bp寄存器
mov ax,[bp+si];使用ss作为段寄存器,因为中括号[]中有bp寄存器
mov ax,[bp+di];使用ss作为段寄存器,因为中括号[]中有bp寄存器

下面的汇编代码是错误的

mov ax,[bx+bp];bx和bp不能同时出现在同一个中括号里
mov ax,[cx]
mov ax,[dx]
mov ax,[ds]

假设DS=2000H,并且内存如下图
在这里插入图片描述
则执行mov ax,[1]这条汇编指令的时候,根据CPU位数不同,其处理也是不同的

8位CPU:将一个内存地址20001处的值B8挪到ax中
16位CPU:将一个内存地址20001处的值B8,20002处的值23,合并成一个16位数23B8H,然后将23B8H挪到ax中
32位CPU:将一个内存地址20001处的值B8,20002处的值23,20003处的01,20004出的B8,合并成一个32位数B80123B8H,挪到ax中

如何修改DS寄存器中的值?
由于CPU硬件设计问题,DS寄存器只能接收其他寄存器的值,而不接受立即数,例如下面的汇编语言是错误的

mov ds,1111H

要想让ds的值为1111H,则必须同一个一个寄存器进行中转,下面的汇编语言是正确的

mov ax,1111H
mov ds,ax

别问为什么,8086CPU就是这么设计的,我也不知道为什么

八:ES数据段附加段寄存器
与DS功能相同,也叫附加段寄存器,是为了弥补在某些情况下数据段寄存器不够使用的情况,如果因为数据段寄存器默认就是DS,所以要想使用ES,则需要如下写法,下面的写法也叫做段超越前缀

mov ax,0xb800
mov ds,ax
mov [ds:0x10],666		;将数字666存放到物理地址0xB8010

九:SS栈段寄存器和SP寄存器
确定栈空间,就是确定栈顶在哪个位置,任意时刻,SS和SP都指向栈顶,段寄存器SS用于存放段地址,寄存器SP用于存放偏移地址,执行push和pop指令的时候,CPU根据SS:SP获取栈顶位置
当执行下面push指令时候
push ax
SP首先-2(8086CPU),将栈顶往上挪动2个存储单元,然后将ax中的内容放到栈内
相对的,pop指令的时候,sp首先会自动+2
注意:执行修改SS指令的时候,比如mov ss,xxx,此时CPU强制屏蔽中断,直到下一条指令执行完毕,所以,mov ss,xxx之后,下面的指令我们必须要修改sp才行

这篇关于Intel8086处理器-段寄存器ES/DS/CS/SS与寻址的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1057353

相关文章

2. c#从不同cs的文件调用函数

1.文件目录如下: 2. Program.cs文件的主函数如下 using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace datasAnalysis{internal static

ElasticSearch的DSL查询⑤(ES数据聚合、DSL语法数据聚合、RestClient数据聚合)

目录 一、数据聚合 1.1 DSL实现聚合 1.1.1 Bucket聚合  1.1.2 带条件聚合 1.1.3 Metric聚合 1.1.4 总结 2.1 RestClient实现聚合 2.1.1 Bucket聚合 2.1.2 带条件聚合 2.2.3 Metric聚合 一、数据聚合 聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:

OpenGL ES学习总结:基础知识简介

什么是OpenGL ES? OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库。 为桌面版本OpenGL 的一个子集。 OpenGL ES管道(Pipeline) OpenGL ES 1.x 的工序是固定的,称为Fix-Function Pipeline,可以想象一个带有很多控制开关的机器,尽管加工

OpenGL ES 2.0渲染管线

http://codingnow.cn/opengles/1504.html Opengl es 2.0实现了可编程的图形管线,比起1.x的固定管线要复杂和灵活很多,由两部分规范组成:Opengl es 2.0 API规范和Opengl es着色语言规范。下图是Opengl es 2.0渲染管线,阴影部分是opengl es 2.0的可编程阶段。   1. 顶点着色器(Vert

Spring点滴五:Spring中的后置处理器BeanPostProcessor讲解

https://www.cnblogs.com/sishang/p/6576665.html BeanPostProcessor接口作用:      如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。   package com.t

寄存器B

MCS-51单片机的中央处理器包含运算部件和控制部件两部分。         1. 运算部件         运算部件以算术逻辑运算单元ALU为核心,包含累加器ACC、B寄存器、暂存器、标志寄存器PSW等许多部件,它能实现算术运算、逻辑运算、位运算、数据传输等处理。         算术逻辑运算单元ALU是一个8位的运算器,它不仅可以完成8位二进制数据加、减、乘、除等基本的算

【SpringMVC学习05】SpringMVC中的异常处理器

SpringMVC在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。 异常处理思路 我们知道,系统中异常包括两类:预期异常和运行时异常(RuntimeException),前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。系统的dao、service、controller出现异常都通过throws E

Elastic Stack--ES集群加密及Kibana的RBAC实战

前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除 学习B站博主教程笔记:  最新版适合自学的ElasticStack全套视频(Elk零基础入门到精通教程)Linux运维必备—ElasticSearch+Logstash+Kibana精讲_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1VMW3e6Ezk/?sp

Makefile问答之02 预处理器与宏

GCC Makefile中,怎样设定预处理器名称 在 GCC 的 Makefile 中,预处理器(preprocessor)的名称通常是 cpp(C PreProcessor),但在实际的 Makefile 中,我们一般是通过 gcc 命令来调用预处理器,而不是直接调用 cpp。不过,你可以通过设置 CPP 变量来显式指定预处理器名称和选项。以下是如何在 Makefile 中进行设置和使用的

期货赫兹量化-种群优化算法:进化策略,(μ,λ)-ES 和 (μ+λ)-ES

进化策略(Evolution Strategies, ES)是一种启发式算法,旨在模仿自然选择的过程来解决复杂的优化问题,尤其在没有显式解、或搜索空间巨大的情况下表现良好。基于自然界的进化原理,进化策略通过突变、选择等遗传算子迭代生成解,并最终寻求全局最优解。 进化策略通常基于两个核心机制:突变和选择。突变是对当前解进行随机扰动,而选择则用于保留适应度更高的个体。本文详细介绍了 (μ,λ)-ES