控制转移和程序结构.ppt_第1页
控制转移和程序结构.ppt_第2页
控制转移和程序结构.ppt_第3页
控制转移和程序结构.ppt_第4页
控制转移和程序结构.ppt_第5页
已阅读5页,还剩67页未读 继续免费阅读

下载本文档

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

文档简介

第5章 控制转移和程序结构,微型计算机原理及应用,2006年,5.1 目标地址寻址方式 5.2 分支程序结构 5.3 循环程序结构 5.4 子程序结构,5.1 目标地址的寻址方式,程序代码在代码段; CS:指明代码段在主存中的开始位置、即段基地址; EIP:给出将要执行指令的偏移地址; 程序顺序执行,微处理器自动增量EIP;程序控制转移,EIP随之改变; 程序转移到另外的代码段, EIP和CS都将改变; 控制转移类指令:改变EIP(有时CS),即改变程序执行顺序(实现程序控制转移)的指令; 目标地址寻址方式:指明目的地、即目标地址的方法;,目标地址目的地址转移地址,5.1.1 转移范围,1. 段内转移 在当前代码段范围内的程序转移; 不需更改CS,只改EIP(偏移地址); 近转移(Near):16位段是16位近转移NEAR16, 32位段是32位近转移NEAR32; 短转移(Short):转移范围在127-128字节; 2. 段间转移 需要更改CS(段地址)和EIP(偏移地址); 远转移(Far):16位段是32位远转移FAR16, 32位段是48位远转移FAR32;,5.1.2 目标地址寻址方式,1. 相对寻址方式 提供目标地址相对于当前指令指针EIP的位移量; 目标地址(转移后的EIP)当前EIP位移量; 相对寻址都是段内转移,最常用、最灵活; 2. 直接寻址方式 直接提供目标地址; 目标地址(转移后的CS和EIP)指令操作数; 3. 间接寻址方式 由寄存器或存储单元提供跳转地址; 目标地址来自寄存器或存储单元、间接获得; 寄存器间接寻址:用寄存器保存目标地址; 存储器间接寻址:用存储单元保存目标地址;,5.1.3 无条件转移指令JMP,JMP label ;程序转向label标号指定的地址; ;有段内相对寻址,段间直接寻址; JMP reg16/reg32 ;程序转向寄存器指定的地址; ;为寄存器间接寻址; JMP mem16/mem32 ;程序转向存储单元指定的地址; ;为存储器间接寻址;,JMP指令的4种类型,1. 段内转移、相对寻址 标号指明目标地址,指令代码包含位移量; 2. 段内转移、间接寻址 通用寄存器或主存单元包含目标指令的偏移地址; 3. 段间转移、直接寻址 标号包含目标指令的段地址和偏移地址; 4. 段间转移、间接寻址 16位段用双字存储单元包含目标地址; 32位段用3字存储单元包含目标地址;,MASM会根据存储模式等信息自动识别,例题5-1无条件转移程序-1,;数据段 0000 0000 nvar dw ? ;代码段 0010 EB 01 jmp labl1 ;8位位移量 0012 90 nop 0013 B8 FF02 labl1: mov ax,type labl1 0016 E9 0001 jmp near ptr labl2 ;16位位移量 0019 90 nop 001A B8 0020 R labl2: mov ax,offset labl3 ; 001D FF E0 jmp ax 001F 90 nop 0020 B8 002B R labl3: mov ax,offset labl4 0023 A3 0000 R mov nvar,ax 0026 FF 26 0000 R jmp nvar 002A 90 nop,相对短转移,相对近转移,寄存器间接近转移,存储器间接近转移,5.2 分支程序结构 5.2.1 条件转移指令Jcc,Jcc label 根据指定的条件确定程序是否发生转移; 条件满足,发生转移;否则,顺序执行下一条指令; LABEL表示目标地址,采用段内相对寻址方式; 16位CPU:字节位移量(-128+127短转移); 32位CPU:多字节位移量(达到32位的全偏移量); 条件转移指令不影响标志,但要利用标志; cc表示利用标志判断的条件,16种、两类; 单个标志状态作为条件; 两数大小关系作为条件;,转移条件cc:单个标志状态,JZ/JE ZF=1 Jump if Zero/Equal JNZ/JNE ZF=0 Jump if Not Zero/Not Equal JS SF=1 Jump if Sign JNS SF=0 Jump if Not Sign JP/JPE PF=1 Jump if Parity/Parity Even JNP/JPO PF=0 Jump if Not Parity/Parity Odd JO OF=1 Jump if Overflow JNO OF=0 Jump if Not Overflow JC CF=1 Jump if Carry JNC CF=0 Jump if Not Carry,转移条件cc:两数大小关系,JB/JNAE CF=1 Jump if Below/Not Above or Equal JNB/JAE CF=0 Jump if Not Below/Above or Equal JBE/JNA CF=1或ZF=1 Jump if Below/Not Above JNBE/JA CF=0且ZF=0 Jump if Not Below or Equal/Above JL/JNGE SFOF Jump if Less/Not Greater or Equal JNL/JGE SF=OF Jump if Not Less/Greater or Equal JLE/JNG ZFOF或ZF=1 Jump if Less or Equal/Not Greater JNLE/JG SF=OF且ZF=0 Jump if Not Less or Equal/Greater,例题5-2实现指令CBW功能的程序-1,8086指令CBW(等于IA-32指令MOVSX AX,AL) 如果AL最高位为0,则设置AH0; 如果AL最高位为1,则设置AHFFH; 如何判断AL最高位是“0”,还是“1”; 逻辑与“80H”结果为0,AL最高位0;否则是1 运算结果是否为0,零位标志ZF反映; JZ或JNZ指令判断并转移;,例题5-2实现指令CBW功能的程序-2,mov al,bvar ;取出要判断的数据 test al,80h ;测试最高位 jz next1 ;最高位为0(ZF1)转移到标号NEXT1; mov ah,0ffh;最高位为1,顺序执行:设置AHFFH; jmp done ;无条件跳过另一个分支 next1:mov ah,0;最高位为0转移到此执行:设置AH0 done:,不等于零转移,等于零转移,例题5-2实现指令CBW功能的程序-3,mov al,bvar ;取出要判断的数据 cmp al,0 ;与0比较 jns next3 ;最高位为0(SF0),转移到标号NEXT3 mov ah,0ffh;最高位为1,顺序执行:设置AHFFH jmp done ;无条件跳过另一个分支 next3: mov ah,0;最高位为0转移到此执行:设置AH00H done:,符号为正转移,5.2.2 单分支结构程序,条件成立转移,否则顺序执行。,例题5-6求绝对值程序,;数据段 dvar dd 0bd630422h ;有符号数据 result dd ? ;保存绝对值 ;代码段 mov eax,dvar cmp eax,0 ;比较EAX与0 jge nonneg ;条件满足:AX0,转移 neg eax ;条件不满足:AX0,为负数,需求补得正值 nonneg: mov result,eax ;分支结束,保存结果,IF-THEN结构,5.2.3 双分支结构程序,非A即B,例题5-8显示数据最高位程序-1,;数据段 dvar dd 0bd630422h ;有符号数据 ;代码段 mov ebx,dvar shl ebx,1 ;EBX最高位移入CF标志 jc one ;CF1,最高位为1,转移 mov dl,0 ;CF0,最高位为0:DL0 jmp two ;一定要跳过另一个分支体 one: mov dl,1 ;DL1 two: mov ah,2 int 21h ;显示,在屏幕上显示dvar变量的最高位的数(0、1)。,5.2.4 多分支结构程序,5.3 循环程序结构设计,循环结构程序构成: 循环初始化 循环体 循环控制,循环程序结构,循环指令,LOOP label ;ECXECX1;若ECX0,循环到LABEL; ;否则,顺序执行 JECXZ label ;ECX0,转移;否则顺序执行 JCXZ label ;CX0,转移;否则顺序执行 32位段使用ECX(16位段使用CX)作为计数器 目标地址采用相对短转移,例题5-11数组求和程序-1,.data array dw 123,244,2467,335,5433 mov ecx,lengthof array xor eax,eax ;求和初值为0 mov ebx,eax ;数组指针为0 again: movzx edx,arrayebx*(type array) add eax,edx ;求和 inc ebx loop again mov sum,eax ;保存结果,例题5-11数组求和程序-2,mov ecx,lengthof array xor eax,eax ;求和初值为0 jecxz done ;数组元素为0,不再进行求和 mov ebx,eax ;数组指针为0 again: movzx edx,arrayebx*(type array) add eax,edx ;求和 inc ebx loop again done: mov sum,eax ;保存结果,循环控制,计数控制循环 通过次数控制循环,常用LOOP指令实现 条件控制循环 根据条件决定是否进行循环,需用条件转移指令 “先判断、后循环”的循环程序结构 循环控制在进入循环之前进行 “先循环、后判断”的循环程序结构 循环之后进行循环条件判断,排序程序,例题5-13查找字符串特定字符个数程序,String db You are wellcom!,0 Space dd ? mov esi,offset string xor ebx,ebx ;EBX用于记录空格数 again: mov al,esi cmp al,0 jz done ;结束标志 cmp al,20h ;空格的ASCII码是20H jne next ;不相等、不是空格,转移 inc bx ;相等、是空格,个数加1 next: inc esi jmp again ;继续循环 done: mov space,ebx ;保存结果,条件控制循环,5.4 子程序结构程序设计,子程序结构,子程序:与主程序分开的、完成特定功能的一段程序。 当主程序(调用程序)执行调用指令CALL调用子程序。 子程序(被调用程序)执行返回指令RET返回主程序,子程序调用指令CALL,CALL指令用在主程序中,实现子程序的调用; 分成段内调用(近调用)和段间调用(远调用); 目标地址采用相对寻址、直接寻址或间接寻址; 入栈返回地址:将CALL下一条指令的地址压入堆栈; 16位段段内:16位偏移地址,段间:再加16位段地址 32位段段内:32位偏移地址,段间:再将16位段选择器零位扩展为32位保存到堆栈; 指令调用形式 CALL label ;入栈返回地址,调用标号指定的子程序; CALL reg16/reg32 ;入栈返回地址,调用寄存器指定地址的子程序; CALL mem16/mem32 ;入栈返回地址,调用存储单元指定地址的子程序;,子程序返回指令RET,RET指令用在子程序结束,实现返回主程序 RET ;无参数返回:出栈返回地址 RET i16 ;有参数返回:出栈返回地址,ESPESPi16,MASM会根据存储模式等信息确定子程序的远近调用,并相应产生返回指令,子程序(过程)定义,格式: 过程名 PROC ;过程体 过程名 ENDP PROC后面可加参数:NEAR或FAR 简化段定义源程序格式中,通常不需指定; 微型、小型和紧凑存储模式:默认属性NEAR; 中型、大型和巨型存储模式:默认属性FAR;,子程序设计,利用过程定义,获得子程序名和调用属性; CALL指令调用子程序,RET指令返回主程序; 压入和弹出操作要成对使用,保持堆栈平衡; 子程序的开始保护寄存器,返回前相应恢复; 子程序安排在代码段的主程序之外; 子程序允许嵌套; 子程序可与主程序共用一个数据段,也可具有独立数据段;,最好有完整的注释,难点是参数传递,例:,将一个字(16进制)分别转换为ASCII码送显示(要转换的字放在WVAR变量中)。,子程序的参数传递,主程序与子程序间通过参数传递建立联系 入口参数(输入参数):主程序子程序 出口参数(输出参数):子程序主程序 参数的具体内容 数据本身(传递数值) 数据的存储地址(传递地址,传递引用) 参数传递方法:寄存器、变量或堆栈;,寄存器传递参数,最简单和常用的参数传递方法; 把参数存于约定的寄存器; 少量数据直接传递数值; 大量数据只能传递地址; 带有出口参数的寄存器不能保护和恢复; 带有入口参数的寄存器可以保护、也可以不保护,但最好能够保持一致;,编写程序实现下列功能: 将变量Bvar中5个字节的压缩BCD码数据,分别转换为分离BCD数,并存入变量BCDA中。 (采用寄存器传递参数),例题5-18有符号十进制数输入程序-1,算法如下: 首先判断输入正数还是负数,并用一个寄存器记录下来; 接着输入09数字(ASCII码),并减30H转换为二进制数; 然后将前面输入的数值乘10,并与刚输入的数字相加得到新的数值; 重复2、3步,直到输入一个非数字字符结束; 如果是负数进行求补,转换成补码;否则直接将数值保存,例题5-18有符号十进制数输入程序-2,mov ecx,count mov ebx,offset array again: call readsid ;输入一个数据 mov ebx,eax ;存放出口参数 add ebx,4 call dpcrlf ;光标回车换行 loop again,例题5-18有符号十进制数输入程序-3,readsid proc ;输入有符号十进制数子程序 push ebx ;说明:负数用“-”引导 push ecx push edx xor ebx,ebx ;EBX保存结果 xor ecx,ecx ;ECX为正负标志:0为正,-1为负,例题5-18有符号十进制数输入程序-4,mov ah,1 ;输入一个字符 int 21h cmp al,+ ;是“”,继续输入字符 jz rsid1 cmp al,- ;是“”,设置1标志 jnz rsid2 mov ecx,-1,例题5-18有符号十进制数输入程序-5,rsid1: mov ah,1 ;继续输入字符 int 21h rsid2: cmp al,0 ;不是09之间的字符,则输入数据结束 jb rsid3 cmp al,9 ja rsid3 sub al,30h ;是09之间的字符,则转换为二进制数,例题5-18有符号十进制数输入程序-6,imul ebx,10 ;数值乘10:EBXEBX10 movzx eax,al add ebx,eax ;与新输入数值相加 jmp rsid1 ;继续输入字符 rsid3: cmp ecx,0 ;是负数,进行求补 jz rsid4 neg ebx rsid4: mov eax,ebx ;设置出口参数 pop edx pop ecx pop ebx ret ;子程序返回 readsid endp,例题5-18有符号十进制数输入程序-7,dpcrlf proc ;光标回车换行子程序 push ax push dx mov ah,2 mov dl,0dh int 21h mov ah,2 mov dl,0ah int 21h pop dx pop ax ret dpcrlf endp,共享变量传递参数,子程序和主程序使用同一个变量名存取数据 变量定义和使用不在同一个源程序中,需要利用PUBLIC、EXTREN声明 共享变量传递参数,子程序的通用性较差 特别适合在多个程序段间、尤其在不同的程序模块间传递数据,例题5-19有符号十进制数输出程序-1,算法如下: 首先判断数据是零、正数或负数,是零显示“0”退出; 是负数,显示“”,求数据的绝对值; 接着数据除以10,余数加30H转换为ASCII码压入堆栈; 重复第3步,直到商为0结束; 依次从堆栈弹出各位数字,进行显示,例题5-19有符号十进制数输出程序-2,mov ecx,count mov ebx,0 again: mov eax,arrayebx*4 mov dtemp,eax ;入口参数存放到共享变量 call dispsid ;调用子程序显示一个数据 inc ebx call dpcrlf ;光标回车换行 loop again,例题5-19有符号十进制数输出程序-3,dispsid proc ;显示有符号十进制数子程序 push eax ;入口参数:共享变量DTEMP push ebx push edx mov eax,dtemp ;取出显示数据 test eax,eax ;判断数据是零、正数或负数 jnz dsid1 mov dl,0 ;是零,显示“0”后退出 mov ah,2 int 21h jmp dsid5,例题5-19有符号十进制数输出程序-4,dsid1: jns dsid2 ;是负数,显示“-” mov ebx,eax ;EAX数据暂存于EBX mov dl,- mov ah,2 int 21h mov eax,ebx neg eax ;数据求补(绝对值),例题5-19有符号十进制数输出程序-5,dsid2: mov ebx,10 push bx ;10压入堆栈,作为退出标志 dsid3: cmp eax,0 ;数据(商)为零,转向显示 jz dsid4 sub edx,edx ;扩展被除数EDX.EAX div ebx ;数据除以10:EDX.EAX10 add dl,30h ;余数(09)转换为ASCII码 push dx ;数据先低位后高位压入堆栈 jmp dsid3,例题5-19有符号十进制数输出程序-6,dsid4: pop dx ;数据先高位后低位弹出堆栈 cmp dl,10 ;是结束标志10,则退出 je dsid5 mov ah,2 ;进行显示 int 21h jmp dsid4 dsid5: pop edx pop ebx pop eax ret ;子程序返回 dispsid endp,堆栈传递参数,主程序将入口参数压入堆栈,子程序从堆栈中取出参数 子程序将出口参数压入堆栈,主程序弹出堆栈取得它们 采用堆栈传递参数是程式化的,它是编译程序处理参数传递、以及汇编语言与高级语言混合编程时的常规方法,例题5-20计算有符号数平均值程序-1,算法如下: 被加数进行符号扩展 求和 除以数据个数得到平均值 32位有符号数扩展到64位,32位表示数据个数(最大232 ) ,不会溢出,例题5-20计算有符号数平均值程序-2,mov eax,count push eax ;压入数据个数(0表示232个) mov ebx,offset array push ebx ;压入缓冲区的偏移地址 call mean ;调用子程序,求平均值 add esp,8 ;平衡堆栈 mov dmed,eax ;保存出口参数,例题5-20计算有符号数平均值程序-3,mean proc ;计算有符号数平均值 push ebp mov ebp,esp push ebx ;保护寄存器 push ecx push edx push esi push edi mov ebx,ebp+6 ;从堆栈取偏移地址 mov ecx,ebp+10 ;从堆栈取数据个数,堆栈示意图,例题5-20计算有符号数平均值程序-4,xor esi,esi ;ESI保存求和的低32位值 mov edi,esi ;EDI保存求和的高32位值 mean1: mov eax,ebx ;取出一个数据EAX cdq ;符号扩展EDX.EAX add esi,eax ;求和低32位 adc edi,edx ;求和高32位 add ebx,4 ;指向下一个数据 dec ecx ;数据个数减少一个 jnz mean1 ;循环 mov eax,esi ;累加和在EDX.EAX mov edx,edi,例题5-20计算有符号数平均值程序-5,mov ecx,ebp+10 ;数据个数在CX idiv ecx ;有符号数除法,EAX平均值(EDX余数) pop edi ;恢复寄存器 pop esi pop edx pop ecx pop ebx pop ebp ret mean endp,宏汇编,宏(Macro):具有宏名的一段汇编语句序列 宏需要先定义 宏名 MACRO 形参表 ;宏定义体 ENDM 然后程序中进行宏调用 宏名 实体参数 宏定义体的标号必须用LOCAL伪指令声明 LOCAL 标号1,标号2,例题5-21十六进制数输入程序-1,;宏定义 dispmsg macro message ;message是形式参数 push ax push dx mov ah,9 lea dx,message int 21h pop dx pop ax endm,例题5-21十六进制数输入程序-2,asctoh macro local asctoh1,asctoh2 cmp al,9 jbe asctoh1 ;小于等于9,是09,只需减去30H cmp al,a jb asctoh2 ;大于9小于a,是AF,还要减7 sub al,20h ;大于等于a,是af,再减去20H asctoh2: sub al,7 asctoh1: sub al,30h endm,例题5-21十六进制数输入程序-3,;数据段 msg db Please input,13,10,$ wvar dw ? ;代码段 dispmsg msg ;提示输入,例题5-21十六进制数输入程序-4,mov cx,4 mov bx,0 ;BX保存转换后的结果 again: mov ah,6 ;输入字符但不显示 mov dl,0ffh int 21h jz again ;没有输入字符继续,功能调用,例题5-21十六进制数输入程序-5,cmp al,0 ;测试是否是合法字符 jb again ;没有输入合法字符,重新输入 cmp al,9 jbe next ;输入合法字符就显示 cmp al,A jb again cmp al,F jbe next cmp al,a jb again cmp al,f ja again ;测试结束,例题5-21十六进制数输入程序-6,next: mov ah,6 ;显示输入字符 mov dl,al int 21h asctoh ;转换为十六进制数 shl bx,4 ;将上次输入左移二进制4位 add bl,al ;加上本次输入的数码 loop again mov wvar,bx,宏展开,宏与子程序,都简化源程序的书写,但有本质区别 宏调用 在汇编时复制宏定义语句 执行时不存在控制的转移与返回 没有减少汇编后的目标代码 执行速度也没有改变 子程序调用 在执行时控制转移到子程序 子程序没有被复制,汇编后的目标代码较短 会影响程序执行速度 宏与子程序各有特点,根据具体问题选择使用 当程序段较短或要求较快执行时,应选用宏 当程序段较长或为减小目标代码时,要选用子程序,源文件包含,INCLUDE 文件名 将INCLUDE伪指令指定的文本文件内容插入源程序 可以包含任何文本文件 一些常用的或有价值的宏定义存放在.MAC宏定义文件 各种常量定义、声明语句等组织在.INC包含文件 常用的子程序形成.ASM汇编语言源文件 利用INCLUDE伪指令包含其他文件,其实质仍然是一个源程序,只不过是分在了几个文件书写 include eg521e.mac ;宏定义文件EG321E.MAC ;只对主程序文件进行汇编、连接,举例,子程序模块,子程序单独编写,汇编形成目标模块OBJ文件 连接时输入子程序模块文件名 用共用伪指令PUBLIC和外部伪指令EXTERN声明 PUBLIC 标识符 ,标识符 ;定义标识符的模块使用 EXTERN 标识符:类型 ,标识符:类型 ;调用标识符的模块使用 子程序在代码段,没有开始执行和结束执行点 采用简化

温馨提示

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

评论

0/150

提交评论