汇编语言程序设计子程序结构.ppt_第1页
汇编语言程序设计子程序结构.ppt_第2页
汇编语言程序设计子程序结构.ppt_第3页
汇编语言程序设计子程序结构.ppt_第4页
汇编语言程序设计子程序结构.ppt_第5页
已阅读5页,还剩38页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1 4 3子程序结构 经常用到的应用问题编写成一个通用子程序大型处理过程分解成小的较方便解决的模块使用子程序的优点使程序的结构更为清楚程序的维护更为方便有利于大程序开发时的多个程序员分工合作对于汇编语言 子程序 Subroutine 高级语言 函数 Function 或过程 Procedure 2 4 3 1子程序指令 子程序与主程序分开的 完成特定功能的一段程序 子程序完成一定功能 它需要主程序调用它 子程序执行完毕 还需要返回到调用它的主程序去继续执行主程序的后续指令 3 子程序一般需要参数 主程序调用子程序前 要为子程序准备好所需要的参数子程序要将对信息处理的结果提供给调用它的主程序 子程序的调用当主程序 调用程序 执行调用指令CALL调用子程序 转到子程序去执行子程序的返回子程序 被调用程序 执行返回指令RET 返回调用它的主程序 4 1 子程序调用指令CALL 1 功能CALL指令用在主程序中 实现子程序的调用CPU硬件自动将主程序调用指令CALL下条指令的地址 返回地址 压入堆栈 以便子程序执行完毕后 还能够返回主程序继续执行 2 调用范围分成段内调用 近调用 同一代码段内和段间调用 远调用 整个存储空间 3 寻址方式目标地址采用相对寻址 直接寻址或间接寻址 5 4 格式 CALLlabel 调用标号指定的子程序 CALLreg16 reg32 调用寄存器指定地址的子程序 CALLmem16 mem32 调用存储单元指定地址的子程序注意 对于段内调用 只修要将调用的段内偏移地址压入堆栈实地址模式 16位的偏移地址保护模式 32位的偏移地址对于段间调用 需要保护偏移地址IP EIP 和CS实地址模式 需要将16位偏移地址IP 16位段基地址CS压入堆栈 需要保护32位的偏移地址EIP和段选择器CS CS被进行0扩展变为32为压入堆栈 6 2 子程序返回指令RET 1 功能RET指令用在子程序结束 实现返回主程序 2 格式 RET 无参数返回 自动从堆栈弹出返回地址 如果定义的是短过程 子程序 则是段内调用 只弹出段内偏移地址IP 或EIP 如果定义的是远过程 子程序 则是段间调用 需要弹出CS和偏移地址 实模式 16位的CS 16位的偏移地址送IP 保护模式 弹出32位 高16位是CS的0扩展丢去 低16位送CS 再弹出32位偏移地址送EIP 7 RETi16 有参数返回 返回主程序与RET指令同 增加的功能 将堆栈指针进行修改 8086及IA 32实地址 SP SP i16IA 32保护模式 ESP ESP i16当使用堆栈向子程序传递参数时 该返回指令较有用 子程序时段内还是段间返回 在子程序设计时由过程定义伪指令通过属性参数指定 NEAR段内FAR段间 8 3 过程定义伪指令 X86的汇编语言 需要利用过程定义伪指令来定义子程序 定义过程 及其属性 1 过程定义伪指令的功能定义一个过程 子程序 说明是短调用还是长调用子程序MASM利用过程定义伪指令获得子程序信息 9 2 格式过程名PROC属性参数 子程序代码过程名ENDP 过程名为符合语法的标识符 与标号的定义相同 子程序调用时 就是用该名称调用对应的子程序 PROC后面可加参数 NEAR或FARNEAR 段内调用的子程序 默认为NEAR FAR 段间调用的子程序在简化段定义源程序格式中 通常不需指定子程序的属性 使用默认属性 10 例4 14 子程序调用程序 1 代码段 主程序00000000B800000001moveax 100000005BD00000005movebp 50000000AE800000016callsubp 调用0000000FB900000003retp1 movecx 3 返回位置00000014BA00000004retp2 movedx 400000019E800000000Ecalldisprd 调用注 disprd为显示子程序 11 例4 14 子程序调用程序 2 子程序subpproc 过程定义 过程名为subppushebpmovebp espmovesi ebp 4 ESI CALL下条指令 标号RETP1 偏移地址movedi offsetretp2 EDI 标号RETP2的偏移地址movebx 2popebp 弹出堆栈 保持堆栈平衡ret 子程序返回subpendp 过程结束子程序的调用和返回都要操作堆栈 保护返回地址 弹出返回地址 12 13 4 3 2子程序设计 子程序的编写方法与主程序一样但需要留意几个问题 利用过程定义 获得子程序名和调用属性CALL指令调用子程序 RET指令返回主程序堆栈压入和弹出操作要成对使用 保持堆栈平衡子程序开始要保护寄存器 返回前相应恢复子程序安排在代码段的主程序之外子程序允许嵌套和递归 最好有完整的注释 难点是参数传递 14 例4 15 十六进制显示程序 1 moveax 1234abcdh 假设一个数据 十六进制xorebx ebxmovecx 8 8位十六进制数again roleax 4 高4位循环移位进入低4位pusheax 保护eax 也可用movedx eax保护callhtoasc 调用子程序movregd 4 ebx al 保存转换后的ASCII码popeax moveax edxincebxdececxjnzagainmoveax offsetregdcalldispmsg 显示 regdbyte EAX 8dup 0 H 0 15 例4 15 十六进制显示程序 2 子程序htoascproc 默认属性 NEAR 将AL低4位表达的一位十六进制数转换为ASCII码andal 0fh 只取AL的低4位oral 30h AL高4位变成3cmpal 39h 是0 9 还是A Fjbehtoend 无符号数比较后 不高于39Haddal 7 是A F ASCII码再加上7htoend ret 子程序返回htoascendp 过程定义结束END 汇编语言原程序结束 16 例4 15 十六进制显示程序 3 也可以使用查表方法进行转换 子程序htoascprocandeax 0fh 取AL低4位moval ASCII eax 换码ret 子程序的局部数据 只读 ASCIIbyte 0123456789ABCDEF htoascendp EAX 1234ABCDH 运行结果 还可以使用换码指令XLAT查表 17 4 3 3参数传递 主程序与子程序间通过参数传递建立联系入口参数 输入参数 主程序 子程序出口参数 输出参数 子程序 主程序传递参数的多少反映程序模块间的耦合程度参数的具体内容数据本身 传递数值 数据的存储地址 传递地址 传递引用 参数传递方法寄存器 约定参数存放在某个或几个寄存器中变量 利用定义的变量堆栈 利用堆栈 18 1 寄存器传递参数 最简单和常用的参数传递方法把参数存于约定的寄存器少量数据直接传递数值大量数据只能传递地址需要注意 带有出口参数的寄存器不能保护和恢复带有入口参数的寄存器可以保护 也可以不保护 但最好能够保持一致 19 例4 16 有符号十进制数显示程序 1 转换的算法如下 1 首先判断数据是零 正数或负数 是零显示 0 退出 2 是负数 显示负号 求数据的绝对值 3 接着数据除以10 余数为十进制数码 加30H转换为ASCII码保存 4 重复 3 步 直到商为0结束 5 依次从高位开始显示各位数字 20 例4 16 有符号十进制数显示程序 2 数据段arraydword1234567890 1234 0 1 writebufbyte12dup 0 显示缓冲区 代码段movecx lengthofarraymovebx 0again moveax array ebx 4 EAX 入口参数callwrite 调用子程序 显示一个数据calldispcrlf 换行以便显示下一个数据incebxdececxjnzagain 寄存器传递参数 21 例4 16 有符号十进制数显示程序 3 显示有符号十进制数的子程序writeproc EAX 入口参数pushebx 保护寄存器pushecxpushedxmovebx offsetwritebuf EBX指向显示缓冲区testeax eax 判断数据是零 正数或负数jnzwrite1 不是零 跳转movbyteptr ebx 0 是零 设置 0 incebxjmpwrite5 转向显示write1 jnswrite2 是正数 跳转movbyteptr ebx 是负数 设置负号incebxnegeax 数据求补 绝对值 寄存器传递参数 22 例4 16 有符号十进制数显示程序 4 write2 movecx 10pushecx 10压入堆栈 作为退出标志write3 cmpeax 0 数据 商 为零 转向保存jzwrite4xoredx edx 零位扩展被除数为EDX EAXdivecx 数据除以10 EDX EAX 10addedx 30h 余数 0 9 转换为ASCII码pushedx 数据先低位后高位压入堆栈jmpwrite3 23 例4 16 有符号十进制数显示程序 5 write4 popedx 数据先高位后低位弹出堆栈cmpedx ecx 是结束标志10 转向显示jewrite5mov ebx dl 数据保存到缓冲区incebxjmpwrite4write5 movbyteptr ebx 0 显示内容加上结尾标志moveax offsetwritebufcalldispmsgpopedx 恢复寄存器popecxpopebxret 子程序返回writeendp 24 2 共享变量传递参数 子程序和主程序使用同一个变量名存取数据如果变量定义和使用不在同一个程序模块中 需要利用PUBLIC EXTREN声明共享变量传递参数 子程序的通用性较差特别适合在多个程序段间 尤其在不同的程序模块间传递数据 25 例4 17 有符号十进制数输入程序 1 十进制有符号整数转换为补码的算法如下 1 判断输入了正数 还是负数 用一个寄存器记录 2 判断下一个字符是否为有效数码字符无效 提示错误重新输入 并转向 1 字符有效 继续 3 字符有效 减30H转换为二进制数 然后将前面输入的数值乘10 并与刚输入的数字相加得到新的数值 4 判断输入的数据是否超出有效范围超出范围 提示错误重新输入 并转向 1 没有超出范围 则继续 5 重复 2 4 步 输入字符都有效 一直处理完 6 是负数进行求补 转换成补码 否则直接将数值保存 26 例4 17 有符号十进制数输入程序 2 数据段count 10arraydwordcountdup 0 tempdword readbufbyte30dup 0 代码段movecx countmovebx offsetarrayagain callread 调用子程序 输入一个数据moveax temp 获得出口参数mov ebx eax 存放到数据缓冲区addebx 4dececxjnzagain 共享变量传递参数 27 例4 17 有符号十进制数输入程序 3 输入有符号十进制数的子程序readproc 出口参数 变量TEMP 补码表示的二进制数值pusheax 说明 负数用 引导pushebxpushecxpushedxread0 moveax offsetreadbufcallreadmsg 输入一个字符串testeax eaxjzreaderr 没有输入数据 错误cmpeax 12jareaderr 输入超过12个字符 错误 28 例4 17 有符号十进制数输入程序 4 movedx offsetreadbuf EDX指向输入缓冲区xorebx ebx EBX保存结果xorecx ecx ECX为正负标志 0为正 1为负moval edx 取一个字符cmpal 是 继续jzread1cmpal 是 设置 1标志jnzread2movecx 1read1 incedx 取下一个字符moval edx testal al 是结尾0 转向求补码jzread3 29 例4 17 有符号十进制数输入程序 5 read2 cmpal 0 不是0 9之间的数码 错误jbreaderrcmpal 9 jareaderrsubal 30h 是0 9之间的数码 转换imulebx 10 原数值乘10 EBX EBX 10jcreaderr CF 1 乘积溢出 出错movzxeax al 零位扩展 便于相加addebx eax 原数乘10后 与新数码相加cmpebx 80000000h 数据超过231 出错jberead1 继续转换下一个数位 30 例4 17 有符号十进制数输入程序 6 readerr moveax offseterrmsg 显示出错信息calldispmsgjmpread0 read3 testecx ecx 判断是正数还是负数jzread4negebx 是负数 进行求补jmpread5read4 cmpebx 7fffffffh 正数超过231 1 出错jareaderr 31 例4 17 有符号十进制数输入程序 7 read5 movtemp ebx 设置出口参数popedxpopecxpopebxpopeaxret 子程序返回errmsgbyte Inputerror enteragain 0readendp 共享变量传递参数 32 3 堆栈传递参数 主程序将入口参数压入堆栈 子程序从堆栈中取出参数出口参数通常不使用堆栈传递高级语言进行函数调用时提供的参数 实质也利用堆栈传递采用堆栈传递参数是程式化的 它是编译程序处理参数传递 以及汇编语言与高级语言混合编程时的常规方法 33 例4 18 计算有符号数平均值程序 1 数据段arraydword675 354 34 代码段pushlengthofarray 压入数据个数pushoffsetarray 压数组的偏移地址callmean 调用求平均值子程序 出口参数 EAX 平均值 整数部分 addesp 8 平衡堆栈 压入了8个字节数据 calldispsid 显示 堆栈传递参数 34 例4 18 计算有符号数平均值程序 2 计算32位有符号数平均值子程序meanproc 入口参数 顺序压入数据个数和数组偏移地址pushebp 出口参数 EAX 平均值movebp esppushebx 保护寄存器pushecxpushedxmovebx ebp 8 EBX 取出的偏移地址movecx ebp 12 ECX 取出的数据个数xoreax eax EAX保存和值xoredx edx EDX 指向数组元素 堆栈传递参数 35 例4 18 计算有符号数平均值程序 3 mean1 addeax ebx edx 4 求和addedx 1 指向下一个数据cmpedx ecx 比较个数jbmean1 循环cdq 将累加和EAX符号扩展到EDXidivecx 有符号数除法 EAX 平均值popedx 恢复寄存器popecxpopebxpopebpretmeanendp 示意图 36 利用堆栈传递参数 返回 37 4 3 4程序模块 程序分段 子程序等是进行程序模块化开发大型程序时采用的方法子程序模块子程序库库文件包含宏汇编源文件包含 38 1 子程序模块 子程序单独编写 汇编形成目标模块OBJ文件连接时输入子程序模块文件名用共用伪指令PUBLIC和外部伪指令EXTERN声明PUBLIC标识符 标识符 定义标识符的模块使用EXTERN标识符 类型 标识符 类型 调用标识符的模块使用子程序在代码段 与主程序文件采用相同的存储模型 没有开始执行和结束执行点处理好子程序与主程序之间的参数传问题 39 例4 19 数据输入输出程序 1 eg0419s asm 子程序文件 includeio32 incpublicread write mean 子程序共用externtemp dword 外部变量 data 定义的变量集中起来writebufbyte12dup 0 显示缓冲区readbufbyte30dup 0 code 代码段writeprocc 明确采用C语言

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论