百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

【新书推荐】6.3节 指令指针寄存器

liebian365 2024-10-18 09:34 8 浏览 0 评论

8086 CPU内部的指令指针寄存器IP是计算机自动运行程序的关键。指令指针寄存器IP自动指向下一条将要执行的指令。

本节内容:使用指令指针寄存器读取和执行指令的工作原理和段寄存器的引用。

指令指针: 8086CPU中的指令指针寄存器IP是16位寄存器。指令指针寄存器IP指向将要执行的指令在代码段中的偏移。只有使用控制指令才可以改变CS:IP的值,如JMP指令、JCC指令、CALL指令、RET指令、IRET指令等。

读取、执行指令的工作原理:代码段内汇编指令的逻辑地址采用CS:IP表示,通过地址加法器将CS*16+IP转换为20位物理地址,然后在该物理内存地址处读取指令机器码。

段寄存器的引用:正常引用段寄存器时,使用段超越前缀,比如“DS:[SI]”中的DS表示数据段超越前缀,表示引用数据段DS中的SI偏移地址处存储的值。默认缺省段超越前缀存在两种情形。一是数据段寄存器DS缺省,偏移地址可以使用[BX]、[SI]、[DI]或其组合形式表示。二是堆栈段寄存器SS缺省,偏移地址只可以使用[BP]表示,[BP]等价于SS:[BP]。

6.3.1 指令指针

当我们的操作系统将计算机可执行程序加载到计算机的内存中之后,IP指令指针寄存器自动指向该程序的入口地址(第一条指令的位置)。然后,按照程序中指令执行的流程和先后顺序,自动执行。

指令编码规则

程序员在编写计算机的源程序时,按照计算机语言的指定编写规则编写源代码。编写程序时,通常按照数据和代码分开的原则编写。数据写在数据段,指令写在代码段。汇编源程序中编写的地址是逻辑地址。代码段的逻辑地址表示为CS:IP,由16位段值和16位偏移组成。当操作系统把编译后的可执行程序加载到计算机的内存中后,CPU读取的指令地址为源程序中编写的逻辑地址,CPU还需要将逻辑地址转换为物理地址后,才可以正确地读写物理内存中的指令或数据。

读取指令时,需要将指令的逻辑地址转换为物理地址:

8086物理地址=段值*16 +偏移。

代码段的逻辑地址: CS:IP。

代码段的物理地址 = CS*16 + IP。

下一条指令的地址=当前指令地址+当前指令机器码的字节数。

动手实验10:测试指令地址

如图6-12所示,在Debug调试器中输入命令a,输入下面三条语句,接着输入u命令,注意观察CS:IP的变化。

mov ax,1的硬编码为B80100,地址为073f:0100;

mov bx,2的硬编码为B80200,地址为073f:0103;

mov cx,3的硬编码为B90300,地址为073f:0106;

上述3条指令的硬编码都是3个字节,下一条指令的地址等于当前指令地址+3。

指令指针

8086 CPU中的指令指针寄存器IP是16位寄存器。指令指针寄存器IP指向将要执行的指令在代码段中的偏移。实际上,除非发生转移,否则将要执行的指令会被预取到指令预取队列,然后再将一条指令分解为多条微指令,并将微指令提交CPU执行。关于指令队列和指令执行的具体流程,我们将在第三部分32位汇编的第二十八章80386处理器体系结构一章中详细讲解。

CS和IP是8086 CPU两个最关键的寄存器。任意时刻CPU都将CS:IP指向的内容当作指令执行。

6.3.2 读取、执行指令的工作原理

读取执行指令

如图6-13所示:

●8086 CPU当前状态:CS中的内容为2000H,IP中的内容为0000H;

●内存20000H~20009H单元存放着可执行的机器码;

●内存20000H~20009H单元存放的机器码对应的汇编指令如下:

地址:20000H~20002H,内容:B8 21 03,长度:3byte,对应汇编指令:mov ax,0321h。

地址:20003H~20005H,内容:BB 06 00,长度:3byte,对应汇编指令:mov bx,0006h。

地址:20006H~20007H,内容:89 D8,长度:2byte,对应汇编指令:mov ax,bx。

地址:20008H~20009H,内容:01 DB,长度:2byte,对应汇编指令:add ax,bx。

假设当前CPU提取的代码段逻辑地址为2000H:0H,由CPU内的地址加法器将此逻辑地址转换为物理地址20000H。地址总线加载物理地址20000H,该物理地址存储汇编指令“mov ax,0321H”对应的机器语言(也称为硬编码)“B8 21 03”,这条机器语言就是将要执行的指令。

6.3.3 段寄存器的引用

在代码段的指令代码中,如何引用段寄存器呢?如图6-14所示,8086 CPU内有4个16位的段寄存器CS、DS、SS、ES,分别用于存储代码段、数据段、堆栈段和附加段的段值。这些段是由程序员在编写16位汇编源程序时人为定义的逻辑段。逻辑段的段值在源程序中并不是指定的,而是使用符号表示,称为该逻辑段的段地址标号。

堆栈段段值存储在SS段寄存器中,堆栈段使用SP栈顶指针寄存器指向堆栈段的栈顶,BP寄存器作为堆栈段内的基址寄存器。

代码段段值存储在CS段寄存器中,代码段使用IP指令指针寄存器指向将要执行的指令。

数据段段值存储在DS段寄存器中,数据段使用BX、SI、DI、BP四个指针寄存器指向段内偏移,或者使用直接段内地址偏移。在使用内存数据拷贝(字符串指令)时,固定使用DS:[SI]指向源地址。

附加段段值存储在ES段寄存器中,附加段通常用于数据拷贝,在字符串指令中固定使用ES:[DI]指向目的地址。

举例

假设在一个源程序中引用了4个逻辑段,需要在源程序的开始位置做如下声明:

assume cs:code,ds:data,ss:stack,es:edata

意思是假设“地址标号code”表示代码段,“地址标号data”表示数据段,“地址标号stack”表示堆栈段,“地址标号edata”表示附加段。

16位汇编语言源程序中段的定义如下:

assume cs:code,ds:data,ss:stack,es:edata

stack segment ;堆栈段定义的起始位置

定义堆栈空间的大小

stack ends ;堆栈段到此结束

data segment ;数据段定义的起始位置

数据段内的数据定义

data ends ;数据段到此结束

edata segment ;附加段定义的起始位置

附加段内的数据定义

data ends ;附加段到此结束

code segment ;代码段定义的起始位置

start: ;代码段内的地址标号

汇编指令代码…

code ends ;代码段到此结束

end start ;指定代码段的入口地址位于地址标号start处

在源程序中,根据实际需要定义一个或多个逻辑段,至少应包含一个代码段

下面分别介绍4个段寄存器的引用方法。

代码段

在汇编语言的源程序中,代码段内存储的是汇编指令代码。代码段的地址标号通常用“code”表示,也可以自定义。当我们编写16位汇编语言源程序时,并不需要真正给段寄存器赋值,只需要声明段地址标号就可以了。当操作系统将编译后的二进制可执行程序(.exe后缀的程序)加载到计算机内存中时,会根据当前计算机系统的配置,自动分配一个段值给段寄存器,替换源代码中的段地址标号。这样的好处是,不需要使用固定的段值,可以将同一个可执行程序加载到不同的计算机系统上运行。

当CPU通过CS:IP读取代码段内的指令时,会自动引用代码段寄存器CS,加上指令指针寄存器IP所给的16位代码段内偏移,得到指令的物理地址。

堆栈段

堆栈段是一个动态分配的内存空间。段寄存器SS存储堆栈段的段值。当涉及堆栈操作时,引用堆栈段SS段寄存器,加上SP栈顶指针寄存器给出的16位堆栈段内偏移,得到堆栈操作的物理地址。

注意

1.编写16位汇编程序时,我们可以自定义堆栈段(小于64KB),也可以使用DOS系统默认分配的64KB堆栈空间。

2.SP栈顶指针寄存器永远指向堆栈段的栈顶。

3.堆栈内的数据存储按照后进先出的原则进行。

4.8086计算机的堆栈空间每次固定分配2个字节空间,即按照16位对齐,不足16位,前面补0。

5.入栈操作时SP寄存器减2,出栈操作时,SP寄存器加2。例如:

push ax ;将ax寄存器的值压入堆栈栈顶,SP-2

pop ax ;将堆栈栈顶2个字节的值pop 到ax寄存器中,SP+2

6.BP寄存器是栈内基址指针寄存器,用于堆栈内的寻址。如果是BP寄存器计算偏移时,缺省引用段寄存器,默认为SS段。例如,汇编语句mov ax,[bp+2]是mov ax,ss:[bp+2]的简写形式。

我们将在第七章8086寻址方式第八章8086指令系统详细讲解堆栈内的寻址和堆栈操作指令。

附加段

ES段寄存器存储附加段的段值。通常附加段用于数据拷贝。在16位汇编语言中,使用字符串指令时,ES:[DI]指向目的地址,目的数据字符串只可以使用ES段寄存器。我们将在第十七章字符串处理的章节中学习字符串指令。

注意

字符串指令LODS、STOS、MOVS、SCANS、CMPS用于字符串的装载、存储、拷贝、扫描和比对。在16位汇编语言中,字符串是以ASCII码字符的形式存储在计算机内存中。对内存中字符串的操作,就是对ASCII数值的操作。因而字符串指令本质上就是内存数据拷贝。所以,我们说ES段寄存器“用于数据拷贝”和“用于字符串指令”的说法是一回事。

数据段

数据段的段值存储于DS段寄存器,用于存储程序所需的数据定义。16位汇编语言程序中,通常我们定义为data segment数据段。数据段作为全局段存在的,整个程序中的任一指令都可以直接引用。

源程序中的引用方法为DS:[SI],缺省DS段寄存器时,默认为DS段。如果一个程序不超过64KB,只需要在程序开始时分别给DS,SS赋值就可以了,程序的其他地方不需要再考虑这些段寄存器,如果程序超过64KB,就需要在两个或者多个段寄存器中存取数据,需要改变段寄存器的值。

段超越前缀:直接明确指定引用的段寄存器,可缺省。如DS:[SI]中,我们将“DS:”称为数据段超越前缀。

数据段和附加段的段内地址偏移可以使用SI、DI、BP、BX寄存器间接方式给出,或者直接给出段内偏移地址的数值,称为直接寻址方式。我们将在第七章8086寻址方式中详细讲解。

段寄存器的引用规则

表6-8给出了16位汇编语言中段引用的规则。可以分为三种情形:

正常使用段超越前缀

代码段必须使用CS段寄存器存储段值,源程序中使用CS:IP表示代码段内逻辑地址。

堆栈段必须使用SS段寄存器存储段值,源程序中使用SS:[BP] 或SS:[BP+立即数]表示堆栈段内逻辑地址。8086CPU指令集不支持SS:[SP]这样的指令。SP栈顶指针寄存器永远指向堆栈的栈顶。

附加段必须使用ES段寄存器存储段值,在字符串指令中,只能使用ES:[DI]表示附加段内的目的地址。

数据段使用DS段寄存器存储段值。在字符串指令中,只能使用DS:[SI]表示数据段内的目的地址。

缺省段超越前缀只有两种情形

1.数据段寄存器DS缺省,偏移地址可以使用[BX]、[SI]、[DI]或其组合形式表示。

2.是堆栈段寄存器SS缺省,偏移地址只可以使用[BP]表示,[BP]等价于SS:[BP]。

段值相同

DS数据段和SS堆栈段可以与CS、ES的段值相同,即都属于同一个段。

练习

1、请举例说明何为段前缀超越。什么场合下要使用段前缀超越?

2、什么情况下,缺省的段寄存器是SS?为什么要这样安排?

3、如何实现数据段与代码段相同?

4、堆栈有哪些用途,请举例说明?

本文摘自编程达人系列教材《X86汇编语言基础教程》。

相关推荐

快递查询教程,批量查询物流,一键管理快递

作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...

一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递

对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...

快递查询单号查询,怎么查物流到哪了

输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...

3分钟查询物流,教你一键批量查询全部物流信息

很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...

快递单号查询,一次性查询全部物流信息

现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...

快递查询工具,批量查询多个快递快递单号的物流状态、签收时间

最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...

快递查询软件,自动识别查询快递单号查询方法

当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...

教你怎样查询快递查询单号并保存物流信息

商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...

简单几步骤查询所有快递物流信息

在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...

物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号

最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...

连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息

快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...

快递查询教程,快递单号查询,筛选更新量为1的单号

最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...

掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析

在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...

从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息

在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...

物流单号查询,在哪里查询快递

如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...

取消回复欢迎 发表评论: