第 4 章 汇编语言程序设计

43
第4第 第第第第第第第第 4.1 第第第第第第 4.2 第第第第第第 4.3 第第第第第第 4.4 第第第第第 4.5 第第第第第第第 4.6 第第第第第第第 4.7 第第第第第第第第

Upload: lilac

Post on 13-Jan-2016

136 views

Category:

Documents


8 download

DESCRIPTION

第 4 章 汇编语言程序设计. 4.1 顺序程序设计 4.2 分支程序设计 4.3 循环程序设计 4.4 子程序设计 4.5 宏结构程序设计 4.6 模块化程序设计 4.7 输入输出程序设计. 4.4 子程序设计. 把功能相对独立的程序段单独编写和调试,作为一个相对独立的模块供程序使用,就形成子程序。 子程序可以实现源程序的模块化,可以简化源程序结构,可以提高编程效率。. 子程序设计要利用过程定义伪指令. 参数传递是子程序设计的重点和难点. 子程序可以嵌套; 一定条件下,还可以递归和重入. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 4 章  汇编语言程序设计

第 4 章 汇编语言程序设计第 4 章 汇编语言程序设计

4.1 顺序程序设计4.2 分支程序设计4.3 循环程序设计4.4 子程序设计4.5 宏结构程序设计4.6 模块化程序设计4.7 输入输出程序设计

Page 2: 第 4 章  汇编语言程序设计

把功能相对独立的程序段单独编写和调试,作为一个相对独立的模块供程序使用,就形成子程序。

子程序可以实现源程序的模块化,可以简化源程序结构,可以提高编程效率。

4.4 子程序设计

子程序设计要利用过程定义伪指令

参数传递是子程序设计的重点和难点

子程序可以嵌套;一定条件下,还可以递归和重入

Page 3: 第 4 章  汇编语言程序设计

4.4.1 4.4.1 程序定义伪指令程序定义伪指令过程名 proc [near|far]...

过程名 endp

过程名(子程序名)为符合语法的标识符。•NEAR 属性(段内近调用)的过程只能被相同代码段的

其他程序调用;•FAR 属性(段间远调用)的过程可以被相同或不同代

码段的程序调用。对简化段定义格式,在微型、小型和紧凑存储模式下,

过程的缺省属性为 near ;在中型、大型和巨型存储模式下,过程的缺省属性为 far 。对完整段定义格式,过程的缺省属性为 near 。

用户可以在过程定义时用 near 或 far 改变缺省属性。

Page 4: 第 4 章  汇编语言程序设计

subname proc ; 具有缺省属性的 subname 过程

push ax ; 保护寄存器:顺序压入堆栈push bx ;ax/bx/cx 仅是示例push cx... ; 过程体pop cx ; 恢复寄存器:逆序弹出堆栈pop bxpop axret ; 过程返回

subname endp ; 过程结束

子程序的常见格式

例 4.10

Page 5: 第 4 章  汇编语言程序设计

ALdisp proc ; 实现 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 ; 是 0Ah ~ 0Fh ,其 ASCII 码还要加上

7aldisp1: mov ah,2 ; 显示

int 21h

例 4.10 上

Page 6: 第 4 章  汇编语言程序设计

pop dx ; 恢复原 ax 值到 dxand dl,0fh ; 转换 al 的低 4 位or dl,30hcmp dl,39hjbe aldisp2add dl,7

aldisp2: mov ah,2 ; 显示int 21hpop dxpop cxpop axret ; 过程返回

ALdisp endp

例 4.10 下

Page 7: 第 4 章  汇编语言程序设计

... ; 主程序,同例 4.8 源程序loop outlp ; 外循环尾mov bx,offset array ; 调用程序段开始mov cx,count

displp: mov al,[bx]call ALdisp ; 调用显示过程mov dl,',' ; 显示一个逗号,以分隔两个数据mov ah,2int 21hinc bxloop displp ; 调用程序段结束.exit 0... ; 过程定义,同例 4.10 源程序end

例 4.10 应用

操作操作

Page 8: 第 4 章  汇编语言程序设计

入口参数(输入参数):主程序 提供给 子程序

出口参数(输出参数):子程序 返回给 主程序

4.4.2 4.4.2 子程序的参数传递子程序的参数传递

参数的形式:参数的形式:① 数据本身(传值) ② 数据的地址(传址)传递的方法:传递的方法:① 寄存器 ② 变量 ③ 堆栈

例例 4.114.11 子程序计算数组元素的“校验和” 入口参数: 数组的逻辑地址(传址),

元素个数(传值); 出口参数: 求和结果(传值)。

Page 9: 第 4 章  汇编语言程序设计

把参数存于约定的寄存器中,可以传值,也可以传址。

子程序对带有出口参数的寄存器不能保护和恢复(主程序视具体情况进行保护)。

子程序对带有入口参数的寄存器可以保护,也可以不保护;但最好一致。

例例 4.11a4.11a•入口参数: CX =元素个数,DS:BX =数组的段地址:偏移地址•出口参数: AL =校验和

用寄存器传递参数

Page 10: 第 4 章  汇编语言程序设计

.startup ; 设置入口参数(含有 DS←数组的段地址)mov bx,offset array;BX←数组的偏移地址mov cx,count ;CX←数组的元素个数call checksuma ; 调用求和过程mov result,al ;处理出口参数.exit 0 主程序 a

checksumaprocxor al,al ;累加器清 0

suma: add al,[bx] ; 求和inc bx ;指向下一个字节loop sumaret

checksumaendpend

子程序 a

Page 11: 第 4 章  汇编语言程序设计

主程序和子程序直接采用同一个变量名共享同一个变量,实现参数的传递。

不通模块间共享时,需要声明。

例例 4.11b4.11b•入口参数:count =元素个数,array =数组名(含段地址:偏移地址)•出口参数:result =校验和

用变量传递参数

Page 12: 第 4 章  汇编语言程序设计

checksumb procpush axpush bxpush cxxor al,al ;累加器清 0mov bx,offset array ;BX←数组的偏移地址mov cx,count;CX←数组的元素个数

sumb: add al,[bx] ; 求和inc bxloop sumbmov result,al ; 保存校验和pop cxpop bxpop axret

checksumb endp

call checksumb ; 调用求和过程主程序 b

子程序 b

Page 13: 第 4 章  汇编语言程序设计

主程序将子程序的入口参数压入堆栈,子程序从堆栈中取出参数;

子程序将出口参数压入堆栈,主程序弹出堆栈取得它们。

例例 4.11c4.11c•入口参数:顺序压入偏移地址和元素个数•出口参数:AL =校验和

用堆栈传递参数

Page 14: 第 4 章  汇编语言程序设计

checksumcprocpush bpmov bp,sppush bxpush cxmov bx,[bp+6]

mov cx,[bp+4] xor al,alsumc: add al,[bx]

inc bxloop sumcpop cxpop bxpop bpret

checksumcendp

mov ax,offset arraypush axmov ax,countpush axcall checksumcadd sp,4mov result,al

主程序 c

子程序 c

•利用 BP间接寻址取出参数注意位移量•主程序实现平衡堆栈: add sp,n•子程序实现平衡堆栈: ret n

参见图

Page 15: 第 4 章  汇编语言程序设计

子程序的嵌套

子程序内包含有子程序的调用就是子程序嵌套。没有什么特殊要求

例题 4.10

Page 16: 第 4 章  汇编语言程序设计

例 4.10 :子程序嵌套ALdisp procpush axpush cxpush dxpush axmov dl,almov cl,4shr dl,clcall dldisppop dxand dl,0fhcall dldisppop dxpop cxpop axret

ALdisp endp

;将 dl 中的一位 16 进制数显示出来dldisp proc

or dl,30hcmp dl,39hjbe dldisp1add dl,7

dldisp1: mov ah,2int 21hret

dldisp endp

Page 17: 第 4 章  汇编语言程序设计

子程序的递归

当子程序直接或间接地嵌套调用自身时称为递归调用,含有递归调用的子程序称为递归子程序。

递归子程序必须采用寄存器或堆栈传递参数,递归深度受堆栈空间的限制。

例 4.12 :求阶乘

01

0)!1(!

N

NNNN

Page 18: 第 4 章  汇编语言程序设计

例 4.12 主程序

.model small

.stack 256

.dataN dw 3result dw ?

.code

.startupmov bx,Npush bxcall factpop result.exit 0

Page 19: 第 4 章  汇编语言程序设计

fact proc ; 计算 N!的近过程push ax ; 入口参数:压入 Npush bp ; 出口参数:弹出 N!mov bp,spmov ax,[bp+6]cmp ax,0jne fact1inc axjmp fact2

fact1: dec axpush axcall factpop axmul word ptr [bp+6]

fact2: mov [bp+6],axpop bppop axret

fact endp

递归子程序

Page 20: 第 4 章  汇编语言程序设计

子程序的重入

•子程序的重入是指子程序被中断后又被中断服务程序所调用,能够重入的子程序称为可重入子程序。在子程序中,注意利用寄存器和堆栈传递参数和存放临时数据,而不要使用固定的存储单元(变量),就能够实现重入。

•子程序的重入不同于子程序的递归。重入是被动地进入,而递归是主动地进入;重入的调用间往往没有关系,而递归的调用间却是密切相关的。递归子程序也是可重入子程序。

Page 21: 第 4 章  汇编语言程序设计

宏汇编重复汇编

条件汇编——统称宏结构

4.5 宏结构程序设计

宏( Macro )是汇编语言的一个特点,它是与子程序类似又独具特色的另一种简化源程序的方法。

Page 22: 第 4 章  汇编语言程序设计

宏——具有宏名的一段汇编语句序列,——宏定义时书写

宏指令——这段汇编语句序列的缩写,——宏调用时书写

宏展开——在宏指令处用这段宏代替的过程,——宏汇编时实现

宏的参数功能强大,颇具特色。配合宏,还有宏操作符和有关伪指令。宏与子程序实际上具有本质的区别。

4.5.1 宏汇编

Page 23: 第 4 章  汇编语言程序设计

宏定义宏定义 宏名 macro [ 形参表 ]宏定义体endm

mainbegin MACRO ;; 定义一个名为 mainbegin 的宏,无参数

mov ax,@data ;; 宏定义体mov ds,axENDM ;; 宏定义结束

mainend MACRO retnum ;; 带有形参 retnummov al,retnum ;; 宏定义中使用参数mov ah,4chint 21hENDM

Page 24: 第 4 章  汇编语言程序设计

宏调用宏调用 宏名 [ 实参表 ]

start: mainbegin ; 宏 调 用 ,建立 DS 内容

dispmsg string ; 宏调用,显示字符串mainend 0 ; 宏调用,返回 DOSend start

• 宏调用的实质是在汇编过程中进行宏展开。• 宏展开的具体过程是:当汇编程序扫描源程序遇到已有定义的宏调用时,即用相应的宏定义体取代源程序的宏指令,同时用位置匹配的实参对形参进行取代。

Page 25: 第 4 章  汇编语言程序设计

宏展开宏展开 宏展开——在汇编时,用宏定义体的代码序列替代宏指令的过程。

start: mainbegin ; 宏指令 1 mov ax,@data ; 宏展开 1 mov ds,ax

mainend 0 ; 宏指令 1 mov al,0 ; 宏展开 1 mov ah,4ch 1 int 21h

例 4.13b操作例 4.13b操作

Page 26: 第 4 章  汇编语言程序设计

宏的参数宏的参数 宏的参数使用非常灵活

宏定义时,可以无参数,例如 4.13a 的 mainbegin ;可以带有一个参数,例如 4.13a 的 mainend ;也可以具有多个参数;例如 4.14a 的 shlext 。参数可以是常数、变量、存储单元、指令(操

作码)或它们的一部分,也可以是表达式;例如 4.14b 的 shift 和 shrot 。

宏定义体可以是任何合法的汇编语句,既可以是硬指令序列,又可以是伪指令序列;例如 4.15 的dstring 。

Page 27: 第 4 章  汇编语言程序设计

;宏定义shlext macro shloprand,shlnum

push cxmov cl,shlnumshl shloprand,clpop cxendm

;宏指令shlext ax,6

;宏展开 1 push cx 1 mov cl,06 1 shl ax,cl 1 pop cx

例 4.14a

Page 28: 第 4 章  汇编语言程序设计

;统一 4条移位指令的宏指令shift macro soprand,snum,sopcode

push cxmov cl,snums&sopcode& soprand,clpop cxendm

;统一移位和循环移位 8条指令的宏指令shrot macro sroprand,srnum,sropcode

push cxmov cl,srnumsropcode sroprand,clpop cxendm

例 4.14b

Page 29: 第 4 章  汇编语言程序设计

;宏定义dstring macro string

db '&string&',0dh,0ah,'$'endm

;宏调用dstring < This is a example. >dstring < 0 !< Number !< 10 >;宏展开 1 db 'This is a example.', 0dh,0ah,'$’ 1 db '0 < Number < 10', 0dh,0ah,'$'

例 4.15

Page 30: 第 4 章  汇编语言程序设计

宏操作符宏操作符

&——替换操作符,用于将参数与其他字符分开。如果参数紧接在其他字符之前或之后,或者参数出现在带引号的字符串中,就必须使用该伪操作符。

< >——字符串传递操作符,用于括起字符串。在宏调用中,如果传递的字符串实参数含有逗号、空格等间隔符号,则必须用这对操作符,以保证字符串的完整。

!——转义操作符,用于指示其后的一个字符作为一般字符,而不含特殊意义。

%——表达式操作符,用在宏调用中,表示将后跟的一个表达式的值作为实参,而不是将表达式本身作为参数

;;—— 宏注释符,用于表示在宏定义中的注释。采用这个符号的注释,在宏展开时不出现。

Page 31: 第 4 章  汇编语言程序设计

与宏有关的伪指令与宏有关的伪指令

•局部标号伪指令LOCAL 标号列表宏定义体采用了标号,应使用局部标号伪指令 LOCAL

加以说明。它必须是宏定义 MACRO 语句之后的第一条语句。•宏定义删除伪指令PURGE 宏名表不需要某个宏定义时,可以把它删除。•宏定义退出伪指令EXITM伪指令 EXITM表示结束当前宏调用的展开。

Page 32: 第 4 章  汇编语言程序设计

;宏定义absol macro oprd

local nextcmp oprd,0jge nextneg oprd

next:endm

例 4.16

;宏调用absol word ptr [bx]absol bx

;宏展开 1 cmp word ptr [bx],0 1 jge ??0000 1 neg word ptr [bx] 1 ??0000: 1 cmp bx,0 1 jge ??0001 1 neg bx 1 ??0001:

Page 33: 第 4 章  汇编语言程序设计

宏与子程序的比较宏与子程序的比较

宏与子程序具有各自的特点,程序员应该根据具体问题选择使用那种方法。通常,当程序段较短或要求较快执行时,应选用宏;

当程序段较长或为减小目标代码时,要选用子程序。

宏——仅是源程序级的简化:宏调用在汇编时进行程序语句的展开,不需要返回;不减小目标程序,执行速度没有改变。

宏调用的参数通过形参、实参结合实现传递,简捷直观、灵活多变。

子程序——还是目标程序级的简化:子程序调用在执行时由 CALL指令转向,RET 指令返回;形成的目标代码较短,执行速度减慢。

子程序需要利用寄存器、存储单元或堆栈等传递参数。

Page 34: 第 4 章  汇编语言程序设计

重复汇编指在汇编过程中,重复展开一段(基本)相同的语句。

重复汇编没有名字,不能被调用;重复汇编常用在宏定义体中,也可以在一般

汇编语句中使用。重复汇编伪指令有三个:

•REPEAT——按参数值重复,•FOR——按参数个数重复,•FORC——按参数的字符个数重复;最后,用 ENDM 结束。

4.5.2 重复汇编

Page 35: 第 4 章  汇编语言程序设计

按参数值重复按参数值重复 REPEAT 重复次数 重复体ENDM

char = 'A'REPEAT 26 db char char = char +1ENDM

1 db char ;等效于 db 'A' 1 char = char +1 1 db char ;等效于 db 'B' 1 char = char +1

... 1 db char ;等效于 db 'Z' 1 char = char +1

Page 36: 第 4 章  汇编语言程序设计

按参数个数重复按参数个数重复 FOR 形参 ,〈实参表〉 重复体ENDM

FOR regad, <ax,bx,cx,dx> push regadENDM

1 push ax 1 push bx 1 push cx 1 push dx

Page 37: 第 4 章  汇编语言程序设计

按参数字符个数重复按参数字符个数重复 FORC 形参 , 字符串 重复体ENDM

FORC regad,dcba pop &regad&xENDM

1 pop dx 1 pop cx 1 pop bx 1 pop ax

Page 38: 第 4 章  汇编语言程序设计

条件汇编伪指令在汇编过程中,根据条件决定汇编的语句。

IFxx 表达式 ;条件满足,汇编分支语句体 1

分支语句体 1

[ ELSE ;条件不满足,汇编分支语句体 2

汇编分支语句体 2 ]

ENDIF ;条件汇编结束

4.5.3 条件汇编

例 4.19 例 4.13c

Page 39: 第 4 章  汇编语言程序设计

pdata macro num IF num lt 100 ;;如果 num < 100 ,则汇编如下语句

db num dup (?) ELSE ;;否则,汇编如下语句

db 100 dup (?) ENDIF

endm

pdata 12 ; 宏调用①db 12 dup(?) ; 宏汇编结果①

pdata 102 ; 宏调用②db 100 dup(?) ; 宏汇编结果②

例 4.19

Page 40: 第 4 章  汇编语言程序设计

dstring MACRO string ;; 定义字符串db '&string&',0dh,0ah,'$'ENDM

mainbegin MACRO dsseg ;; 设置数据段地址mov ax,dssegmov ds,axENDM

dispmsg MACRO messagemov dx,offset messagemov ah,09hint 21hENDM

例 4.13c 上

Page 41: 第 4 章  汇编语言程序设计

mainend MACRO retnum ;; 返回 DOS ,可以不带参数ifb <retnum> mov ah,4ch ;;没有参数else mov ax,4c00h+(retnum AND 0ffh) ;; 有参数endifint 21hENDM

例 4.13c 中

Page 42: 第 4 章  汇编语言程序设计

.model small

.stack 256

.datamsg1 equ this bytedstring <Hello,Everybody !!>msg2 equ this bytedstring <You see,I made it.>

.codestart: mainbegin @data ;建立 DS 内容

dispmsg msg1 ; 显示 msg1字符串dispmsg msg2 ; 显示 msg2字符串mainend ; 返回 DOSend start

例 4.13c 下

Page 43: 第 4 章  汇编语言程序设计

宏结构的作用

宏汇编、重复汇编和条件汇编为源程序的编写提供了很多方便,灵活运用它们可以编写出非常良好

的源程序来。

汇编系统中有些以圆点起始的 伪指令(如 .startup 、 .exit等) 实际上是一种宏结构。