第五章 循环与分支程序设计 §5.1 循环与转移指令 §5.2 循环程序设计 §5.3 分支程序设计
§5.1 循环与转移指令 一、循环控制指令 二、转移指令 控制转移类指令通过改变IP(和CS)值,实现程序执行顺序的改变
程序中的某段需反复执行若干次时,用循环来实现 一、循环控制指令 8086指令系统的循环控制指令均为二字节指令 一字节为转移的相对位移量(8位带符号的二进制数) IP ← IP+相对位移量 EIP ← EIP+相对位移量 隐含使用CX作为循环计数器 短转移 程序中的某段需反复执行若干次时,用循环来实现
一、循环控制指令 LOOP label ;CX←CX-1,CX≠0,循环到标号label LOOPE/LOOPZ label ;CX←CX-1,CX≠0 且ZF=1,循环到标号label 等于时循环 LOOPNE/NZ label ;CX←CX-1,CX≠0且ZF=0,循环到标号label 不等于时循环
一、循环控制指令(例) MOV CX,COUNT ;设置循环次数 MOV SI,OFFSET DATA_BYTE XOR AX,AX ;BX清0,用于存放累加和 AGAIN: ADD AL,[SI] ADC AH,0 INC SI LOOP AGAIN ;计数器减1,不为0继续循环
一、循环控制指令(例) MOV CX,COUNT ;设置循环次数 MOV SI,OFFSET STRING XOR BX,BX ;BX清0,用于记录空格数 MOV AL,20H AGAIN: CMP AL,[SI] JNZ NEXT ;ZF=0,非空格,转移 INC BX ;ZF=1,是空格,个数加1 NEXT: INC SI LOOP AGAIN ;计数器减1,不为0继续循环
二、转移指令 无条件转移指令 条件转移指令
无条件转移指令 JMP label ;程序转向label标号指定的地址 NEAR FAR JMP label ;程序转向label标号指定的地址 只要执行无条件转移指令JMP,就使程序转到指定的目标地址处,从目标地址处开始执行那里的指令 JMP指令分成4种类型: ⑴ 段内转移、直接寻址 ⑵ 段内转移、间接寻址 ⑶ 段间转移、直接寻址 ⑷ 段间转移、间接寻址 目的地址与JMP属同一逻辑段,只修改IP值 从一个代码段转移到另一个代码段,CS和IP都会被修改
1. 无条件转移指令 —目标地址的寻址方式 直接寻址方式 间接寻址方式 转移地址象立即数一样,直接在指令的机器代码中,就是直接寻址方式 1. 无条件转移指令 —目标地址的寻址方式 直接寻址方式 转移地址象立即数一样,直接在指令的机器代码中,就是直接寻址方式 间接寻址方式 转移地址在寄存器或主存单元中,就是通过寄存器或存储器的间接寻址方式 用标号表达 用寄存器或存储器操作数表达
1. 无条件转移指令 —目标地址的范围:段内 段内转移——近转移(near) 段内转移——短转移(short) 1. 无条件转移指令 —目标地址的范围:段内 段内转移——近转移(near) 在当前代码段64KB范围内转移 ( ±32KB范围) 不需要更改CS段基值,只要改变IP偏移地址 段内转移——短转移(short) 转移范围可以用一个字节表达,在段内-128~+127范围的转移 代码段
1.无条件转移指令 —目标地址的范围:段间 段间转移——远转移(far) 从当前代码段跳转到另一个代码段,可以在1MB范围 1.无条件转移指令 —目标地址的范围:段间 段间转移——远转移(far) 从当前代码段跳转到另一个代码段,可以在1MB范围 需要更改CS段基值和IP偏移地址 目标地址必须用一个32位数表达,叫做32位远指针,它就是逻辑地址 代码段 实际编程时,汇编程序会根据目标地址的距离,自动处理成短转移、近转移或远转移 程序员可用操作符short、near ptr 或far ptr 强制
段内直接寻址转移 JMP label ;IP←IP+位移量 JMP AGAIN ;转移到AGAIN处继续执行 实际为相对寻址 JMP label ;IP←IP+位移量 位移量是紧接着JMP指令后的那条指令的偏移地址,到目标指令的偏移地址的地址位移 当向地址增大方向转移时,位移量为正;向地址减小方向转移时,位移量为负 JMP AGAIN ;转移到AGAIN处继续执行 …… AGAIN: DEC CX ;标号AGAIN的指令 JMP OUTPUT ;转向OUTPUT OUTPUT: MOV RESULT,AL ;标号OUTPUT的指令
段内间接寻址转移 JMP r16/m16 ;IP←r16/m16 将一个16位寄存器或主存字单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容 JMP AX ;IP←AX JMP WORD PTR [BX] ;IP←[BX]
段间直接寻址转移 ;IP←label的偏移地址 JMP far ptr label ;CS←label的段基值 将标号所在段的段基值作为新的CS值,标号在该段内的偏移地址作为新的IP值;程序跳转到新的代码段执行 JMP FAR PTR OTHERSEG ;远转移到代码段2的otherseg
段间间接寻址转移 ;IP←[mem],CS←[mem+2] JMP far ptr mem 用一个双字存储单元表示要跳转的目标地址。这个目标地址存放在主存中连续的两个字单元中的,低位字送IP寄存器,高位字送CS寄存器 MOV WORD PTR [BX],0 MOV WORD PTR [BX+2],1500H JMP FAR PTR [BX] ;转移到1500H:0
2.条件转移指令 Jcc label ;条件满足,发生转移:IP←IP+8位位移量 ;条件不满足,顺序执行
2. 条件转移指令 Jcc指令的操作数label是一个标号 Jcc指令为2个字节,条件不满足时的顺序执行就是当前指令偏移指针IP加2 一个8位位移量是相对于当前IP的,且距当前IP地址-128~+127个单元的范围之内,属于段内短距离转移 Jcc指令为2个字节,条件不满足时的顺序执行就是当前指令偏移指针IP加2
2. 条件转移指令—指令的分类 Jcc指令不影响标志,但要利用标志。 根据利用的标志位不同,19条指令分成4种情况: ⑴ 判断单个标志位状态 ⑴ 判断单个标志位状态 ⑵ 比较无符号数高低 ⑶ 比较有符号数大小 ⑷ 判断计数器CX为0
助记符 标志位 JC JA/JNBE JNC JAE/JNB JZ/JE JB/JNAE JNZ/JNE JBE/JNA JS CF=1 JA/JNBE CF=0且ZF=0 JNC CF=0 JAE/JNB CF=0或ZF=1 JZ/JE ZF =1 JB/JNAE CF=1且ZF=0 JNZ/JNE ZF =0 JBE/JNA CF=1或ZF=1 JS SF =1 JG/JNLE SF=OF且ZF=0 JNS SF=0 JGE/JNL SF=OF或ZF=1 JP/JPE PF =1 JL/JNGE SF≠OF且ZF=0 JNP/JPO PF =0 JLE/JNG SF≠OF或ZF=1 JO OF =1 JCXZ CX=0 JNO OF =0 实际虽然指令只有19条,但却有31个助记符 采用多个助记符,只是为了方便记忆和使用
判断单个标志位状态 这组指令单独判断5个状态标志之一 ⑴JZ/JE和JNZ/JNE:利用零标志ZF,判断结果是否为零 (或相等) ⑵JS和JNS:利用符号标志SF,判断结果是正是负 ⑶JO和JNO:利用溢出标志OF,判断结果是否产生溢出 ⑷JP/JPE和JNP/JPO:利用奇偶标志PF,判断结果中 “1”的个数是偶是奇 ⑸JC和JNC:利用进位标志CF,判断结果是否进位或借 位 例 题 例 题 例 题 例 题 例 题
2.条件转移指令— JZ/JNZ指令 REPZ CMPSB ;重复比较两个字符 JNZ UNMAT ;ZF=0(不等),转移 MOV AL,0 ;顺序执行(相等) JMP OUTPUT UNMAT: MOV AL,0FFH OUTPUT: MOV RESULT,AL JZ MAT ;ZF=1(相等),转移 MOV AL,0FFH ;顺序执行(不等) MAT: MOV AL,0
2. 条件转移指令— JS/JNS指令 计算|X-Y|(绝对值)。X和Y为存放于X单元和Y单元的16位操作数,结果存入RESULT。 MOV AX,X SUB AX,Y JNS NONNEG NEG AX NONNEG: MOV RESULT,AX
2.条件转移指令— JO/JNO指令 计算X-Y。X和Y为存放于X单元和Y单元的16位操作数,若溢出,则转移到OVERFLOW处理 MOV AX,X SUB AX,Y JO OVERFLOW ... ;无溢出,结果正确 OVERFLOW: ... ;有溢出处理
2.条件转移指令— JP/JNP指令 设字符的ASCII码在AL寄存器中。将字符加上奇校验位:在字符ASCII码中为“1”的个数为奇数时令其最高位为“0”,否则令最高位为“1” AND AL,7FH;最高位置“0”,同时判断“1”的个数 JNP NEXT ;个数已为奇数,则转向NEXT OR AL,80H ;否则,最高位置“1” NEXT: ...
2.条件转移指令— JC/JNC指令 记录BX中1的个数 XOR AL,AL ;AL=0,CF=0 AGAIN: TEST BX,0FFFFH ;等价于 CMP BX,0 JZ NEXT SHL BX,1 JNC AGAIN INC AL JMP AGAIN NEXT: ... ;AL保存1的个数
2.条件转移指令 —无符号数的比较 无符号数的大小用高(Above)低(Below)表示 2.条件转移指令 —无符号数的比较 无符号数的大小用高(Above)低(Below)表示 利用CF确定高低、利用ZF标志确定相等(Equal) 两数的高低分成4种关系: ⑴高于(不低于等于): JA ( JNBE ) ⑵高于等于(不低于): JAE ( JNB ) ⑶低于(不高于等于): JB(JNAE) ⑷低于等于(不高于): JBE(JNA)
2. 条件转移指令 —无符号数的比较(例) CMP AX,BX ;比较AX和BX JAE NEXT ;若AX≥BX,转移 2. 条件转移指令 —无符号数的比较(例) CMP AX,BX ;比较AX和BX JAE NEXT ;若AX≥BX,转移 XCHG AX,BX ;若AX<BX,交换 NEXT: ... 结果:AX保存较大的无符号数
2. 条件转移指令 —有符号数的比较 有符号数的大(Greater)小(Less)需要组合OF、SF标志,并利用ZF标志确定相等(Equal) 两数的大小分成4种关系: ⑴ 小于(不大于等于):JL(JNGE) ⑵小于等于(不大于):JLE(JNG) ⑶大于(不小于等于): JG ( JNLE ) ⑷大于等于(不小于): JGE ( JNL )
2. 条件转移指令 —有符号数的比较(例) CMP AX,BX ;比较AX和BX JGE NEXT ;若AX≥BX,转移 2. 条件转移指令 —有符号数的比较(例) CMP AX,BX ;比较AX和BX JGE NEXT ;若AX≥BX,转移 XCHG AX,BX ;若AX<BX,交换 NEXT: ... 结果:AX保存较大的有符号数
2. 条件转移指令 —计数器CX为0转移 JCXZ label ;CX=0,发生转移:IP←IP+8位位移量 ;CX≠0,顺序执行
§5.2 循环程序设计 一、循环程序的结构形式 二、循环程序设计 三、多重循环程序设计
一、循环程序的结构形式 初始化 循环的初始状态 循环体 循环的工作部分 及修改部分 修改部分 计数控制循环 Y 条件控制循环 控制条件 N 结束 初始化 循环的初始状态 循环体 循环的工作部分 及修改部分 计数控制循环 条件控制循环 修改部分 控制条件 Y N 先循环,后判断
一、循环程序的结构形式 初始化 循环的初始状态 N 计数控制循环 条件控制循环 控制条件 Y 结束 循环体 循环的工作部分 及修改部分 先判断,后循环
二、循环程序设计(例) .model small .stack 256 .data sum dw ? .code .startup mov sum,ax ;将累加和送入指定单元 .exit 0 end xor ax,ax ;被加数ax清0 mov cx,100 again: add ax,cx ;从100,99,...,2,1倒序累加 loop again
循环次数固定,完全由循环计数器控制 例5.2 在ADDR单元存放着数Y的地址,试编制一程序把Y中1的个数存入COUNT单元中 Y 开始 1的个数计数器←0 循环次数计数器CX←16 Y左移一次 CF=1 1的个数计数器+1 CX ←CX-1=0 COUNT ← 1的个数计数器 结束 N Y 例5.2 在ADDR单元存放着数Y的地址,试编制一程序把Y中1的个数存入COUNT单元中 循环次数固定,完全由循环计数器控制
例5.2 DATA SEGMENT Y DW 1234H ADDR DW Y COUNT DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV DL,0 MOV BX,ADDR MOV AX,[BX] MOV CX,16 REPEAT: SHL AX,1 JNC NEXT INC DL NEXT: LOOP REPEAT EXIT0: MOV COUNT,DL MOV AH,4CH INT 21H CODE ENDS END START
例5.2 Y 开始 1的个数计数器←0 循环次数计数器CX←16 Y=0 Y左移一次 N CF=1 1的个数计数器+1 CX ←CX-1=0 COUNT ← 1的个数计数器 结束 N Y Y=0 例5.2
例5.2 DATA SEGMENT Y DW 1234H ADDR DW Y COUNT DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV DL,0 MOV BX,ADDR MOV AX,[BX] MOV CX,16 REPEAT: SHL AX,1 JNC NEXT INC DL NEXT: LOOP REPEAT EXIT0: MOV COUNT,DL ADD DL,30H MOV AH,2 INT 21H MOV AH,4CH CODE ENDS END START CMP AX,0 JZ EXIT0 JMP REPEAT
例5.4 将正数N插入一个已升序排列的字数组的正确位置。该数组的首地址和末地址分别为ARRAY_ HEAD 和ARRAY_ END,其中所有的数均为正数。 23, 37, 49, 52 32 END HEAD 23, 37, 49, 52 32, -1, -1, 解法一: 从数组的尾部开始比较 N较大,则在比较对象后插入,结束循环 N较小,则把比较对象及其后元素后移一个字 循环结束的控制: 执行插入操作后结束循环 若N比所有元素都小,扫描整个数组后仍无法结束循环,将-1加在数组前可解决该问题
例5.4 开始 (ARRAY_HEAD-2)←-1 初始化变址寄存器SI K<=N 将N放在K的后面 K后移一个字单元 结束 修改地址
例5.4 MOV AX,N DATAREA SEGMENT MOV ARRAY_HEAD-2,-1 X DW ? MOV SI,0 COMP:CMP ARRAY_END[SI],AX JLE INSERT MOV BX,ARRAY_END[SI] MOV ARRAY_END[SI+2],BX SUB SI,2 JMP COMP INSERT: MOV ARRAY_END[SI+2],AX RET MAIN ENDP PROGRAM ENDS END START DATAREA SEGMENT X DW ? ARRAY_HEAD DW 3,5,15,23,37,49 ARRAY_END DW 105 N DW 32 DATAREA ENDS PROGRAM SEGMENT MAIN PROC FAR ASSUME CS:PROGRAM,DS:DATAREA START: PUSH DS SUB AX,AX PUSH AX MOV AX,DATAREA MOV DS,AX MOV BX,ARRAY_END[SI] CMP BX,AX JLE INSERT
例5.4 将正数N插入一个已升序排列的字数组的正确位置。 该数组的首地址和末地址分别为ARRAY_ HEAD 和ARRAY_ END,其中所有的数均为正数。 解法二: 从数组的头部开始比较 N较小,则在比较对象前插入,结束循环 N较大,则把比较对象及其前元素前移一个字 可扫描整个数组,循环次数为数组元素个数 执行插入操作后结束循环 循环结束的控制: 若N比所有元素都小,形成新的头;若N比所有元素都大,则被置于尾部
MOV AX,N MOV SI,0 MOV CX,COUNT REPEAT: MOV BX,ARRAY_HEAD[SI] CMP BX,AX JAE INSERT ;N较小,则转插入操作 MOV ARRAY_HEAD[SI-2],BX ;数组元素前移1字单元 INC SI LOOP REPEAT INSERT: MOV ARRAY_HEAD[SI-2],AX ;将N加入到数组中 MOV AX,4C00H INT 21H MAIN ENDP CSEG ENDS END MAIN ;SET ENTRY POINT DSEG SEGMENT PARA 'DATA' DW ? ARRAY_HEAD DW 3,5,13H,23H,37H DW 49H,52H,65H,78H,99H,105H COUNT EQU ($-ARRAY_HEAD)/2 N DW 32H DSEG ENDS CSEG SEGMENT PARA 'CODE' ASSUME CS:CSEG ASSUME DS:DSEG,SS:SSEG MAIN PROC FAR ;make neccessary initalizalition MOV AX,DSEG MOV DS,AX MOV ES,AX
例5.5 设有数组X和Y,每个数组都有10个元素,完成以下计算: Z1=X1+Y1 Z2=X2+Y2 Z3=X3-Y3 Z4=X4-Y4 Z5=X5-Y5 Z6=X6+Y6 Z7=X7-Y7 Z8=X8-Y8 Z9=X9+Y9 Z10=X10+Y10 结果存入数组Z。 比例尺:0000000011011100B
MOV BX,0 MOV CX,10 MOV DX,FLAG NEXT: MOV AX,X[BX] SHR DX ,1 JC SUBTRACT ADD AX,Y[BX] JMP RESULT SUBTRACT : SUB AX,Y[BX] RESULT : MOV Z[BX],AX ADD BX,2 LOOP NEXT MOV AH,4CH INT 21H CODE ENDS END START DATA SEGMENT X DW 11,33,10,60,4,7,19,80,45,23 Y DW 44,5,2,90,78,32,12,10,100,98 Z DW 10H DUP(?) FLAG DW 0000000011011100B DATA ENDS STK SEGMENT STACK DW 20H DUP(0) STK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STK START: MOV AX,DATA MOV DS,AX
三、多重循环程序设计 例5.7 有一个首地址为A的N字数组,请编制程序使该数组中的数按照从大到小的次序整序 冒泡法从第一个元素开始,依次对相邻的两个元素进行比较,使前一个元素不小于后一个元素;将所有元素比较完之后,最小的元素排到了最后;然后,除掉最后一个元素之外的元素依上述方法再进行比较,得到次小的元素排在后面;如此重复,直至完成就实现元素从大到小的排序 这需要一个双重循环程序结构
冒泡法的排序 序号 数 比 较 遍 数 1 2 3 4 1 32 2 15 3 16 4 8 5 85 32 16 15 85 8
CSEG SEGMENT PARA ‘CODE’ ASSUME CS:CSEG, DS:DSEG,SS:SSEG MAIN PROC FAR ;MAKE NECCESSARY INITALIZALITION PUSH DS XOR AX,AX PUSH AX MOV AX,DSEG MOV DS,AX MOV ES,AX MOV CX,N DEC CX LOOP1: MOV DI,CX ;保存计数器 MOV BX,0 ;数组地址指针清零 LOOP2: MOV AX,A[BX] CMP AX,A[BX+2] JGE COTINUE XCHG A[BX+2],AX ;交换 MOV A[BX],AX COTINUE: ADD BX,2 ;修改数组指针 LOOP LOOP2 MOV CX,DI ;恢复循环计数器 LOOP LOOP1 RET MAIN ENDP CSEG ENDS END MAIN ;SET ENTRY POINT
CSEG SEGMENT PARA ‘CODE’ ASSUME CS:CSEG, DS:DSEG,SS:SSEG MAIN PROC FAR ;MAKE NECCESSARY INITALIZALITION PUSH DS XOR AX,AX PUSH AX MOV AX,DSEG MOV DS,AX MOV ES,AX MOV CX,N DEC CX LOOP1: MOV DI,CX ;保存计数器 MOV BX,0 ;数组地址指针清零 MOV DL,0 LOOP2: MOV AX,A[BX] CMP AX,A[BX+2] JGE COTINUE XCHG A[BX+2],AX ;交换 MOV A[BX],AX INC DL ;交换次数计数器+1 COTINUE: ADD BX,2 ;修改数组指针 LOOP LOOP2 CMP DL,0 JZ EXIT0 ;数组已整序,则退出 MOV CX,DI ;恢复循环计数器 LOOP LOOP1 EXIT0: RET MAIN ENDP CSEG ENDS END MAIN ;SET ENTRY POINT
§5.3 分支程序设计 一、分支程序的结构形式 二、分支程序的设计 三、跳转表
一、分支程序的结构形式 AH=0 fuction0 N AH=1 AH=2 fuction1 fuction2 Y (C)多分支结构
分支程序的设计方法 例5.9 在附加段中,有一个按从小到大顺序排列的无符号数数组,其首地址存放在DI寄存器中,数组中的第一个单元存放着数组长度。在AX中有一无符号数,要求在数组中查找该数,如找到则使CF=0,并在SI中给出该元素的偏移地址;如未找到,则使CF=1。
跳跃表法 例5.10 试根据AL寄存器中哪一位为1(从低位到高位)把程序转移到8个不同的程序分支去。 跳转目标的地址在数据段中(5-10-1.asm) 跳转目标的地址在代码段中(5-10-2.asm)
SSEG SEGMENT PARA STACK 'STACK' DW 100H DUP(0) SSEG ENDS DSEG SEGMENT PARA 'DATA' TAB DW ROUTINE1 ;程序段1在代码段的偏移量 DW ROUTINE2 DW ROUTINE3 DW ROUTINE4 DW ROUTINE5 DW ROUTINE6 DW ROUTINE7 DW ROUTINE8 MESS DB 'THIS IS ROUTINE ' NUMBER DB 8 DB 0AH,0DH,'$' DSEG ENDS CSEG SEGMENT PARA 'CODE' ASSUME CS:CSEG, DS:DSEG,SS:SSEG MAIN PROC FAR MOV AX,DSEG ;make neccessary initalizalition MOV DS,AX MOV ES,AX MOV AL, NUMBER CMP AL,0 JE CONTINUE_MAIN_LINE ;AL值为0则继续运行主程序段 LEA BX,TAB LOP1: SHR AL,1 JNC NOT_YET JMP WORD PTR [BX] NOT_YET: ADD BX,TYPE TAB JMP LOP1 CONTINUE_MAIN_LINE: MOV AH,4CH INT 21H
EXIT: MOV DX,OFFSET MESS MOV AH,9 INT 21H JMP CONTINUE_MAIN_LINE ;MOV AH,0AH ;INT 21H ;RETURN DOS MOV AX,4C00H MAIN ENDP CSEG ENDS END MAIN ;SET ENTRY POINT ROUTINE1: MOV NUMBER, 31H JMP EXIT ROUTINE2: MOV NUMBER, 32H ROUTINE3: MOV NUMBER, 33H ROUTINE4: MOV NUMBER, 34H ROUTINE5: MOV NUMBER, 35H ROUTINE6: MOV NUMBER, 36H ROUTINE7: MOV NUMBER, 37H ROUTINE8: MOV NUMBER, 38H
MOV DX,OFFSET MESG1 MOV AH,9 INT 21H MOV AH,1 ;从键盘获得AL值 AND AL,0FH DEC AL ;计算表地址(号-1)*3 MOV BL,AL SHL BL,1 ADD BL,AL MOV BH,0 ADD BX,OFFSET TAB JMP BX TAB: JMP ROUTINE1 JMP ROUTINE2 JMP ROUTINE3 JMP ROUTINE4 JMP ROUTINE5 JMP ROUTINE6 JMP ROUTINE7 JMP ROUTINE8 JMP ROUTINE9 SSEG SEGMENT PARA STACK 'STACK' DW 100H DUP(0) SSEG ENDS DSEG SEGMENT PARA 'DATA' MESG1: DB 'PLEASE INPUT THE NUMBER:$' MESS DB 0AH,0DH,'THIS IS ROUTINE ' NUMBER DB ? DB 0AH,0DH,'$' DSEG ENDS CSEG SEGMENT PARA 'CODE' ASSUME CS:CSEG, DS:DSEG,SS:SSEG MAIN PROC FAR ;MAKE NECCESSARY INITALIZALITION MOV AX,DSEG MOV DS,AX MOV ES,AX
ROUTINE1: MOV NUMBER, 31H JMP EXIT ROUTINE2: MOV NUMBER, 32H ROUTINE3: MOV NUMBER, 33H ROUTINE4: MOV NUMBER, 34H ROUTINE5: MOV NUMBER, 35H ROUTINE6: MOV NUMBER, 36H ROUTINE7: MOV NUMBER, 37H ROUTINE8: MOV NUMBER, 38H ROUTINE9: MOV NUMBER, 39H EXIT: MOV DX,OFFSET MESS MOV AH,9 INT 21H ;MOV AH,0AH ;INT 21H ;RETURN DOS MOV AX,4C00H MAIN ENDP CSEG ENDS END MAIN ;SET ENTRY POINT