包含多个段的程序---汇编学习笔记
包含多个段的程序
要使用一段安全的空间,第五章中我们说0:200~0:2ff是相对安全的。可这段代码容量只有256个字节。
合法地通过操作系统取得的空间都是安全的。
程序取得所需空间的方法有两种,一是加载程序的时候程序分配,再就是程序在执行的过程中向系统申请。
对于使用多个段的问题,我们将讨论:
(1)在一个段中存放数据、代码、栈,我们先来体会一下不使用多个段时的情况;
(2)将数据、代码、栈放入不同的段中。
6.1 在代码段中使用数据
考虑这样一个问题,编程计算以下8个数据的和,结果存在ax寄存器中:
0123h、0456h、0789h、0abch、0defh、0fedh、0cbah、0987h
我们如何去寻找这个内存段的空间呢?(这里有代码段和数据段)
从规范的角度来讲,我们不能自己随便决定哪段空间可以使用,应该由系统来分配。我们可以在程序中,定义我们希望处理的数据,这些数据就会被编译、连接程序作为程序的一部分写到可执行文件中。当可执行文件中的程序被加载入内存时,这些数据也同时被加载入内存中。与此同时,我们要处理的数据也就自然而然地获得了存储空间。
看具体程序:
assume cs:code
code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h ;dw代表是字型数据mov bx,0mov ax,0mov cx,8
s: add ax,cs:[bx]add bx,2loop smov ax,4c00hint 21hcode ends
end
编译、连接这段程序后,我们看到如下:
显然,我们程序从cs:ip开始,而cs开始部分就是数据部分。明显是我们程序在代码段的dw影响了这段代码开始执行的位置(更准确的说,是我们没有定义数据段)。
那么,我们怎样让程序正确的(或说cs:ip)指向程序入口呢?如下:
assume cs:code
code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hstart: mov bx,0mov ax,0mov cx,8
s: add ax,cs:[bx]add bx,2loop smov ax,4c00hint 21hcode ends
end start
如上代码所看到的,我们在两处加了start。
可执行文件中的程序执行过程如下:
- 由其他的程序(Debug、command或其他程序)将可执行文件中的程序加载入内存;
- 设置CS:IP指向程序的第一条要执行的指令(即程序的入口),从而使程序得以运行;
- 程序运行结束后,返回到加载者。
现在的问题是:我们由什么来判定程序入口呢?具体框架如下
6.2 在代码段中使用栈
完成下面的程序,利用栈,将程序中定义的数据逆序存放。
assume cs:code
code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h? mov ax,4c00hint 21hcode ends
end
程序思路:定义的数据存放在cs:0~f单元中,我们只要将数据依次入栈,再依次出栈就可以逆序存放了。
问题是:我们首先要有一段可当作栈的内存空间。如下:
assume cs:code
code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;用dw定义16个字型数据,在程序加载后,将取得16个字的;内存空间,存放这16个数据。后面的程序段中将这段空间;当作栈来使用start: mov ax,csmov ss,axmov sp,30h ;将设置栈顶ss:sp指向cs:30mov bx,0mov cx,8s: push cs:[bx]add bx,2loop s ;将代码段0~15单元中的8个字型数据依次入栈mov bx,0mov cx,8s0: pop cs:[bx]add bx,2loop s0mov ax,4c00hint 21hcode ends
end start
自此,我们的程序段定义并且使用了,发现很麻烦。
检测点 6.1
(1)下面程序实现依次使用内存0:0~0:15单元中的内容改写程序中的呃数据,完成程序:
assume cs:code
code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hstart: mov ax,0mov ds,axmov bx,0mov cx,8
s: mov ax,[bx]mov cs:[bx],ax ;题目这段代码为空,需要自己填写add bx,2loop smov ax,4c00hint 21hcode ends
end start
(2)下面的程序实现依次内存0:0~0:15单元中的内容改写程序中的数据,数据的传送用栈来进行。栈空间设置在程序内。完成程序:
assume cs:code
code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdw 0,0,0,0,0,0,0,0start: mov ax,cs ;题目ax后面为__mov ss,axmov sp,20h ;题目ss后面为__mov ax,0mov ds,axmov bx,0mov cx,8s: push [bx]pop cs:[bx] ;题目为________add bx,2loop smov ax,4c00hint 21hcode ends
end start
6.3 将数据、代码、栈放入不同的段
在前面的内容中,我们在程序中用到了数据和栈,将数据、栈和代码都放在了一个段里面。
这样做显然有两个问题:
(1)把它们放在一个段中使程序显得混乱
(2)前面程序中处理的数据很少,用到的栈空间也很小,加上没有很长的代码,放到一个段里面没有问题。但如果数据、栈和代码需要的空间超过64KB,就不能放在一个段中。
所以,应该考虑用多个段存放数据、栈和代码。如下所示:
assume cs:code,ds:data,ss:stack;数据段
data segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
data ends;栈段
stack segmentdw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends;代码段
code segmentstart: mov ax,stackmov ss,axmov sp,20h ;设置栈顶ss:sp指向stack:20mov ax,datamov ds,axmov bx,0 ;设置ds:bx指向data段的第一个单元mov cx,8
s: push [bx]add bx,2loop s ;以上将data段中的0~15单元中的8个字型数据一次入栈mov bx,0mov cx,8
s0: pop [bx]add bx,2loop s0 ;以上依次出栈8个字型数据到data段的0~15单元中mov ax,4c00hint 21hcode endsend start
程序说明:
(1)定义多个段的方法
定义一个段的方法和前面所讲的定义代码段的方法没有区别,只是对于不同的段,要有不同的段名。
(2)对段地址的引用
现在,程序中有多个段了,如何访问段中的数据呢?当然要通过地址,而地址是分为两部分,即段地址和偏移地址。如何指明要访问的数据的段地址呢?在程序中,段名就相当于一个标号,它代表了段地址。(形如:mov ax,data)
(3)“代码段”、“数据段”、“栈段”完全是我们的安排
- 我们在源程序中为这三个命名为code、stack、data
- 我们在源程序中用伪指令“assume cs:code,ds:data,ss:stack”将它们关联起来
- 若要CPU按我们的安排行事,就要用机器指令控制它,源程序中的汇编指令是CPU要执行的内容。CPU如何知道执行它们?我们在源程序的最后用“end start”说明程序的入口,这个入口将被写入可执行文件描述信息,可执行文件的程序被加载入内存后,CPU的CS:IP被设置指向这个入口,从而开始执行程序中的第一条指令。
–
实验 5 编写、调试具有多个段的程序
(1)将下面的程序编译连接,用Debug加载、跟踪,然后回答这个问题。
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
stack endscode segment
start: mov ax,stackmov ss,axmov sp,16mov ax,datamov ds,axpush ds:[0]push ds:[2]pop ds:[2]pop ds:[0]mov ax,4c00hint 21hcode ends
end start
1.CPU执行程序,程序返回前,data段的数据为多少?
2.CPU执行程序,程序返回前,cs=?、ss=?、ds=?。
3.设置程序加载后,code段的段地址为X,则data段的段地址为?,stack段的段地址为?。
code=X、data=X-20、stack=X-10。
(2)将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。
assume cs:code,ds:data,ss:stackdata segmentdw 0123h,0456h
data endsstack segmentdw 0,0
stack endscode segment
start: mov ax,stackmov ss,axmov sp,16mov ax,datamov ds,axpush ds:[0]push ds:[2]pop ds:[2]pop ds:[0]mov ax,4c00hint 21hcode ends
end start
1.CPU执行程序,程序返回前,data段中的数据为多少?
2.CPU执行程序,程序返回前,cs=?、ss=?、ds=?。
3.设程序加载后,code段的段地址为X,则data段的段地址为?,stack段的段地址为?。
cs = X , ds = X-20, ss = X-10。
4.对于如下定义的段:
name segment
···
name ends
如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为?。
N/256取上整
(3)将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。
assume cs:code,ds:data,ss:stackcode segment
start: mov ax,stackmov ss,axmov sp,16mov ax,datamov ds,axpush ds:[0]push ds:[2]pop ds:[2]pop ds:[2]mov ax,4c00hint 21hcode endsdata segmentdw 0123h,0456h
data endsstack segmentdw 0,0
stack endsend start
1.CPU执行程序,程序返回前,data段中的数据为多少?
2.CPU执行程序,程序返回前,cs=?、ss=?、ds=?。
3.设程序加载后,code段的段地址为X,则data段的段地址为?,stack的段地址为?。
code=X , data=X+(code指令字节数/256)取上整+1 , stack = data + 1。
(4)如果将(1)(2)(3)题中的最后一条伪指令“end start”改为“end”(也就是说,不指名程序的入口),则哪个程序仍然可以正确执行?请说明原因。
第3个可以,首先是指令从何处开始,3可以正确的指向指令开始出,而其他两个不行;其次,是指令结束,3个都可以正常结束,因为只要遇到mov ax,4c00h和int 21h执行完后,程序就返回了。
(5)程序如下,编写code段中的代码,将a段和b段中的数据依次相加,将结果存到c段中。
assume cs:codea segmentdb 1,2,3,4,5,6,7,8
a endsb segmentdb 1,2,3,4,5,6,7,8
b endsc segmentdb 0,0,0,0,0,0,0,0
c ends
;题目code需要自己编写
code segment
start:mov ax,cmov ds,axmov bx,0mov ax,amov es,axmov cx,8s: mov dl,0add dl,es:[bx]add dl,es:[bx+16]mov [bx],dlinc bxloop smov ax,4c0hint 21hcode ends
end start
实验结果如下:
(6)程序如下,编写code段中的代码,用push指令将a段中的前8个字型数据,逆序存储到b段中。
assume cs:codea segmentdw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0fh,0ffh
a endsb segmentdw 0,0,0,0,0,0,0,0
b ends
;题目代码段需要自己编写
code segment
start:mov ax,bmov ss,axmov sp,16mov ax,amov ds,axmov bx,0s: push [bx]add bx,2loop smov ax,4c00hint 21hcode ends
end start
实验结果如下:
本章完
包含多个段的程序---汇编学习笔记相关推荐
- 第一个程序---汇编学习笔记
第四章 第一个程序 4.1 一个源程序从写出到执行的过程 一个汇编语言程序从写到最终执行的简要过程. 编写汇编源程序 对源程序进行编译连接 执行可执行文件中的程序 如图所示: 4.2 源程序 程序代码 ...
- 包含多个段的程序01 - 零基础入门学习汇编语言29
第六章:包含多个段的程序01 让编程改变世界 Change the world by program 引言 前面我们写的程序中,只有一个代码段. 现在有一个问题是: 如果程序需要用其他空间来存放数据, ...
- 《汇编语言》第6章 -包含多个段的程序 检测点答案,实验5,总结
第6章:包含多个段的程序 1.在代码段中使用数据 "dw":define word(定义字型数据:) "db"(定义字节型数据:) "start&qu ...
- 汇编学习笔记——伪指令
目录 伪指令 段定义 结束标记 段关联标记 数据定义 标号 offset指令 seg指令 地址标号 数据标号 代码分段 程序标识 多文件系统 字符输入 重复定义 注释 重复汇编伪指令 伪指令汇总 伪指 ...
- 汇编学习笔记——汇编指令
目录 汇编指令 nop指令 mov.add.sub指令 adc.sbb指令 and.or指令 移位指令 逻辑左/右移指令 循环左/右移指令 算术左/右移指令 带进位循环左/右移指令 inc指令 pus ...
- GTK+图形化应用程序开发学习笔记(五)—组装盒、组合表、固定容器构件
GTK+图形化应用程序开发学习笔记(五)-组装盒.组合表.固定容器构件 一.组装盒 组装盒(GtkBox)也称为组合构件.使用组装盒可以将多个构件放在一个容器中.容器可以把组装盒看作是一个构件.不像按 ...
- GTK+图形化应用程序开发学习笔记(一)—概述
GTK+图形化应用程序开发学习笔记(一)-概述 一.什么是GNOME. GNOME的意思是"GNU Network Object Model Environment"(GNU网络对 ...
- 【前端学习笔记】移动web-黑马程序员学习笔记
移动web-黑马程序员学习笔记 1 字体图标 2 平面转换 2.1 绝对定位元素居中: 2.2 双开门效果 2.3 旋转效果 2.4* 转换原点 2.5 多重转换效果 2.6 缩放 3* 渐变 4 空 ...
- 汇编学习笔记:对抗反汇编实验2019092801
汇编学习笔记:对抗反汇编实验2019092801 实验描述 实验环境 实验过程 实验结论 实验描述 使用相连的jz和jnz指令跳转到紧接着jnz指令的call指令的第二个字节.call指令实际上无效. ...
最新文章
- 10.2.2移动产品离线功能等具体解释----暨4月8日移动《在离线一体化》公开课Qamp;A...
- Apache OFBIZ高速上手(二)--MVC框架
- c++ STL 工程实践的15条建议
- Macbook pro wifi连接无线路由不稳定掉线的解决办法
- 每天进步一点点《ML - 逻辑回归》
- Vue中基于Vuex使用echarts组件动态数据绑定的方法
- Asp.Net中global.asax文件的描述
- qbittorrent container 改共享文件_SSH连接docker中的container
- 如何帮助企业把风控做得更好?
- Cocos2d-x v3.2笔记——总结Cocos2d-x 3.x版本的一些变化
- FPGA + labwindows/CVI 2017 串口通信 电子钟
- android上传速度测试,使用Android获取当前的互联网速度(移动和Wifi)
- 如何获取免费的数字货币历史数据
- 对于阿里云的oss上传本地图片的相关注意点
- Android接入极光推送,接入华为,小米,OPPO,VIVO厂商通道
- 学习笔记2022.7.25-7.30
- 默的各种写法图片_默字的意思、默的繁体字、默的笔顺笔画、默字部首和繁体字默的意思...
- 让字母自增,就像A-Z,Z后面就是AA-AZ,然后BA-BZ...
- 720度全景带你vr云游景区,vr云游在景区的应用优势
- RiskCloud-基于Markov算法精准的SIL验证模块