综合应用第2章硬指令和第3章伪指令,第4章从程序结构角_第1页
综合应用第2章硬指令和第3章伪指令,第4章从程序结构角_第2页
综合应用第2章硬指令和第3章伪指令,第4章从程序结构角_第3页
综合应用第2章硬指令和第3章伪指令,第4章从程序结构角_第4页
综合应用第2章硬指令和第3章伪指令,第4章从程序结构角_第5页
已阅读5页,还剩65页未读 继续免费阅读

下载本文档

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

文档简介

1、1综合应用第2章硬指令和第3章伪指令,第4章从程序结构角度展开程序设计,重点掌握:分支结构程序设计循环结构程序设计子程序结构程序设计2l顺序程序结构是指完全按顺序逐条执行的指令序列,这在程序段中是大量存在的,是最基本、最常见的程序结构,但作为完整的程序则很少见.model small.stack.dataXdw 5Ydw 6Zdw 7 .code.startupmov ax,Xadd ax,Yadd ax,Zmov dl,al;入口参数:DLALmov ah,2;02号DOS功能调用int 21h;显示一个ASCII码字符.exit 0end4l分支程序根据条件是真或假决定执行与否l判断的条件

2、是各种指令,如CMP、TEST等执行后形成的状态标志l转移指令Jcc和JMP可以实现分支控制;还可以采用MASM 6.x提供的条件控制伪指令实现l条件成立跳转,否则顺序执行分支语句体;注意选择正确的条件转移指令和转移目标地址cmp ax,0jns nonneg;分支条件:AX0neg ax;条件不满足,求补nonneg: mov result,ax;条件满足例:计算AX的绝对值条件成立跳转执行第2个分支语句体,否则顺序执行第1个分支语句体。注意第1个分支体后一定要有一个JMP指令跳到第2个分支体后shl bx,1;BX最高位移入CFjc one ;CF1,即最高位为1,转移mov dl,0 ;

3、CF0,即最高位为0,DL0jmp two;一定要跳过另一个分支体one: mov dl,1;DL1two: mov ah,2int 21h;显示mov dl,0;DL0shl bx,1;BX最高位移入CFjnc two ;CF0,最高位为0,转移mov dl,1 ;CF1,最高位为1,DL1two: mov ah,2int 21h;显示l多个条件对应各自的分支语句体,哪个条件成立就转入相应分支体执行。多分支可以化解为双分支或单分支结构的组合,例如: or ah,ah;等效于cmp ah,0 jz function0;ah0,转向function0 dec ah;等效于cmp ah,1 jz

4、function1;ah1,转向function1 dec ah;等效于cmp ah,2 jz function2;ah2,转向function211AH=0fuction0YNAH=1fuction1YNAH=2fuction2YN12l需要在数据段事先安排一个按顺序排列的转移地址表l输入的数字作为偏移量。因为只有2个字节16位偏移地址,所以偏移量需要乘2l关键是要理解间接寻址方式JMP指令地址表地址表分支分支1地址地址分支分支2地址地址.Table db disp1, disp2, disp3, disp4, .datamsgdb Input number(18):,0dh,0ah,$ms

5、g1db Chapter 1 : .,0dh,0ah,$msg2db Chapter 2 : .,0dh,0ah,$.msg8db Chapter 8 : . ,0dh,0ah,$tabledw disp1,disp2,disp3,disp4dw disp5,disp6,disp7,disp8;取得各个标号的偏移地址此处等同于此处等同于 offset disp1start1:mov dx,offset msg;提示输入数字mov ah,9int 21hmov ah,1;等待按键int 21hcmp al,1;数字 8?ja start1and ax,000fh;将ASCII码转换成数字dec

6、axshl ax,1;等效于add ax,axmov bx,axjmp tablebx;(段内)间接转移:IPtable+bxstart2:mov ah,9int 21h.exit 0disp1:mov dx,offset msg1;处理程序1jmp start2.可以改为可以改为 call tablebx对应修改为对应修改为 ret16l循环结构一般是根据某一条件判断为真或假来确定是否重复执行循环体l循环指令和转移指令可以实现循环控制;还可以采用MASM 6.x提供的循环控制伪指令实现17 结束结束 初始化初始化 循环的初始状态循环的初始状态 循环体循环体 循环的工作部分循环的工作部分及修改

7、部分及修改部分 计数控制循环计数控制循环条件控制循环条件控制循环修改部分修改部分控制条件控制条件Y YN N.model small.stack.datasumdw ?.code.startupxor ax,ax;被加数AX清0mov cx,100again:add ax,cx;从100,99,.,2,1倒序累加loop againmov sum,ax;将累加和送入指定单元.exit 0end 计数控制循环计数控制循环,循环次数固定循环次数固定 mov ah,1;从键盘输入一个字符 int 21h mov bl,al;BLAL字符的ASCII码 ;DOS功能会改变AL内容,故字符ASCII码存

8、入BL mov ah,2 mov dl,:;显示一个分号,用于分隔 int 21h mov cx,8;CX8(循环次数)again: shl bl,1;左移进CF,从高位开始显示mov dl,0;MOV指令不改变CFadc dl,30h;DL030HCF ;CF若是0,则DL0;若是1,则DL1mov ah,2int 21h;显示loop again;CX减1,如果CX未减至0,则循环mov bx,offset stringagain:mov al,bx;取一个字符or al,al;是否为结尾符0jz done;是,退出循环cmp al,A;是否为大写AZjb nextcmp al,Zja n

9、extor al,20h ;是,转换为小写字母(使D5=1)mov bx,al;仍保存在原位置next:inc bxjmp again;继续循环done:.exit 0 条件控制循环条件控制循环,利用标志退利用标志退出出大小写字母仅大小写字母仅 D D5 5位不同位不同21l“冒泡法”是一种排序算法,不是最优的算法,但它易于理解和实现l冒泡法从第一个元素开始,依次对相邻的两个元素进行比较,使前一个元素不大于后一个元素;将所有元素比较完之后,最大的元素排到了最后;然后,除掉最后一个元素之外的元素依上述方法再进行比较,得到次大的元素排在后面;如此重复,直至完成就实现元素从小到大的排序l这需要一个双

10、重循环程序结构序号 数比比 较较 遍遍 数数1234 1 32 2 85 3 16 4 15 5 8321615885161583285158163285815163285mov cx,count;CX数组元素个数dec cx;元素个数减1为外循环次数outlp: mov dx,cx;DX内循环次数mov bx,offset arrayinlp:mov al,bx;取前一个元素cmp al,bx+1;与后一个元素比较jna next;前一个不大于后一个元素,则不进行交换xchg al,bx+1;否则,进行交换mov bx,alnext:inc bx;下一对元素dec dxjnz inlp;内循

11、环尾loop outlp;外循环尾 计数控制双重循环计数控制双重循环;现有一个以$结尾的字符串,要求剔除其中的空格.datastringdb Let us have a try !,$.code.startupmov si,offset stringoutlp:cmp byte ptr di,$ ;外循环,先判断后循环jz done;为$结束cmp byte ptr si, ;检测是否是空格jnz next;不是空格继续循环mov di,si;是空格,进入剔除空格分支;该分支是循环程序段inlp:inc dimov al,di;前移一个位置mov di-1,alcmp byte ptr di,

12、$;内循环,先循环后判断jnz inlpjmp outlpnext:inc si;继续对后续字符进行处理jmp outlpdone:.exit 0;结束 条件控制双重循环条件控制双重循环26l把功能相对独立的程序段单独编写和调试,作为一个相对独立的模块供程序使用,就形成子程序l子程序可以实现源程序的模块化,可简化源程序结构,可以提高编程效率格式格式: :过程名过程名 proc near|farproc near|far.过程名过程名endpendpl过程名(子程序名)为符合语法的标识符NEAR属性(段内近调用)的过程只能被相同代码段的其他程序调用FAR属性(段间远调用)的过程可以被相同或不同代

13、码段的程序调用l对简化段定义格式,在微型、小型和紧凑存储模式下,过程的缺省属性为near;在中型、大型和巨型存储模式下,过程的缺省属性为farl对完整段定义格式,过程的缺省属性为nearl用户可以在过程定义时用near或far改变缺省属性subnameproc;具有缺省属性的subname过程push ax ;保护寄存器:顺序压入堆栈push bx ;ax/bx/cx仅是示例push cx;过程体,程序的主要功能pop cx ;恢复寄存器:逆序弹出堆栈pop bxpop axret;过程返回subnameendp;过程结束;子程序功能:实现光标回车换行dpcrlfproc;过程开始push a

14、x;保护寄存器AX和DXpush dxmov dl,0dh;显示回车mov ah,2int 21hmov dl,0ah;显示换行mov ah,2int 21hpop dx;恢复寄存器DX和AXpop axret;子程序返回dpcrlfendp;过程结束ALdispproc;实现al内容的显示push ax;过程中使用了AX、CX和DXpush cxpush dxpush ax;暂存axmov dl,al;转换al的高4位mov cl,4shr dl,clor dl,30h;al高4位变成3cmp dl,39hjbe aldisp1add dl,7;是0Ah0Fh,还要加上7aldisp1:mo

15、v ah,2;显示int 21hpop dx;恢复原ax值到dxand dl,0fh;转换al的低4位or dl,30hcmp dl,39hjbe aldisp2add dl,7aldisp2:mov ah,2;显示int 21hpop dxpop cxpop axret;过程返回ALdispendp.;主程序mov bx,offset array;调用程序段开始mov cx,countdisplp:mov al,bxcall ALdisp;调用显示过程mov dl,;显示一个逗号,分隔数据mov ah,2int 21hinc bxloop displp;调用程序段结束.exit 0.;过程定

16、义endHTOASCproc;将AL低4位表达的一位16进制数转换为ASCII码and al,0fhcmp al,9jbe htoasc1add al,37h;是0AH0FH,加37Hret;子程序返回htoasc1:add al,30h;是09,加30Hret;子程序返回HTOASCendp34l入口参数(输入参数):主程序提供给子程序l出口参数(输出参数):子程序返回给主程序l参数的形式: 数据本身(传值) 数据的地址(传址)l传递的方法: 寄存器 变量 堆栈35l子程序计算数组元素的“校验和”l校验和是指不记进位的累加入口参数:数组的逻辑地址(传址)元素个数(传值)出口参数:求和结果(传

17、值)l把参数存于约定的寄存器中,可以传值,也可以传址。l子程序对带有出口参数的寄存器不能保护和恢复(主程序视具体情况进行保护)l子程序对带有入口参数的寄存器可以保护,也可以不保护;但最好一致入口参数:CX元素个数,DS:BX数组的段地址:偏移地址出口参数:AL校验和.startup ;设置入口参数(含有DS数组的段地址)mov bx,offset array ;BX数组的偏移地址mov cx,count;CX数组的元素个数call checksuma;调用求和过程mov result,al;处理出口参数.exit 0checksumaprocxor al,al;累加器清0suma:add al

18、,bx;求和inc bx;指向下一个字节loop sumaretchecksumaendpendl主程序和子程序直接采用同一个变量名共享同一个变量,实现参数的传递l不同模块间共享时,需要声明入口参数:count元素个数,array数组名(含段地址:偏移地址)出口参数:result校验和;主程序 call checksumb;子程序checksumbprocpush axpush bxpush cxxor al,al;累加器清0mov bx,offset array;BX数组的偏移地址mov cx,count;CX数组的元素个数sumb:add al,bx;求和inc bxloop sumbmo

19、v result,al ;保存校验和pop cxpop bxpop axretchecksumbendpl主程序将子程序的入口参数压入堆栈,子程序从堆栈中取出参数l子程序将出口参数压入堆栈,主程序弹出堆栈取得它们入口参数:顺序压入偏移地址和元素个数出口参数:AL校验和.startupmov ax,offset arraypush axmov ax,countpush axcall checksumcadd sp,4mov result,al.exit 0 要注意堆栈的分配情况,保证参数存取正确、子程序正要注意堆栈的分配情况,保证参数存取正确、子程序正确返回,并保持堆栈平衡确返回,并保持堆栈平衡

20、checksumcprocpush bpmov bp,sp;利用BP间接寻址存取参数push bxpush cxmov bx,bp+6 ;SS:BP+6指向偏移地址mov cx,bp+4 ;SS:BP+4指向元素个数xor al,alsumc:add al,bx inc bxloop sumcpop cxpop bxpop bpretchecksumcendp45 主程序实现平衡堆栈:主程序实现平衡堆栈: add sp,n 子程序实现平衡堆栈:子程序实现平衡堆栈: ret n46子程序内包含有子程序的调用就是子程序嵌套没有什么特殊要求ALdispprocpush axpush cx;实现al内

21、容的显示push ax;暂存axmov cl,4shr al,cl;转换al的高4位call htoasc;子程序调用(嵌套)pop ax;转换al的低4位call htoasc;子程序调用(嵌套)pop cxpop axretALdispendp;将AL低4位表达的一位16进制数转换为ASCII码HTOASCprocpush axpush bxpush dxmov bx,offset ASCII;BX指向ASCII码表and al,0fh;取得一位16进制数xlat CS:ASCII;换码:ALCS:BXAL,注意数据在代码段CS mov dl,al;显示mov ah,2int 21hpop

22、 dxpop bxpop axret;子程序返回;子程序的数据区ASCIIdb 30h,31h,32h,33h,34h,35h,36h,37hdb 38h,39h,41h,42h,43h,44h,45h,46hHTOASCendp 这是一个具有局部变量的子程序。因为数据区与子程序都在代码段,所以利用了换码指令XLAT的另一种助记格式(写出指向缓冲区的变量名,目的是便于指明段超越前缀)。串操作MOVS、LODS和CMPS指令也可以这样使用,以便使用段超越前缀 除采用段超越方法外,子程序与主程序的数据段不同时,我们还可以通过修改DS值实现数据存取;但需要保护和恢复DS寄存器50l当子程序直接或间接

23、地嵌套调用自身时称为递归调用,含有递归调用的子程序称为递归子程序l递归子程序必须采用寄存器或堆栈传递参数,递归深度受堆栈空间的限制例:求阶乘 N!= N*(N-1)! 当N0 1 当N=0.model small.stack 256.dataNdw 3resultdw ?.code.startupmov bx,Npush bx;入口参数:Ncall fact;调用递归子程序pop result;出口参数:N!.exit 0;计算N!的近过程;入口参数:压入 N;出口参数:弹出 N!fact procpush axpush bpmov bp,spmov ax,bp+6 ;取入口参数 Ncmp a

24、x,0jne fact1;N0,N!N(N-1)!inc ax;N0,N!1jmp fact2fact1:dec ax;N-1push axcall fact;调用递归子程序求(N-1)!pop axmul word ptr bp+6 ;求 N(N-1)!fact2:mov bp+6,ax ;存入出口参数 N!pop bppop axretfactendp调用时进栈调用时进栈返回时出栈返回时出栈13!2!1!55l子程序的重入是指子程序被中断后又被中断服务程序所调用,能够重入的子程序称为可重入子程序。在子程序中,注意利用寄存器和堆栈传递参数和存放临时数据,而不要使用固定的存储单元(变量),就能

25、够实现重入。l子程序的重入不同于子程序的递归。重入是被动地进入,而递归是主动地进入;重入的调用间往往没有关系,而递归的调用间却是密切相关的。递归子程序也是可重入子程序。56 首先判断输入为正或负数,并用一个寄存器记录 接着输入09数字(ASCII码),并减30H转换为二进制数 然后将前面输入的数值乘10,并与刚输入的数字相加得到新的数值 重复、步,直到输入一个非数字字符结束 负数进行求补,转换成补码;否则直接保存数值l本例采用16位寄存器表达数据,所以只能输入32767732768间的数值l但该算法适合更大范围的数据57l子程序从键盘输入一个有符号十进制数;子程序还包含将ASCII码转换为二进

26、制数的过程l输入时,负数用“”引导,正数直接输入或用“”引导l子程序用寄存器传递出口参数,主程序调用该子程序输入10个数据.datacount= 10arraydw count dup(0);预留数据存储空间.code.startupmov cx,countmov bx,offset arrayagain:call read;调用子程序输入一个数据mov bx,ax;将出口参数存放缓冲区inc bxinc bxcall dpcrlf;调用子程序,光标回车换行以便输入下一个数据loop again.exit 0;输入有符号10进制数的通用子程序;出口参数:AX补码表示的二进制数值;说明:负数用“

27、”引导,正数用“”引导或直接输入;数据范围是3276732768readprocpush bxpush cxpush dxxor bx,bx;BX保存结果xor cx,cx;CX为正负标志,0为正,1为负mov ah,1;输入一个字符int 21hcmp al,+;是“”,继续输入字符jz read1cmp al,-;是“”,设置1标志jnz read2;非“”和“”,转read2mov cx,-1read1:mov ah,1;继续输入字符int 21hread2:cmp al,0;不是09之间的字符,则输入数据结束jb read3cmp al,9ja read3sub al,30h;是09之

28、间的字符,则转换为二进制数;利用移位指令,实现数值乘10:BXBX10shl bx,1mov dx,bxshl bx,1shl bx,1add bx,dx;bx内容乘10mov ah,0add bx,ax;已输入数值乘10后,与新输入数值相加jmp read1;继续输入字符read3:cmp cx,0jz read4neg bx;是负数,进行求补read4:mov ax,bx;设置出口参数pop dxpop cxpop bxret;子程序返回readendp;使光标回车换行的子程序dpcrlfproc.;省略dpcrlfendpend63 首先判断数据是零、正数或负数,是零显示“0”退出 是负数,显示“”,求数据的绝对值; 接着数据除以10,余数加30H转换为ASCII码压入堆栈 重复步,直到余数为0结束 依次从堆栈弹出各位数字,进行显示l本例采用16位寄存器表达数据,所以只能显示32767732768间的数值l但该算法适合更大范围的数据64l子程序在屏幕上显示一个有符号十进制数;子程序还包含将二进制数转换为ASCII码的过程l显示时,负数用“”引导,正数直接输出、没有前导字符l子程序的入口参数用共享变量传递,主程序调用该子程序显示10个数据.datacount= 10arraydw 1234,-1234,0,

温馨提示

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

评论

0/150

提交评论