汇编语言学习第六章-包含多个段的程序

2024-08-25 05:18

本文主要是介绍汇编语言学习第六章-包含多个段的程序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

                     本博文系列参考自<<汇编语言>>第三版,作者:王爽


在前面的介绍的程序中只有一个代码段。那么如果我们需要将代码,数据分别存储在不同的内存空间应该怎么办呢?我们知道我们不可能随便使用任何一段内存空间,因为我们这段内存地址空间可能存储着非常重要的内容。其实,这只是我们考虑的太多啦,一旦我们将程序载入内存后,操作系统为我们分配的用于程序运行的内存空间都是安全的,绝对不会与其他程序的内存空间相重叠的。

往往程序获取内存有两种方式:一种是在程序载入内存的时候操作系统已经分配好的内存空间,另外一种是我们在程序运行的时候需要申请额外的内存空间进行相关的存储。(这里第二种方式为动态分配我们暂时不讨论)

前面我们已经有过这样的经验,我们在程序中定义一个段,然后当程序载入内存的时候,操作系统会自动为我们分配一个内存段用于存储。我们从另一方面来说说这个问题,如果我们程序中不仅包括代码,还有数据,甚至还有后面学习到的栈空间。我们如果把这些数据都保存到一个段,那么显然在程序设计和使用上难免逻辑不够清晰,往往我们都是在程序中定义不同的段来进而在内存空间中分别存储代码,数据和栈。


6.1在代码段中使用数据

这里我们先考虑这样一个问题,我们需要计算如下八个数的和:

0123h、0456h、0789h、0abch、0defh、0fedh、0cbah、0987h

这里我们要解决这个问题需要将上面这八个数据依次存储到某个寄存器中,然后再用某个寄存件保存累加结果进行累积。但是这样显然不够smart,如果可以用循环就最好了。那么问题来了,既然要用循环我们就需要把这8个数据依次存储到内存中的一段连续区域中。那么如果找到一段连续的内存空间呢?我们可以在程序中定义一段这8个数据,然后当程序经过编译链接成可执行文件载入到内存后,这8个数据就存储在了连续的内存空间了,接下来我们就可以使用循环进行累积求和了。

程序代码如下:


程序主要解释,其中dw为定义字型数据 define word,这里一共定义了8个字型数据。一共16个字节。 bx用于循环的索引,每次循环内存向后移动两个字节,ax为用于存储累积结果,cx用于循环计数器,初始值为8,每循环一次cx=cx-1.程序很简单,相信大家都能理解。这里特别说明,我们定义了一个代码段code。 因为dw存储在代码段的最开始位置,所以第一个字型数据的内存偏移定义为0.所以其实际内存地址为cs:0   紧接着0456h在其后的两个字节为cs:2.

接下来我们将该程序保存为vpeot.asm同时编译链接为vpoet.exe(上图代码中mov ax,4c00h忘记加逗号了,囧),然后再用debug工具加载该程序,如下:



从上图中可以看到cs=14FB,可以知道程序是从CS:0000即14FB:0000开始执行的。我们用u命令打印程序指令,发现的确是从14FB:0000开始执行的。然而前面的的一部分并非程序真正的指令,我们可以大胆猜测前面的内容为存储我们定义的dw数据的指令,现在我们使用d命令查看14FB:0000的内存内容。


可以看出从内存14FB:0000开始的16个字节为我们定义的8个字型数据。

那么如果要查看实际的汇编指令需要从14FB:0010开始查看:

\

这些对了吧。程序被加载后,整个程序的前16个字节为我们定义的8个字型数据。后面的才为我们的汇编指令。

那么如果我们想执行我们的汇编指令,只需要将寄存器IP的值设为0010即可。‘

这里还有一个问题就产生了,如果我们不是使用debug工具来改变IP而是直接将程序载入内存中,程序的入口地址并非我们的汇编指令,怎么办呢?
我们可以为程序增加一个标号来标示程序的入口,比如:


这里,我们在第一句汇编指令前面加上了一个标号start同时在伪指令end后也加上了start 这里的start就标示了程序的入口,表明一旦程序载入内存后,CS:IP就会指向第一条指令mov bx,0  我们可以再次编译链接生成exe然后通过debug工具加载到内存中来证实这一点。


先看我们看到程序的入口已经指向了第一条指令,就不需要我们像之前那样更改IP的地址了。


6.2在代码段中使用栈

同样先看一个问题,有8个数据存储在内存的一段连续的空间中。

0123h、0456h、0789h、0abch、0defh、0fedh、0cbah、0987h

我们需要编程实现这8个数据的逆序存放。


这个问题的思路是,假设这8个数据存储在CS:0~CS:F这段内存空间中,我们可以利用栈存储空间的特点,将这8个字型数据依次压入栈的内存空间中,然后依次弹出到这CS:0~CS:F这段内存空间中,便可以显示数据的逆序存放。这种思路需要我们在程序中定义一段内存空间作为栈空间使用,实现代码如下:

assume cs:codecode segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0start:mov ax,csmov ss,axmov sp,30hmov bx,0mov cx,8s:push cs:[bx]add bx,2loop smov bx,0mov cx,8s0:pop cs:[bx]add bx,2loop s0mov ax,4c00hint 21h
code endsend start

这里mov sp,30h需要注意,因为我们在程序的开始首先定义了8个字型用于存储需要逆序存储的数据,同时分配了16个字型的数据用于栈空间使用,所以一共有24个字型,即48个字节的存储空间。所以SP指向栈顶的地址为:SS:IP=CS:30H。

接下来我们编译链接该程序,同时debug加载到内存中,如下所示:

可以看出汇编指令的确是从CS:0030开始。


6.3将数据、代码、栈放入不同的段

前面的程序中我们都是将数据,代码,栈放到一个栈空间中。这样的缺陷就是程序的逻辑不够清晰,还有一个问题是如果代码数据以及栈空间的大小超过一个段的大小,显然他们就不能被放到一个段中了。所以在实际的程序设计中,我们往往将代码,数据以及栈分别定义到不同的段空间中。

我们还是用6.2的问题来进行描述,这次我们将代码,数据,栈空间分配到不同的段中,程序如下:

assume cs:code,ds:data,ss:stackdata segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
data endsstack segmentdw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack endscode segmentstart:mov ax,stackmov ss,axmov sp,20hmov ax,datamov ds,axmov bx,0mov cx,8s:push [bx]add bx,2loop smov bx,0mov cx,8s0:pop [bx]add bx,2loop s0mov ax,4c00hint 21h
code endsend start

关于程序的说明:

1.定义多个段的方法与前面定义一个段的方法相同,不同的段有不同段名。

2.对段名的引用。既然已经定义了不同的段,那么如何通过段名来访问呢。实际上段名代表了该段的段地址。比如假设data段中的数据0abch的地址为data:6,要将该地址的内存传入bx:
mov ax,data

mov ds,ax

mov bx,ds:[6]

3.代码段,数据段,栈段的由我们安排。我们定义了三个段名data,code,stack并非是存储就代表data必须存储数据,code必须存储代码。我们可以把data用于存储代码,code用于存储数据都是可以的。 另外assume cs:code,ss,stack,ds:data并非是这样关联后cs就指向了代码段,或者说ss指向了栈段。而这里只是编译器让我们将code段与cs相关联,即把code段的段地址存入cs。CPU如何处理我们定义段的内容,是当做指令执行还是数据访问,这完全由汇编程序本身决定,也由cs:ip,ds,ss:sp的值来确定的。


OK,关于本章的内容就介绍到这里了。


这篇关于汇编语言学习第六章-包含多个段的程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识