接口技术 第4章 (46)
MOV DI,-1
NEXT: INC DI
;DI为元素下标
CMP ARRAY[DI], 0 ;从0号元素起,逐个与0比较
LOOPZ NEXT
JNE OK
;ZF=0,即有非零单元素,转OK
MOV DL,‘0’
;没有找到非零元素,显示一个‘0’
OK: MOV DX,DI
OR DL,30H ;将下标字符转换成ASCII码
SHOW: MOV AH,02H
INT 21H
MOV AX,4C00H ;显示下标
INT 21H
;返回DOS
例6:在目的串中指定位置上插入字符串
;子程序名: STR_INSERT ;入口参数 DS:BX指向源串,ES:BP指向目的串,
ES:DX指向目的串中插入源串的位置。 每个串的前两个字节内为16位的串长度。 ;出口参数 在目的串指定位置上插入了源串
;实现W—(X+120)X Y
SBB
DX,BX
;结果在DX:AX中
ADD
AX,200
;实现W—(X+120)X Y+200
ADC
DX,0
;结果在DX,AX中
IDIV
Z
;最后除以Z,结果商在AX,余数在DX中
MOV
RESULT,AX
;存放结果到数据区
MOV
RESULT+2,DX
MOV
AH,4CH
;返回到DOS
;否,再加上07H
PRINTIT:
MOV
DL,AL
;输出单个字符
MOV
AH,02H
INT
21H
DEC
CH
JNZ
ROTATE
;继续下次转换
RET
BINHEX
ENDP
CSEG2
ENDS
END
例2:求无序表中的最大元素及其位置
;模块A, 文件名MAIN.ASM
EXTRN FOUND:NEAR
DATA1 SEGMENT… ARRAY DB d1,d2,d3, … dn
ENDS
SEGMENT
ASSUME CS:C_SEG,DS:D_SEG
MOV
AX,D_SEG
;填入段地址
MOV
DS,AX
MOV
AX,X
;X+120
ADD
AX,120
IMUL
Y
;(X+120)X Y
MOV
CX,AX
;乘积暂时存BX:CX
MOV
BX,DX
MOV
AX,W
;将W带符号扩展
CWD
SUB
AX,CX
COUNT EQU $ —ARRAY
;数据个数
DATA1 ENDS
CODE SEGMENT WORD PUBLIC ‘CODE ’
ASSUME CS:CODE,DS:DATA1
MAIN: MOV AX,DATA1
MOV DS,AX
;装入段基址
MOV CX,COUNT
LEA SI,ARRAY
CALL FOUND ;找出最大元素及位置
3. 多个模块的组合形式
NONE 表示本段为独立段,不与其他模块段发生连接逻辑。
PUBLIC 表示将本段与其他模块中说明为PUBLIC的同名段邻
接在一起,共用一个段地址。组成一个大的物理段(“段组”) 。
STACK 表示将该段与其他同名的堆栈段连接在一起,组合后
的物理段的长度等于参与组合的各堆栈段的长度之和。
MOV CX,4
;循环次数4→CX
RETRY: PUSH CX
MOV CL,4
SHL BX,CL
MOV DX,0
;DX:AX组成被除数
DIV WORD PTR[SI] ;除以权值,商、余数在AX、DX中
OR BX,AX
;压缩BCD 码
MOV AX,DX
;余数送AX
POP CX
ADD SI,2
;地址加2,指向下一权值
;键盘输入十进制数
MOV DEC—NUM,BX ;二进制数DEC—NUM
CALL FAR PTR BINHEX ;以十六进制形式显示
MOV AH,4CH
INT 21H
;返回DOS
;从键盘输入十进制数,将其转换为二进制数并送BX
DECBIN GETCHAR:
EXIT: DECBIN CSEG1
PROC MOV MOV INT SUB JL CMP JG MOV XCHG MOV MUL XCHG ADD JMP RET ENDP ENDS END
MOV
BX,DEC—NUM
MOV
CH,04H
;共有4位十六进制数
ROTATE:
MOV
CL,04H
ROL
BX,CL
;取最4bit二进制数待转换
MOV
AL,BL
AND
AL,0FH
ADD
AL,30H
;十六进制数 ASCII码
CMP
AL,3AH
;十六进制数在0~9之间吗?
JL
PRINTIT
;是,输出
ADD
AL,07H
W1000 DW 1000,100,10 , 1 ;十进制数千,百。十,个位权值
;子程序名:AX2TOBCD。入口参数:AX=二进制数。出口参数:AX=压缩BCD码
AX2TOBCD PROC NEAR
……
;保护现场
XOR BX,BX
;BCD码暂存单元清零
MOV SI,OFFSET W1000 ;权值首地址送SI
4.6模块化程序设计技术
1. 全局符号的定义与引用 单个模块中使用的符号(变量、标号或子程序名)为 局部符号。一个模块中定义的符号如不另加说明,均 为局部符号,局部符号只能在定义它的模块中使用。
多个模块可共同使用的符号为全局符号。只要将局部 符号在定义和使用它的模块中分别用 PUBLIC 和 EXTRN语句说明,即可作为全局符号(又称外部符 号)使用,全局符号构成了模块间通信的主要渠道。 2. 模块间的转移 模块间的转移有两种:近(段内)转移和远(段间) 转移。它们都是通过转移语句来实现的。具体实现转 移的语句是:JMP、CALL 和 INT。
BCDTO2 ENDP
例2:二进制数转换为BCD码 编程将AX中的二进制数转换成4位BCD码,转换的结 果放在AX中(设AX中的数值小于十进制数10000)。 算法:将AX中的二进制数除以1000得到的商是千位上 的BCD码,所得余数除以100得到的商是百位上的 BCD码,所得余数再除以10得到的商是十位上的BCD 码,最后所得的余数是个位上的BCD码。
SSEG ENDS
DSEG1 SEGMENT
DEC—NUM DW ?
DSEG1 ENDS
CSEG1 SEGMENT
ASSUME CS:CSEG1,DS:DSEG1
START: MOV AX,DSEG1
MOV DS,AX
;装入段基址
PUSH DS
JMP FAR PTR PROMPT
KEY—IN: CALL DECBIN
例1:键盘输入十进制数,以十六进制形式在屏幕上
显示。
;模块A 文件名MAIN. ASM
EXTRN PROMPT:FAR,BINHEX:FAR ;引用外部符号
PUBLIC DEC—NUM,KEY—IN
;定义外部符号
SSEG SEGMENT PARA STACK ‘ STACK ’
DB 100 DUP( ?)
ASSUME CS:CSEG2,DS:DSEG2
PROMPT: MOV AX,DSEG2
MOV DS,AX
;装入段基址
LEA
DX,MSG
MOV AH,09H
INT
21H
POP DS
JMP
FAR PTR KEY—IN
;将DEC—NUM中的二进制数转换为十六进制数的ASCII 码并输出
BINHEX
PROC FAR
NEAR BX,0 AH,1 21H AL,30H EXIT AL,09H
EXIT AH,0 AX,BX CX,0AH CX AX,BX BX,AX GETCHAR
START
;累加和BX(已转换的二进制)初始化
;键入值是否在0~9之间? ;否,转至EXIT
;是,将AX中的BCD数与BX内容交换 ;累加和AX乘以当前权值
W10 DW 10
;十进制数权值
;子程序名:BCDTO2。
入口参数:AX=BCD码。出口参数:AX=二进制数。
BCDTO2 PROC NEAR
PUSH BX
PUSH CX
PUSH DX
MOV BX,AX ;保存AX中的BCD码到BX
MOV AX,0
;结果单元清零
MOV CX,4
;共处理4位BCD码
RETRY: PUSH CX
RET
BINTOASC ENDP
例5:在字节数组中找出第一个非零元素,并显示它的下标
.MODEL SMALL
.DATA
ARRAY DB 0,0,0,25H,0,0,34H,36H,45H
COUNT EQU 9
.CODE
START: MOV AX, DATA
MOV DS,AX
MOV CX,COUNT
JB BTOA2
;小余10转BTOA2
XOR DX,DX ;被除数高字清0
DIV CX
;除以0
OR DL,30H ;余数变ASCII吗
MOV [SI],AL
;存最高位的ASCII码
DEC SI
;ASCII码地址减1
JMP BTOA1
BTOA2: OR AL,30H