汇编语言程序设计(40).ppt_第1页
汇编语言程序设计(40).ppt_第2页
汇编语言程序设计(40).ppt_第3页
汇编语言程序设计(40).ppt_第4页
汇编语言程序设计(40).ppt_第5页
已阅读5页,还剩96页未读 继续免费阅读

下载本文档

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

文档简介

第7章 汇编语言程序设计,汇编语言是一种以处理器指令系统为基础的低级程序设计语言,它采用助记符表达指令操作码,采用标识符号表示指令操作数 利用汇编语言编写程序的主要优点是可以直接、有效地控制计算机硬件,因而容易创建代码序列短小、运行快速的可执行程序 在有些应用领域,汇编语言的作用是不容置疑和无可替代的 汇编程序设计的过程是与其他高级语言程序设计大致相同,第7章:教学重点,汇编语言源程序格式(程序结构) 汇编语言常用伪指令的使用方法 常量、变量和标号 汇编语言程序设计方法 顺序程序设计 分支程序设计 循环程序设计 子程序设计,7.1 汇编语言程序结构,汇编语言源程序是由语句序列组成的,语句序列应包括: 数据(程序要处理的对象); 处理数据的实体(程序); 承上启下的记录。 8086/8088 汇编语言程序必须具备: 代码段(处理数据的对象) 数据段(定义加工处理对象) 堆栈段,标准汇编语言程序框架,定义堆栈段 STACK_SEG SEGMENT PARA STACK STACK ;定义堆栈深度与堆栈段变量 STACK_SEG ENDS 定义数据段 DATA_SEG SEGMENT PARA PUBLIC DATA ;定义变量 DATA_SEG ENDS,data1 db 32h, 38h, 30h, 36h, 37h,$ data2 db 33h, 35h, 33h, 38h, 32h, $,sta db 100 dup (?),通常,一个源程序都有大体相同的结构或框架,下面给出一个源程序的框架结构,该程序是在PC-DOS环境下运行的。,定义代码段 CODE_SEG SEGMENT PARA PUBLIC CODE MAIN PROC FAR ASSUME CS:CODE_SEG, DS:DATA_SEG ASSUME SS:STACK_SEG START: PUSH DS MOV AX,0 PUSH AX MOV AX,DATA_SEG MOV DS,AX ;主过程内容 RET MAIN ENDP PROC_A PROC NEAR ;子过程A内容,A为主过程调用 PROC_A ENDP ;其他过程内容 CODE_SEG ENDS END START,1 汇编语言源程序格式,完整的汇编语言源程序由段组成 一个汇编语言源程序可以包含若干个代码段、数据段、附加段或堆栈段,段与段之间的顺序可随意排列 需独立运行的程序必须包含一个代码段,并指示程序执行的起始点,一个程序只有一个起始点 所有的可执行性语句必须位于某一个代码段内,说明性语句可根据需要位于任一段内 通常,程序还需要一个堆栈段,源程序由语句序列构成,1. 汇编语言的语句的类型和组成,执行性语句执行性语句用于表达处理器指令(也称为硬指令),汇编后对应一条指令代码。由处理器指令组成的代码序列是程序设计的主体 标号: 硬指令助记符 操作数,操作数 ;注释 说明性语句说明性语句用于表达伪指令,指示源程序如何汇编、变量怎样定义、过程怎么设置等 名字 伪指令助记符 参数,参数, ;注释,2. 硬指令与伪指令,硬指令(Instruction)使CPU产生动作、并在程序执行时才处理的指令 硬指令就是第6章学习的处理器指令,与具体的处理器有关、与汇编程序无关 伪指令(Directive)不产生CPU动作、在程序执行前由汇编程序处理的说明性指令 伪指令与具体的处理器类型无关,但与汇编程序有关。不同版本的汇编程序支持不同的伪指令,硬指令和伪指令采用易于记忆的符合表达,这就是助记符,3. 标号、名字与标识符,标号是反映硬指令位置(逻辑地址)和属性的标识符,后跟一个冒号分隔 名字是反映伪指令位置(逻辑地址)和属性的标识符,后跟空格或制表符分隔,没有冒号 标识符(Identifier)一般最多由31个字母、数字及规定的特殊符号(如 _、$、?、)组成,不能以数字开头。默认情况下,汇编程序不区别标识符中的字母大小写 一个源程序中,每个标识符的定义是唯一的,还不能是汇编语言采用的保留字,名字和标号的属性,名字和标号是用户自定义的标识符。名字指向一条伪指令,标号指向一条硬指令。名字和标号一经使用便具有两类属性: 逻辑地址名字和标号对应存储单元的逻辑地址,含有段地址和偏移地址; 类型变量名的类型可以是BYTE(字节)、WORD(字)和DWORD(双字)等;标号、段名、子程序名的类型可以是NEAR(近)和FAR(远),分别表示段内或段间调用 汇编程序提供有关的操作符,以便获取这些属性值,地址操作符,地址操作符取得名字或标号的段地址和偏移地址,类型操作符,类型操作符对名字或标号的类型属性进行设置 类型名 PTR 名字/标号 其中可以是BYTE、WORD、DWORD(依次表示字节、字、双字)等,或者是NEAR、FAR(分别表示近、远),还可以是由结构、记录等定义的类型 对变量: LENGTH 操作符获知某变量名指向多少个数据项 SIZE 操作符获知它共占用多少字节空间,4. 保留字,保留字(Reserved Word)是汇编程序已经利用的标识符(也称为关键字),主要有: 硬指令助记符例如:MOV、ADD 伪指令助记符例如:DB、DW 操作符例如:OFFSET、PTR 寄存器名例如:AX、CS 预定义符号例如:data,汇编语言大小写不敏感,5. 操作数和参数,处理器指令的操作数可以是立即数、寄存器和存储单元 伪指令的参数可以是常数、变量名、表达式等,可以有多个,参数之间用逗号分隔,6. 注释,语句中由分号“;”开始的部分为注释内容,用以增加源程序的可读性 必要时,一个语句行也可以由分号开始作为阶段性注释 汇编程序在翻译源程序时将跳过该部分,不对它们做任何处理,8. 分隔符,语句的4个组成部分要用分隔符分开 标号后用冒号,注释前用分号 操作数之间和参数之间使用逗号分隔 其他部分通常采用空格或制表符 多个空格和制表符的作用与一个相同 MASM支持续行符 “”,例1 : 在屏幕上显示一段信息,;数据段(定义要显示的字符串) string dbHello, Assembly !,0dh,0ah,$ ;代码段(显示字符串的程序) mov dx,offset string mov ah,9 int 21h,Hello, Assembly !,7.2 常量、变量和标号,汇编语言的数据可以简单分为常量和变量 常量可以作为硬指令的立即数或伪指令的参数 变量主要作为存储器操作数 汇编语言语句中的名字和标号具有逻辑地址和类型属性,主要用做地址操作数,也可以作为立即数和存储器操作数,7.2.1 常量,常量表示一个固定的数值,它又分成多种形式 常数 字符串 符合常量 数值表达式,1. 常数,指由10、16、2和8进制形式表达的数值,各种进制的数据以后缀字母区分,默认不加后缀字母的是十进制数,2. 字符串,字符串常量是用单引号或双引号括起来的单个字符或多个字符 其数值是每个字符对应的ASCII码值 例如: d(等于64H) AB(等于4142H) Hello, Assembly !,3. 符号常量,符号常量使用标识符表达一个数值 符号定义伪指令有“等价EQU”和“等号”: 符号名 EQU 数值表达式 符号名 数值表达式 EQU用于数值等价时不能重复定义符号名,但“”允许有重复赋值。例如: X = 7 ;等效于:X qeu 7 X = X+5 ;“X EQU X+5”是错误的,4. 数值表达式,数值表达式一般是指由运算符连接的各种常量所构成的表达式 汇编程序在汇编过程中计算表达式,最终得到一个确定的数值,所以也是常量 表达式的数值在程序运行前的汇编阶段计算,所以组成表达式的各部分必须在汇编时就能确定 汇编语言支持多种运算符(表3.4) 我们经常使用的是加减乘除( * / ) 例如: mov ax,3*4+5 ;等价于:mov ax,17,运算符,1. 算术运算符: 加减乘除( * / ) 2. 取值运算符: SEG、OFFSET、TYPE、SIZE和LENGTH 3. 属性运算符 PTR,地址操作符,地址操作符取得名字或标号的段地址和偏移地址,类型操作符,类型操作符对名字或标号的类型属性进行设置 类型名 PTR 名字/标号 其中可以是BYTE、WORD、DWORD(依次表示字节、字、双字)等,或者是NEAR、FAR(分别表示近、远),还可以是由结构、记录等定义的类型 对变量: LENGTH 操作符获知某变量名指向多少个数据项 SIZE 操作符获知它共占用多少字节空间,7.2.2 变量,变量实质上是指内存单元的数据,虽然内存单元地址不变,但其中存放的数据可以改变 变量需要事先定义才能使用 变量定义(Define)伪指令为变量申请固定长度为单位的存储空间,并可以同时将相应的存储单元初始化 定义后的变量可以利用变量名等方法引用其中的数据,即变量的数值,1. 变量的定义,变量定义的汇编语言格式为: 变量名 伪指令 初值表 变量名为用户自定义标识符,表示初值表首元素的逻辑地址,常称为符号地址。变量名也可以没有 初值表是用逗号分隔的参数,主要由常量、数值表达式或“?”组成。其中“?”表示未赋初值 多个存储单元如果初值相同,可以用复制操作符DUP进行定义: 重复次数 DUP(重复参数) 变量定义伪指令有DB、DW、DD等,字节变量的定义DB(Define Byte),DB伪指令用于分配一个或多个字节单元,并可以将它们初始化为指定值 初值表中每个数据一定是字节量,存放一个8位数据: 可以是0255的无符号数 或是128127带符号数 也可以是字符串常数,实例,字节变量定义实例,;数据段 X db a,-5 db 2 dup(100),? Y db ABC,应用,字节变量的应用,mov al,X ;此处X表示它的第1个数据,故ALa dec X+1 ;对X为始的第2个数据减1,故成为6 mov Y,al ;现在Y这个字符串成为 aBC,字变量的定义DW(Define Word),DW伪指令用于分配一个或多个字单元,并可以将它们初始化为指定值 初值表中每个数据是字量,一个字单元可用于存放任何16位数据: 一个段地址 一个偏移地址 两个字符 065535之间的无符号数 3276832767之间的带符号数,字变量定义实例,;数据段 count dw 8000h,?,AB maxint equ 64h number dw maxint array dw maxint dup(0),双字变量的定义DD(Define Double word),DD伪指令用于分配一个或多个双字单元,并可以将它们初始化为指定值 初值表中每个数据是一个32位的双字量: 可以是有符号或无符号的32位整数 也可以用来表达16位段地址(高位字)和16位的偏移地址(低位字)的远指针 vardd DD 0,?,12345678h farpoint DD 00400078h,2. 变量的应用,变量具有存储单元的逻辑地址 程序代码中 通过变量名引用其指向的首个数据 通过变量名加减位移量存取以首个数据为基地址的前后数据,例2 变量的定义,;数据段 bvar1 db 100,01100100b,64h,d ;字节变量:不同进制表达同一个数值,内存中有4个64H minint = 5 ;符号常量:minint数值为5,不占内存空间 bvar2 db -1,minint,minint+5 ;内存中数值依次为FFH,5,0AH db ?,2 dup(20h) ;预留一个字节空间,重复定义了2个数值20H wvar1 dw 2010h,4*4 ;字变量:两个数据是2010H、0010H,共占4个字节 wvar2 dw ? ;wvar2是没有初值的字变量,例2 变量的定义(续),dvar dd 12347777h,87651111h,? ;双字变量:2个双字数据,一个双字空间 abc db a,b,c,? ;定义字符,实际是字节变量 maxint equ 0ah ;符号常量:maxint10 string db ABCDEFGHIJ ;定义字符串:使用字节定义DB伪指令 crlfs db 13,10,$ ;回车符0DH、换行符0AH和字符$24H array1 dw maxint dup(0) ;10个初值为0的字量,可以认为是数组 array db 2 dup(2,3,2 dup(4) ;6个字节内容依次为:02 03 04 04 02 03 04 04,例2 变量的应用,;代码段 mov dl,bvar1 ;DL100 dec bvar2+1 ;bvar2+14 mov abc3,dl ;abcabcd mov ax,word ptr dvar0 ;取双字到DX.AX mov dx,word ptr dvar2 add ax,word ptr dvar4 ;加双字到DX.AX adc dx,word ptr dvar6 mov word ptr dvar8,ax ;保存双字的求和结果 mov word ptr dvar10,dx,例2 变量的应用(续),mov cx,maxint ;CX10 mov bx,0 ;BX0 again: add stringbx,3 ;string每个数值加3 inc bx loop again ;循环 lea dx,abc ;从abc开始 mov ah,9 ;09H号DOS功能调用 int 21h ;显示结果:abcdDEFGHIJKLM,3. 变量的定位,汇编程序按照指令的先后顺序一个接着一个分配存储空间,按照段定义伪指令规定的边界定位属性确定每个逻辑段的起始位置(包括偏移地址) 定位伪指令ORG控制数据或代码所在的偏移地址 ORG 参数 ORG伪指令是将当前偏移地址指针指向参数表达的偏移地址。例如: ORG 100h ;从100H处安排数据或程序 ORG $+10 ;偏移地址加10,即跳过10个字节空间 汇编语言程序中,符号“$”表示当前偏移地址值,定义数据伪指令DB、DW、DD、DQ、DT 符号定义伪指令EQU、= 段定义伪指令SEGMENT和ENDS 设定段寄存器伪指令ASSUME 定义过程的伪指令PROC和ENDP 宏指令MACRO 定位伪指令ORG 汇编结束伪指令END,7.3 汇编语言伪指令,1. 定义数据伪指令,该类伪指令用来定义存储空间及其所存数据的长度。 DB:定义字节,即每个数据是1个字节。 DW:定义字,即每个数据占1个字(2个字节)。 DD:定义双字,即每个数据占2个字。低字部分在低地址,高字部分在高地址。 DQ:定义4字长,即每个数据占4个字。 DT:定义10个字节长,用于压缩式十进制数, 例如:DATA1 DB 5,6,8,100 DATA2 DW 7,287 TABLE DB ? ;表示在TABLE单元中存放的内容是随机的,当一个定义的存储区内的每个单元要放置同样的数据时,可用DUP操作符。 一般格式:COUNT DUP(?), COUNT 为重复的次数,“( )”中为要重复的数据。 如:BUFFER DB 100DUP(0) ;表示以BUFFER为首地址的100个字节中存放00H数据 BUFFER1 DB 100 DUP(3,5,2DUP(10),35),24,NUM,2. 符号定义伪指令,EQU 伪指令给符号定义一个值。在程序中,凡是出现该符号的地方,汇编时均用其值代替, 如:TIMES EQU 50 DATA DB TIMES DUP(?) 上述两个语句实际等效于如下一条语句: DATA DB 50 DUP(?) “=”伪指令可给初始变量赋值。 如:COUNT=100 ;COUNT=100 TIME=50 ;TIME=50 PURGE伪指令用于释放由EQU伪指令定义的变量,使这些变量可以被重新定义。 PURGE TIMES ; 释放TIMES变量 TIMES EQU 2 ; 重新定义,3. 段定义伪指令,SEGMENT和ENDS 一般来说,一个完整的汇编源程序由3个段组成,即堆栈段、数据段和代码段。段定义伪指令可将源程序划分成若干段,以便生成目的代码和连接时将各同名段进行组合。 段定义伪指令一般格式为 : 段名 SEGMENT 定位类型 组合类型 类别 段名 ENDS SEGMENT和ENDS应成对使用,缺不可。 其中段名是不可省略的。其它是可选项,是赋予段名的属性,可以省略。 例如: DATA SEGMENT DW 20 DUP(?) DATA ENDS,4.设定段寄存器伪指令ASSUME,一般格式: ASSUME 段寄存器:段名,段寄存器:段名, 功能:通知汇编程序,哪一个段寄存器是该段的段寄存器,如CODE表示代码段,DATA表示数据段,STACK表示堆栈段。 例如: CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK MOV AX,DATA ;DATA段值送AX MOV DS,AX ;AX内容送DS,DS才有实际段值 CODE ENDS,5.定义过程的伪指令PROC和ENDP,在程序设计中,可将具有一定功能的程序段看成为一个过程(相当于一个子程序),它可以被别的程序调用。 格式: 过程名 PROC 类型 过程体 RET 过程名 ENDP,CODE1 SEGMENT ASSUME CS:CODE1 FARPROC PROC FAR RET FARPROC ENDP CODE1 ENDS CODE2 SEGMENT ASSUME CS:CODE2 CALL FAR PROC CODE2 ENDS CODE1 段中的FAR PROC 过程被另一段CODE2调用,故为远过程。,例:,6. ORG 伪指令,ORG伪指令规定了在某一段内,程序或数据代码存放的起始偏移地址。 格式: ORG 例如:DATA SEGMENT BUFF1 DB 23,56H,EOF ORG 2000H BUFF2 DB STRING DATA ENDS 上述变量定义中,BUFF1从DATA段偏移地址为0的单元开始存放,而BUFF2则从DATA段偏移为2000H的单元开始存放,两者不是连续存放。,7. 汇编结束伪指令END,该伪指令表示源程序的结束令汇编程序停止汇编。因此,任何一个完整的源程序均应有END指令。 格式: END 表达式 其中表达式表示该汇编程序的启动地址。 例如: END START ;表明该程序的启动地址为START。,7.4 汇编程序设计,简单程序设计 分支程序设计 循环程序设计 子程序设计,1. 顺序程序设计,没有分支、循环等转移指令的程序,会按指令书写的前后顺利依次执行,这就是顺序程序 顺序结构是最基本的程序结构 完全采用顺序结构编写的程序并不多见,例题4 顺序程序设计实例 采用查表法,实现一位16进制数 转换为ASCII码显示,例4 数据段,;数据段 ASCII db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h ;对应0 9的ASCII码 db 41h,42h,43h,44h,45h,46h ;对应A F的ASCII码 hex db 04h,0bh ;假设两个数据,例4 代码段,;代码段 mov bx,offset ASCII ;BX指向ASCII码表 mov al,hex ;AL取得一位16进制数,恰好就是ASCII码表中的位移 and al,0fh ;只有低4位是有效的,高4位清0 Xlat ;换码:ALDS:BXAL mov dl,al ;入口参数:DLAL mov ah,2 ;02号DOS功能调用 int 21h ;显示一个ASCII码字符 mov al,hex+1 ;转换并显示下一个数据 and al,0fh xlat mov dl,al mov ah,2 int 21h,XLAT,2. 分支程序设计,分支程序根据条件是真或假决定执行与否 判断的条件是各种指令,如CMP、TEST等执行后形成的状态标志 转移指令Jcc和JMP可以实现分支控制 分支结构有 单分支结构 双分支结构 多分支结构,单分支结构,条件成立跳转,否则顺序执行分支语句体 注意选择正确的条件转移指令和转移目标地址,实例:求绝对值,计算AX中有符号数的绝对值,cmp ax,0 jge nonneg ;条件满足(AX0),转移 neg ax ;条件不满足,求补 nonneg: mov result,ax ;条件满足,;不恰当的分支 cmp ax,0 jl yesneg ;条件满足(AX0),转移 jmp nonneg yesneg: neg ax ;条件不满足,求补 nonneg: mov result,ax ;条件满足,双分支结构,条件成立跳转执行第2个分支语句体,否则顺序执行第1个分支语句体 注意第1个分支体后一定要有一个JMP指令跳到第2个分支体后,实例:显示BX的最高位,例:显示BX的最高位,shl bx,1 ;BX最高位移入CF标志 jc one ;CF1,即最高位为1,转移 mov dl,30h ;CF0,即最高位为0:DL30H0 jmp two ;一定要跳过另一个分支体 one: mov dl,31h ;DL 31H1 two: mov ah,2 int 21h ;显示,可以用JNC替换JC,显示BX的最高位(续),shl bx,1 ;BX最高位移入CF标志 jnc one ;CF0,即最高位为0,转移 mov dl,31h ;CF1,即最高位为1:DL31H1 jmp two ;一定要跳过另一个分支体 one: mov dl,30h ;DL 30H0 two: mov ah,2 int 21h ;显示,例5. 显示压缩BCD码,无前导0,;数据段 BCD db 04h ;代码段 mov dl,BCD test dl,0ffh ;如果BCD码为0,显示0 jz zero ;双分支结构 test dl,0f0h ;如果BCD码高位为0,不显示0 jz one ;单分支结构,显示压缩BCD码,无前导0(续),mov cl,4 ;处理高位 shr dl,cl or dl,30h ;转换为ASCII码 mov ah,2 ;显示高位 int 21h mov dl,BCD and dl,0fh one: or dl,30h ;处理低位 jmp two zero: mov dl,0 two: mov ah,2 int 21h,例6: 大小写字母转换,;如果DL是一个小写字母,则转换为大写 cmp dl,a ;小于小写字母a,不需要处理 jb disp cmp dl,z ;大于小写字母z,也不需要处理 ja disp sub dl,20h ;是小写字母,则转换为大写 disp: ,转换原理,多分支结构,多分支结构是多个条件对应各自的分支语句体,哪个条件成立就转入相应分支体执行,or ah,ah ;cmp ah,0 jz function0 dec ah ;cmp ah,1 jz function1 dec ah ;cmp ah,2 jz function2,3. 循环程序设计,循环程序结构是满足一定条件的情况下,重复执行某段程序 循环结构的程序通常有3个部分: 循环初始部分为开始循环准备必要的条件,如循环次数、循环体需要的数值等 循环体部分指重复执行的程序部分,其中包括对循环条件等的修改程序段 循环控制部分判断循环条件是否成立,决定是否继续循环,关键是什么?,循环控制,循环结构程序的设计关键是循环控制部分 循环控制可以在进入循环之前进行,也可以在循环体后进行,于是形成两种结构: “先判断、后循环”结构 “先循环、后判断”结构 循环结束的控制可以用循环次数,还可以用特定条件等,于是又有: 计数控制循环 条件控制循环,图示,先循环后判断的循环结构,1. 计数控制循环,计数控制循环利用循环次数作为控制条件 易于采用循环指令LOOP和JCXZ实现 初始化:将循环次数或最大循环次数置入CX 循环体 循环控制:用LOOP指令对CX减1、并判断是否为0,例7: 用二进制显示BL内容,mov cx,8 ;CX8(循环次数) again: shl bl,1 ;左移进CF,从高位开始显示 mov dl,0 ;MOV指令不改变CF adc dl,30h ;DL030HCF ;CF若是0,则DL 0 ;CF若是1,则DL 1 mov ah,2 int 21h ;显示 loop again ;CX减1,如果CX未减至0,则循环,计数控制循环 先循环后判断,例8. 求数组元素的最大值和最小值,;数据段 array dw 10 ;假设一个数组,其中头个数据10表示元素个数 dw -3,0,20,900,587,-632,777,234,-34,-56 ;这是一个有符号字量元素组成的数组 maxay dw ? ;存放最大值 minay dw ? ;存放最小值,初始化:循环次数元素个数1 循环体:逐个比较求最大、小值 循环控制:比较完所有数据,例8. 代码段,;代码段 lea si,array mov cx,si ;取得元素个数 dec cx ;减1后是循环次数 add si,2 mov ax,si ;取出第一个元素给AX,AX用于暂存最大值 mov bx,ax ;取出第一个元素给BX,BX用于暂存最小值,初始化,例8. 代码段(续),maxck: add si,2 cmp si,ax ;与下一个数据比较 jle minck mov ax,si ;AX取得更大的数据 jmp next minck: cmp si,bx jge next mov bx,si ;BX取得更小的数据 next: loop maxck ;计数循环 mov maxay,ax ;保存最大值 mov minay,bx ;保存最小值,循环体,2. 条件控制循环,条件控制循环需要利用特定条件判断循环是否结束 条件控制循环用条件转移指令判断循环条件 转移指令可以指定目的标号来改变程序的运行顺序,如果目的标号指向一个重复执行的语句体的开始或结束,便构成了循环控制结构,例9. 显示以0结尾的字符串,;数据段 string db Let us have a try !,0 ;代码段 mov bx,offset string again: mov dl,bx cmp dl,0 jz done ;为0结束 mov ah,2 ;不为0,显示 int 21h inc bx ;指向下一个字符 jmp again done: ,条件控制循环 先判断后循环,例10 记录某个字存储单元数据中1的个数,;数据段 number dw 1110111111100100B ;代码段 mov bx,number xor dl,dl ;循环初值:DL0 again: test bx,0ffffh ;也可以用cmp bx,0 jz done ;全部是0就可以退出循环,减少循环次数 shl bx,1 ;用指令shr bx,1也可以 adc dl,0 ;利用ADC指令加CF的特点进行计数 jmp again,条件控制循环 先判断后循环,例10. 十进制显示(016数值),done: cmp dl,10 ;判断1的个数是否小于10 jb digit ;1的个数小于10,转移 push dx mov dl,1 ;1的个数大于或等于10 mov ah,2 ;则要先显示一个1 int 21h pop dx sub dl,10 digit: add dl,0 ;显示个数 mov ah,2 int 21h,单分支结构,4. 子程序设计,把功能相对独立的程序段单独编写和调试,作为一个相对独立的模块供程序使用,就形成子程序 子程序可以实现源程序的模块化,可简化源程序结构,可以提高编程效率 主程序(调用程序)需要利用CALL指令调用子程序(被调用程序) 子程序需要利用RET指令返回主程序,1. 过程定义和子程序编写,汇编语言中,子程序要用一对过程伪指令PROC和ENDP声明,格式如下: 过程名 PROC NEAR|FAR ;过程体 过程名 ENDP 可选的参数指定过程的调用属性。没有指定过程属性,则采用默认属性 NEAR属性(段内近调用)的过程只能被相同代码段的其他程序调用 FAR属性(段间远调用)的过程可以被相同或不同代码段的程序调用,子程序编写注意事项,子程序要利用过程定义伪指令声明 子程序最后利用RET指令返回主程序,主程序执行CALL指令调用子程序 子程序中对堆栈的压入和弹出操作要成对使用,保持堆栈的平衡 子程序开始应该保护使用到的寄存器内容,子程序返回前相应进行恢复 子程序应安排在代码段的主程序之外,最好放在主程序执行终止后的位置(返回DOS后、汇编结束END伪指令前),也可以放在主程序开始执行之前的位置,子程序编写注意事项(续),子程序允许嵌套和递归 子程序可以与主程序共用一个数据段,也可以使用不同的数据段(注意修改DS),还可以在子程序最后设置数据区(利用CS寻址) 子程序的编写可以很灵活,例如具有多个出口(多个RET指令)和入口,但一定要保证堆栈操作的正确性 处理好子程序与主程序间的参数传递问题 提供必要的子程序说明信息,例11 用显示器功能调用输出一个字符的子程序,;主程序 mov al,? ;主程序提供显示字符 call dpchar ;调用子程序 ;子程序:显示AL中的字符 dpchar proc ;过程定义,过程名为dpchar push ax ;顺序入栈,保护寄存器 push bx mov bx,0 mov ah,0eh ;显示器0EH号输出一个字符功能 int 10h pop bx ;逆序出栈,恢复寄存器 pop ax ret ;子程序返回 dpchar endp ;过程结束,例11 源程序,; wjl11.asm .model small .stack .code start: mov ax,data mov ds,ax mov al,? ;主程序提供显示字符 call dpchar ;调用子程序 mov ax,4c00h int 21h,主程序部分,本程序不需要数据段,例11 源程序(续),dpchar proc ;过程定义,过程名为dpchar push ax ;顺序入栈,保护寄存器 push bx mov bx,0 mov ah,0eh ;显示器0EH号输出一个字符功能 int 10h pop bx ;逆序出栈,恢复寄存器 pop ax ret ;子程序返回 dpchar endp ;过程结束 end start,子程序安排在主程序执行终止后的位置,例12 显示以“0”结尾字符串的嵌套子程序,;数据段 msg db Well, I made it !,0 ;代码段(主程序) mov si,offset msg ;主程序提供显示字符串 call dpstri ;调用子程序,例12 子程序,;子程序dpstri:显示DS:SI指向的字符串(以0结尾) dpstri proc push ax dps1: mov al,si ;取显示字符 inc si cmp al,0 ;是结尾,则显示结束 jz dps2 call dpchar ;调用字符显示子程序 jmp dps1 dps2: pop ax ret dpstri endp ;子程序dpchar:显示AL中的字符,含数据区的子程序,;子程序HTOASC:十六进制数转换为ASCII码 HTOASC proc push bx mov bx,offset ASCII and al,0fh xlat CS:ASCII ;换码:ALCS:BXAL pop bx ret ;数据区 ASCII db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h db 41h,42h,43h,44h,45h,46h HTOASC endp,多出口子程序,;子程序HTOASC:十六进制数转换为ASCII码 HTOASC proc and al,0fh cmp al,9 jbe htoasc1 add al,37h ;是A F,加37H ret ;子程序返回 htoasc1: add,30h ;是0 9,加30H ret ;子程序返回 HTOASC endp,7.5 汇编语言程序汇编步骤,汇编语言程序要能在机器上运行,还必需将汇编源程序汇编成可执行程序。为此必须完成以下几个步骤: 编辑源程序 调用汇编程序对源程序进行汇编 对目标程序进行连接 运行可执行程序并调试,1汇编程序 汇编是把汇编语言程序翻译成机器语言描述的目标程序的过程。 汇编程序(ASM)是完成汇编任务的程序。 2连接程序 连接程序的主要功能是实现多个目标文件及库文件的连接,并完成浮动地位的重定位。 从汇编语言源程序到可执行程序的生成过程如图所示。,开发过程1:源程序的编辑,源程序文件要以ASM为扩展名 源程序文件的形成(编辑)可以通过任何一个文本编辑器实现: DOS中的全屏幕文本编辑器EDIT 其他程序开发工具中的编辑环境 Windows中的记事本Notepad,开发过程2:源程序的汇编(MASM 6.x),汇编是将源程序翻译成由机器代码组成的目标模块文件的过程 MASM 6.x提供的汇编程序是ML.EXE。 如果源程序中没有语法错误,MASM将自动生成一个目标模块文件(.obj);否则MASM将给出相应的错误信息。这时应根据错误信息,重新编辑修改源程序后,再进行汇编,开发过程2:源程序的汇编(MASM 5.x),MASM 5.x提供的汇编程序是MASM.EXE。 默认

温馨提示

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

评论

0/150

提交评论