王爽 汇编语言第三版 第10章 call 和 ret 指令 以及 子程序设计

 

 

第10章 call 和 ret 指令

 

10.1 ret 和 reft 指令

call 和 ret 指令都是转移指令,他们都修改 IP,或同事修改 CS 和 IP 。他们经常被共同来实现子程序的设计。

 

 

10.2 call 指令 和 根据位移 转移的call指令

 

 

 

段间转移 的 call 指令

 

 

转移地址 在 寄存器 中 的 call 指令

 

 

转移地址在内存 中 的 call 指令

 

 

10.7 call 和 ret 的配合使用 来 实现子程序

 

子程序 框架

 

10.8 乘法指令

 

 

10.12 寄存器的冲突问题

 

 

 

实验 10 解析

 

王爽《汇编语言》(第三版)实验10解析:https://www.cnblogs.com/nojacky/p/9523904.html

 

1. 显示字符串

示例代码:

assume cs:codedatasg segmentdb 'welcome to masm!', 0
datasg endscode segmentstart:  mov dh, 8mov dl, 3mov cl, 2mov ax, datasgmov ds, axmov si, 0call show_strmov ax, 4c00hint 21hshow_str:   push dx                push cx        push si     ; 保护子程序寄存器中用到的寄存器; 由于主程序的限定; 这里由CPU自动为我们分配栈空间mov di, 0    ; 显示缓存区中的偏移量mov bl, dh   dec bl       ; bl-1才是真正的行,因为行号从0开始计数mov al, 160  mul bl       ; 每行160字节 用 行数*每行偏移量 得到目标行的偏移量mov bx, ax   ; mul bl之后,乘积存储在ax中,这里要转存入bx中mov al, 2    ; 列的偏移量为2,两个字节代表一列!!!mul dl       ; 与行偏移量同理add bl, al   ; 将列偏移量与行偏移量相加,得到指定位置的偏移量。mov ax, 0b800hmov es, ax   ; 指定显示缓存区的内存位置mov al, cl   ; 由于后面jcxz语句的判断要用到cx,所以我们要将; cl(颜色)先存下来。s:     mov ch, 0mov cl, ds:[si]     ; 首先将当前指向字符串的某个字符存入cx中jcxz ok             ; 如果cx为0,则转移到ok标号执行相应代码mov es:[bx+di],cl   ; 将字符传入低地址mov es:[bx+di+1],al ; 将颜色传入高地址add di, 2    ; 列偏移量为2inc si       ; 字符串的偏移量为1loop s       ; 不为0,继续复制ok:     pop dx      pop cxpop si      ; 还原寄存器变量ret         ; 结束子程序调用
code endsend start

运行结果:

示例代码 2:

data segmentdb 'Welcome to masm!',0
data endscode segmentassume cs:code,ds:data
start:mov dh,1              ;dh装行号(范围:1--25)mov dl,1              ;dl装列号(范围:1--80)[注:每超过80等于行号自动加1]mov cl,0cah           ;cl中存放颜色属性(0cah为红底高亮闪烁绿色属性)mov ax,datamov ds,axmov si,0call show_strmov ax,4c00hint 21h  show_str:   ;显示字符串的子程序[定义开始]push cxpush simov al,0A0hdec dh          ;行号在显存中下标从0开始,所以减1mul dhmov bx,axmov al,2mul dlsub ax,2       ;列号在显存中下标从0开始,又因为偶字节存放字符,所以减2add bx,ax      ;此时bx中存放的是行与列号的偏移地址mov ax,0B800hmov es,ax      ;es中存放的是显存的第0页(共0--7页)的起始的段地址mov di,0mov al,clmov ch,0
s:      mov cl,ds:[si]jcxz okmov es:[bx+di],cl       ;偶地址存放字符mov es:[bx+di+1],al     ;奇地址存放字符的颜色属性inc siadd di,2jmp short s
ok:     pop sipop cxret    ;显示字符串的子程序[定义结束]
code endsend start

 

 

2. 解决除法溢出的问题

示例代码:

assume cs:code,ss:stackstack segmentdw 8 dup(0)
stack endscode segment
start:mov ax, stackmov ss, axmov sp, 10hmov ax, 4240hmov dx, 0fhmov cx, 0ah      call divdwmov ax, 4c00hint 21hdivdw:  ;子程序定义开始push axmov ax, dxmov dx, 0div cxmov bx, axpop axdiv cxmov cx, dxmov dx, bxret   ;子程序定义结束
code endsend start

测试1: 
计算:1000000/10(F4240H/0AH) 商:100000(186A0H) 余数:0 
调试结果: 

这里写图片描述

测试2: 
计算:1000020/11(F4254H/0BH) 商:90910(1631EH) 余数:10(0AH) 
调试结果: 

这里写图片描述

 

 

3. 数值显示

示例代码:

assume cs:code,ds:datadata segmentdb 10 dup (0)
data endscode segment
start:mov ax,12666mov bx,datamov ds,bxmov si,0call dtoc mov dh,8mov dl,3mov cl,0cahcall show_strmov ax,4c00hint 21h
dtoc:  ;数值显示的子程序定义push dxpush cxpush axpush sipush bxmov bx,0
s1:     mov cx,10dmov dx,0div cx        mov cx,axjcxz s2add dx,30hpush dxinc bxjmp short s1
s2:     add dx,30hpush dxinc bx     ;再进行一次栈操作(补充当"商为零而余数不为零"时的情况)mov cx,bxmov si,0
s3:     pop axmov [si],alinc siloop s3
okay:   pop bxpop sipop axpop cxpop dxret   ;数值显示的子程序定义结束
show_str:  ;显示字符串的子程序已经在第一题中说明,在此不再赘述。push bxpush cxpush simov al,0A0hdec dhmul dhmov bx,axmov al,2mul dlsub ax,2add bx,axmov ax,0B800hmov es,axmov di,0mov al,clmov ch,0
s:      mov cl,ds:[si]jcxz okmov es:[bx+di],clmov es:[bx+di+1],alinc siadd di,2jmp short s
ok:     pop sipop cxpop bxret
code ends
end start

运行结果:

详解版:

源地址:https://blog.csdn.net/include_heqile/article/details/80602772

assume cs:codedata segmentdw 123, 12666, 1, 8, 3, 38data endsascii segmentdb 100 dup(0);ascii码值,一个字节即可存储ascii endsdiv segmentdw 16 dup(0);除法溢出计算需要使用该数据段来临时保存结果div endscode segmentstart:      mov bx, datamov ds, bx;ds段寄存器用来存放待处理的数据mov si, 0call dtocmov cx, 6mov ax, 0mov dh, 8show:       push cxmov dl, 3mov cl, 2call show_strpop cx;我们需要更改行号来避免覆盖inc dhloop showmov ax, 4c00hint 21h dtoc:       ;该子程序用于将数值型的数字转换为字符串;十进制数值转换为ASCII码值,转换关系为:ascii=10进制+30H;要想将一个十进制的整数拆分成一个一个的数值,那我们需要让这个数;除以10,然后将得到的结果依次入栈,除完之后再依次出栈,即可得到由高位到低位;的所有数值,之后将这些值加上30H,即得到其对应的ASCII码值,然后将这些;ASCII码值存放到一个数据段中,调用show_str函数,来在屏幕上显示这些数值;为了存储转换后的ASCII码值,我们需要新开辟一个数据段push axpush bxpush cxpush dxpush dspush sipush esmov ax, asciimov es, ax;使用es段寄存器来存储转换后的ascii码值mov di, 0;存储ASCII数据时用来指向ascii段中的每个内存单元 mov cx, 6loop_zone:  push cx;因为内层循环会更改cx的值,所以我们需要使用栈结构来保存cx的值mov dx, 0;记录十进制数据的位数mov ax, ds:[si];ax存放被除数split:      push dx;下面要用到dx寄存器,因此我们先保存dxmov cx, 0ah;cx存放除数 mov dx, 0;dx作为被除数高16位,置0div cx;32/16的除法运算,商存储在ax中,余数存储在dx中mov cx, dx;call divdw;其实用不着调用divdw,这个除法溢出问题不是真正的除法溢出问题;我们只需要将被除数凑成32位的,除数当做16位的即可;此程序返回运算后的商和余数,分别保存在ax和cx中;如果被除数大于2550,al是无法存放商的,会造成溢出,因此,我们需要调用本实验中第二个函数;专门用于解决除法溢出问题的函数,虽然程序2解决的是32/16的除法运算的溢出问题,但是对于16/8位的;除法运算也是完全适用的;由于入栈时只能使用字型数据,所以我们压入的是ax,此时需要将;无关数据,也就是al置0pop dx;取出dx更改前的值push cx;余数入栈inc dx;当循环终止的时候可以进行弹栈存储操作了,但是我们需要一个标记,来标识我们需要;弹出多少次,我们使用dx来进行存储mov cx, axadd cx, dx;ax中的值在下一次运算中一定会用到,dx中的值也有可能会用到(当被除数很大时);此时可以临时保存数据的只有cx了,因此我们直接将运算结果放到cx中;一举两得jcxz ok1;处理过程是需要循环的,循环结束的条件是商==0 ;我们只需要将执行jcxz指令即可,当cx的值位0的时候,它会自动跳转到ok1循环的jmp short split ok1:        pop axadd al, 30hmov byte ptr es:[di], alinc didec dxmov cx, dxjcxz lastjmp short ok1last:       ;最后一步,在数据的ASCII数据形式的最后加上一个0mov ah, 0mov byte ptr es:[di], ah inc di;从split到ok1到最后一步是对data段中第一个数据的处理;这个过程需要进行循环操作;在这个循环中,di,bx是放在循环外的pop cxadd si, 2loop loop_zonepop espop sipop dspop dxpop bxpop cxpop axretdivdw:      push dspush dxpush cxpush ax mov ax, divmov ds, axmov dx, 0;由于本程序中被除数是16位,但是divdw是32/16,所以我们需要将被除数的高位补16个0,也就是将dx置0mov ax, dxmov dx, 0div cx;ax存放商,dx存放余数;根据公式,使用被除数高位除以除数得到的商×65536;*65536等价于在低位加16个0,因此操作就会变得非常简单;使用被除数高位除以除数得到的余数×65536+被除数的低位,再将得到的结果除以除数;两者的结果相加,即可得到32位/16位的无溢出结果push dx;使用栈临时保存余数mov dx, axmov ax, 0mov ds:[0], axmov ds:[2], dxpop dx;弹出余数,作为右操作数中被除数的高16位pop bx;得到被除数的低16位push bx;恢复栈顶数据,避免对主程序造成干扰;add ax, bx;将右操作数[]中的左操作数的低16位和被除数的低16位相加;但是右操作数[]中的左操作数的低16位一定是全0的,因此我们可以省略这一步;直接执行mov ax, bxmov ax, bxdiv cx;ax存放商,dx存放余数;由于左操作数的低16位一定是全0,所以不必与其相加,直接将;右操作数的低16位存储到ds:[0]内存单元即可mov ds:[0], ax;商的低16位放到ds:[0]单元中mov ds:[4], dx  ;余数放到ds:[4]单元中;ds:[2]中一直保存的都是商的高16位,且没有被更改过,因此无须任何操作pop axpop cxpop dxmov ax, ds:[0];ax保存商的低16位mov dx, ds:[2];dx保存商的高16位mov cx, ds:[4];cx保存余数  pop ds;之所以要在pop ds之前将数据转移,是因为子程序divdw调用前,ds已经被使用;指向的是其他的段,如果不在pop之前转移数据,那么div段的数据就无法获取了retshow_str:   push bxpush cxpush dxpush dspush espush dipush axpush si;根据上节中的框架,为了不让子程序干扰主程序中寄存器的值,将所有子程序会用到的寄存器进行压栈mov di, axmov ax, 0b800hmov es, ax;颜色区的段地址mov ax, asciimov ds, ax;待输出的ASCII码值数据段mov al, 160 mul dh;每行占160个字节,乘以行数push ax;将行计算的结果存储到栈中mov al, 2mul dl;每列占2个字节,乘以列数pop bx;将上次运算的结果(160×行数)的值转移到bx中add bx, ax  ;此时的ax值为(2×列数);将两者相加,最终结果保存到bx中mov dl, cl;因为下面的跳转指令jcxz需要用到cx寄存器,故需要将cl的值先保存在dl中change:     mov cl, ds:[di]mov ch, 0 inc di;我们需要记录下di的值,下一轮循环还会用到它;这样一来,我们就需要调整入栈和出栈寄存器的位置了;我们在pop di之前pop ax,然后使用ax来保存di的值jcxz ok2mov ch, dl mov es:[bx+si], cxadd si, 2jmp short changeok2:        pop sipop axmov ax, dipop dipop espop dspop dxpop cxpop bx retcode endsend start 

这里写图片描述

示例代码 2:

assume cs:code,ds:datadata segmentdb 10 dup(0)
data endscode segment
start:mov ax,12666mov bx,datamov ds,bxmov si,0call dtocmov dh,8mov dl,3mov cl,02hcall show_strmov ax,4c00Hint 21Hdtoc:push dxpush cxpush axpush sipush bxmov bx,0	;bx在子程序中用来存放位数,用栈来临时存放修改后的字符dtoc00:mov cx,10d	;d表示十进制mov dx,0div cx		;除以10mov cx,ax	;得到的商赋给cxjcxz dtoc01		;当前商为0则调到s2add dx,30H	;将余数加上30H得到相应的ASCII码push dxinc bxjmp short dtoc00dtoc01:				;当商为0时,余数为个位add dx,30Hpush dxinc bx		;再进行一次栈操作(补充当商为0而余数不为0时的情况)mov cx,bx mov si,0dtoc02:				;s3实现将栈中的数据依次出栈放到制定内存中pop axmov [si],alinc siloop dtoc02dtoc03:pop bxpop sipop axpop cxpop dxretshow_str:	;显示字符串的子程序(定义开始)push cxpush simov al,0a0H	;每行为160字节 a0H=160dec dh	;行号在显存中下标从0开始,所以减1mul dh	;相当于从(n-1)*0a0H个Byte单元开始mov bx,ax	;定位好的位置偏移地址存放在bx里面(行)mov al,2	;每个字符占两个字节mul dl	;定位列,结果ax存放的是定位好的列的位置sub ax,2	;列号在显存中下标从0开始,又因为偶字节存放字符,所以减2add bx,ax	;此时bx存放的是行与列的偏移地址mov ax,0b800Hmov es,axmov di,0	;指向显存的偏移地址mov al,cl	;cl是存放颜色的参数,这时候al存放颜色了mov ch,0	;下边cx存放的是每次准备处理的字符show_str00:mov cl,ds:[si]	;ds:[si]指向'Weclome to masm!'jcxz show_str01mov es:[bx+di],cl	;偶数地址存放字符mov es:[bx+di+1],al	;奇数地址存放颜色属性inc siadd di,2jmp short show_str00 show_str01:pop sipop cxretcode ends
end start

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/495685.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

org/apache/maven/cli/MavenCli : Unsupported major.minor version 51.0

一、错误现象: 当改变了jdk版本时,在编译java时,会遇到Unsupported major.minor version错误。 jdk版本和stanford parser对应关系 JDK版本和Java编译器内部的版本号 J2SE 8 52, J2SE 7 51, J2SE 6.0 50, J2SE 5.0 49, JDK 1.4 48, J…

ip, tcp, udp, icmp header

Figure 1. IPv4 header Figure 2. TCP header Figure 3. UDP header Figure 4. ICMP header reference:TCP/IP Reference转载于:https://www.cnblogs.com/lbsx/archive/2010/11/30/1891814.html

人民日报三问人工智能,给法律制度带来哪些挑战?

来源:亿欧网 作者:倪弋摘要:人工智能生成物是否具有知识产权?人工智能可以替代司法者吗?人工智能侵权责任如何认定?人工智能的出现会给现行的法律制度带来了不少挑战,只有在法律研究上未雨绸缪…

测试用例设计--判定表

一. 判定表 定义判定表通常由四部分组成,如上图: 条件桩 : 它列出决定一组条件的对象; 条件项: 它列出各种可能的条件组合; 动作桩: 它列出所有的操作; 动作项: 它列出在对应的条件组合下的动作. 应用的范围在多个条件决定多个动…

王爽 汇编语言第三版 第11章 标志寄存器

条件码: ① OF(Overflow Flag)溢出标志,溢出时为1,否则置0.标明一个溢出了的计算,如:结构和目标不匹配.② SF(Sign Flag)符号标志,结果为负时置1,否则置0.③ ZF(Zero Flag)零标志,运算结果为0时…

Gartner:预计2018年人工智能行业总价值达1.2万亿美元

来源:网络大数据市场研究公司Gartner周三发布最新研究报告称,人工智能行业的总价值将在2018年达到1.2万亿美元,比2017年增长70%。其中,创造商业价值最大的领域是客户体验解决方案。该公司还预计,到2022年的时候&#x…

JAVA将html[动态]页面转成图片

近日项目上接到一个任务,设计并编写住院病案首页页面,然后将其转换成图片显示给医生查看。 天哪,住院病案内容那么多,光编写这个页面就已经够呛了,转图片我也没弄过,于是百度了一下,花了两天时间…

王爽 汇编语言第三版 课程设计 1

From:https://www.cnblogs.com/Since-natural-ran/p/6938133.html 汇编语言-课程设计1: https://www.cnblogs.com/tsembrace/p/3267158.html 王爽课程设计1(汇编语言编写): https://www.imooc.com/article/18785 王爽《汇编语言》课程设计1: https://blog.csdn.net/…

挑战权威还是偏离主流?颠覆性研究或将证明神经信号是机械波

来源:科研圈 翻译 马骁骁 编辑 魏潇 廖红艳就职于哥本哈根尼尔斯玻尔研究所(Niels Bohr Institute)的托马斯亨伯格(Thomas Heimburg),是一位研究量子力学和生物物理的物理学家。然而,他却希…

史上最全的女人坐月子注意事項

希望男人们要精心照顾好妻子,让妻子平安度过这一时期,为了宝宝,为了你们的幸福,因为你爱她就要呵护她,她好你也好,她平安就是你们全家的幸福,精致女人把祝福送给你们! 传统上人们将产…

斯坦福大学、DARPA与硅谷公司共同分析前沿科技发展趋势

来源:科技日报 作者:张梦然日前,斯坦福大学研究团队、美国国防部高级研究计划局(DARPA)以及硅谷创投公司和米资本的专家们,共同研讨了技术将如何重塑行业和社会等问题。他们分析了现今全球前沿科技的未来…

小甲鱼 OllyDbg 教程系列 (一) :二进制破解科普系列之 ReverseMe

小甲鱼 视频教程( 4、5 集 ):https://www.bilibili.com/video/av6889190?p4 实验程序 reverseME.exe 下载地址:https://pan.baidu.com/s/18NDV3rQ_yV_qzUrNRYmqjA 提取码:e91j http://www.360doc.com/content/1…

java将字符串生成图片

java将字符串保存为图片 因为最近接触到的需求是要将指定的字符串内容保存为图片,我知道肯定要用awt相关的东西,但是以前没有接触过awt,所以只能去网上学习相关的东西和找有关的资料,好在最后可以解决,直接上代码&…

AI 综述专栏 | 超长综述让你走近深度人脸识别

来源:人工智能前沿讲习班 作者: 葛政相信做机器学习或深度学习的同学们回家总会有这样一个烦恼:亲朋好友询问你从事什么工作的时候,如何通俗地解释能避免尴尬?我尝试过很多名词来形容自己的工作:机器学习&…

机器人也能拥有人类情感:“情感计算”让机器人学会“读心术”

来源:《情感计算与情感机器人系统》作者:吴敏,刘振焘,陈略峰著随着机器人进入日常生活中的各个方面,人们对其提出了更高的要求,希望它们具有感知人类情感、意图的能力,这类机器人称为情感机器人…

C 语言 函数调用栈

From:https://www.cnblogs.com/clover-toeic/p/3755401.html https://www.cnblogs.com/clover-toeic/p/3756668.html 程序的执行过程可看作连续的函数调用。当一个函数执行完毕时,程序要回到调用指令的下一条指令(紧接call指令)处继续执行。函数调用过…

寒武纪创始人兼CEO陈天石博士的公开信

来源:来源:寒武纪科技摘要:2018年5月3日,寒武纪已在中国上海发布了首款云端智能芯片MLU100及相应的板卡产品。作为寒武纪的创始人和CEO,我非常自豪地与大家分享一个消息:2018年5月3日,寒武纪已在…

压栈, 跳转,执行,返回:从汇编看函数调用

From:https://www.jianshu.com/p/594357dff57e C函数调用过程原理及函数栈帧分析:https://blog.csdn.net/zsy2020314/article/details/9429707 从本篇开始,我们讨论一些高级语言中的基础设施:堆栈,函数调用&#xff0…

IBM AIX 5.3 系统管理 -- 系统启动过程详解

一. 启动过程 启动过程包含下面的一些步骤: 1.1启动一个系统的初始步骤是上电自检(Power On Self Test,POST)。其目的是验证基本硬件是否处于正常的工作状态。同时初始化内存、键盘、通信,以及音频设备。您可以看到在屏…