1、第六章答案 = 1.下面的程序段有错吗?若有,请指出错误. CRAY PROC PUSH AX ADD AX,BX RET ENDP CRAY 解:当然有错误,ENDP CRAY 写反了,应该将其改成 CRAY ENDP. 2.已知堆栈寄存器 SS的内容是 0F0A0H,堆栈指示器 SP的内容是 00B0H,先执行 两条把 8057H和 0F79BH分别入栈的 PUSH指令.然后再执行一 POP指令.试画出 示意图说明堆栈及 SP内容的变化过程. 3.分析下面“6,3 的程序“,画出堆栈最满时各单元的地址及内容. ; 6.3题的程序 ;= S_SEG SEGMENT AT 1000H ;DEF
2、INE STACK SEGMENT DW 200 DUP(?) TOS LABEL WORD S_SEG ENDS C_SEG SEGMENT ;DEFINE CODE SEGMENT ASSUME CS:C_SEG,SS:S_SEG MOV AX,S_SEG MOV SS,AX MOV SP,OFFSET TOS PUSH DS MOV AX,0 PUSH AX . PUSH T_ADDR PUSH AX PUSHF . POPF POP AX POP T_ADDR RET C_SEG ENDS ;END OF CODE SEGMENT END C_SEG ;END OF ASSEMBLY
3、4.分析下面“6.4 题的程序“的功能,写出堆栈最满时各单元的地址及内容. ; 6.4题的程序 ;= STACK SEGMENT AT 500H DW 128 DUP(?) TOS LABEL WORD STACK ENDS CODE SEGMENT ;DEFINE CODE SEGMENT MAIN PROC FAR ;MAIN PART OF PROGRAM ASSUME CS:CODE,SS:STACK START: ;STARTING EXECUTION ADDRESS MOV AX,STACK MOV SS,AX MOV SP,OFFSET TOS PUSH DS SUB AX,AX
4、 PUSH AX ;MAIN PART OF PROGRAM GOES HERE MOV AX,4321H CALL HTOA RET ;RETURN TO DOS MAIN ENDP ;END OF MAIN PART OF PROGRAM HTOA PROC NEAR ;DEFINE SUBPROCEDURE HTOA CMP AX,15 JLE B1 PUSH AX PUSH BP MOV BP,SP MOV BX,BP+2 AND BX,000FH MOV BP+2,BX POP BP MOV CL,4 SHR AX,CL CALL HTOA POP AX B1: ADD AL,30H
5、 CMP AL,3AH JL PRINTIT ADD AL,07H PRINTIT: MOV DL,AL MOV AH,2 INT 21H RET HTOA ENDP ;END OF SUBPROCEDURE CODE ENDS ;END OF CODE SEGMENT END START ;END OF ASSEMBLY 5.下面是 6.5题的程序清单,请在清单中填入此程序执行过程中的堆栈变化. 0000 STACKSG SEGMENT 0000 20 . DW 32 DUP(?) ? 0040 STACKSG ENDS 0000 CODESG SEGMENT PARA CODE 0000
6、BEGIN PROC FAR ASSUME CS:CODESG,SS:STACKSG 0000 1E PUSH DS 0001 2B C0 SUB AX,AX 0003 50 PUSH AX 0004 E8 0008 R CALL P10 0007 CB RET 0008 BEGIN ENDP 0008 B10 PROC 0008 E8 000C R CALL C10 000B C3 RET 000C B10 ENDP 000C C10 PROC 000C C3 RET 000D C10 ENDP 000D CODESG ENDS END BEGIN 6.写一段子程序 SKIPLINES,完成
7、输出空行的功能.空行的行数在 AX寄存器中. 解: SKIPLINES PROC NEAR PUSH CX PUSH DX MOV CX,AX NEXT: MOV AH,2 MOV DL,0AH INT 21H MOV AH,2 MOV DL,0DH INT 21H LOOP NEXT POP DX POP CX RET SKIPLINES ENDP 7.设有 10个学生的成绩分别是 76,69,81,90,73,88,99,63,100和 80分.试编制 一个子程序统计 60-69,70-79,80-89,90-99和 100分的人数并分别存放到 S6,S7,S8,S9和 S10单元中. D
8、SEG SEGMENT NUM DW 76,69,84,90,73,88,99,63,100,80 N DW 10 S6 DW 0 S7 DW 0 S8 DW 0 S9 DW 0 S10 DW 0 DSEG ENDS CODE SEGMENT MAIN PROC FAR ASSUME CS:CODE, DS:DSEG START: PUSH DS SUB AX, AX PUSH AX MOV AX, DSEG MOV DS, AX CALL SUB1 RET MAIN ENDP SUB1 PROC NEAR PUSH AX PUSH BX PUSH CX PUSH SI MOV SI, 0 M
9、OV CX, N NEXT: MOV AX, NUMSI MOV BX, 10 DIV BL MOV BL, AL CBW SUB BX, 6 SAL BX, 1 INC S6BX ADD SI,2 LOOP NEXT POP SI POP CX POP BX POP AX RET SUB1 ENDP CODE ENDS END START (解法二) datasg segment grade db 76,69,84,90,73,88,99,63,100,80 s6 db 0 s7 db 0 s8 db 0 s9 db 0 s10 db 0 mess6 db 6069:$ mess7 db 7
10、079:$ mess8 db 8089:$ mess9 db 9099:$ mess10 db 100:$ datasg ends codesg segment main proc far assume cs:codesg,ds:datasg start: push ds sub ax,ax push ax mov ax,datasg mov ds,ax call sub1 lea dx,mess6 call dispstr mov dl,s6 call dispscore call crlf lea dx,mess7 call dispstr mov dl,s7 call dispscore
11、 call crlf lea dx,mess8 call dispstr mov dl,s8 call dispscore call crlf lea dx,mess9 call dispstr mov dl,s9 call dispscore call crlf lea dx,mess10 call dispstr mov dl,s10 call dispscore call crlf ret main endp sub1 proc near mov cx,10 mov si,0 loop1: mov al,gradesi cmp al,60 jl next5 cmp al,70 jge n
12、ext1 inc s6 jmp short next5 next1: cmp al,80 jge next2 inc s7 jmp short next5 next2: cmp al,90 jge next3 inc s8 jmp short next5 next3: cmp al,100 jg next5 je next4 inc s9 jmp short next5 next4: inc s10 next5: inc si loop loop1 ret sub1 endp dispstr proc near mov ah,9 int 21h dispstr endp dispscore p
13、roc near add dl,30h mov ah,2 int 21h dispscore endp crlf proc near mov dl,0dh mov ah,2 int 21h mov dl,0ah mov ah,2 int 21h ret crlf endp codesg ends end start 8.编写一个有主程序和子程序结构的程序模块.子程序的参数是一个 N字节数组 的首地址 TABLE,数 N及字符 CHAR.要求在 N字节数组中查找字符 CHAR,并记录 该字符的出现次数.;主程序则要求从键盘接收一串字符以建立字节数组 TABLE, 并逐个显示从键盘输入的每个字符
14、CHAR以及它在 TABLE数组中出现的次数.(为 简化起见,假设出现次数=15,可以用十六进制形式显示出来) 解: DATA SEGMENT MAXLEN DB 40 N DB ? TABLE DB 40 DUP (?) CHAR DB A ; 查找字符A EVEN _ADDR DW 3 DUP(?) DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA MAIN PROC FAR START: PUSH DS MOV AX, 0 PUSH AX MOV AX, DATA MOV DS, AX LEA DX, MAXLEN MOV AH, 0AH IN
15、T 21H ; 从键盘接收字符串 MOV _ADDR, OFFSET TABLE MOV _ADDR+2, OFFSET N MOV _ADDR+4, OFFSET CHAR MOV BX, OFFSET _ADDR ; 通过地址表传送变量地址 CALL COUNT ; 计算 CHAR的出现次数 CALL DISPLAY ; 显示 RET MAIN ENDP COUNT PROC NEAR ; COUNT子程序 PUSH SI PUSH DI PUSH AX PUSH CX MOV DI, BX MOV SI, BX+2 MOV CL, BYTE PTRSI MOV CH, 0 MOV SI,
16、 BX+4 MOV AL, BYTE PTRSI MOV BX, 0 AGAIN: CMP AL, BYTE PTRDI JNE L1 INC BX L1: INC DI LOOP AGAIN POP CX POP AX POP DI POP SI RET COUNT ENDP DISPLAY PROC NEAR ; DISPLAY子程序 CALL CRLF ; 显示回车和换行 MOV DL, CHAR MOV AH, 2 INT 21H MOV DL, 20H MOV AH, 2 INT 21H MOV AL, BL AND AL, 0FH ADD AL, 30H CMP AL, 3AH J
17、L PRINT ADD AL, 7 PRINT: MOV DL, AL INT 21H CALL CRLF RET DISPLAY ENDP CRLF PROC NEAR ; CRLF子程序 MOV DL, 0DH MOV AH, 2 INT 21H MOV DL, 0AH MOV AH, 2 INT 21H RET CRLF ENDP CODE ENDS END START 9.编写一个子程序嵌套结构的程序模块,分别从键盘输入姓名及 8个字符的电话 号码,并以一定的格式显示出来. 主程序 TELIST: (1)显示提示符 INPUT NAME:; (2)调用子程序 INPUT_NAME输入姓
18、名: (3)显示提示符 INPUT A TELEPHONE NUMBER:; (4)调用子程序 INPHONE输入电话号码; (5)调用子程序 PRINTLINE显示姓名及电话号码; 子程序 INPUT_NAME: (1)调用键盘输入子程序 GETCHAR,把输入的姓名存放在 INBUF缓冲区中; (2)把 INBUF中的姓名移入输出行 OUTNAME; 子程序 INPHONE: (1)调用键盘输入子程序 GETCHAR,把输入的 8位电话号码存放在 INBUF缓冲区 中; (2)把 INBUF中的号码移入输出行 OUTPHONE. 子程序 PRINTLINE: 显示姓名及电话号码,格式为:
19、NAME TEL * * = ;编写一个子程序嵌套结构的程序模块,分别从键盘输入姓名及 8个字符的电话 号码,并以一定的格式显示出来 (解法一) data segment No_of_name db 20 No_of_phone db 8 inbuf db 20 dup(?) outname db 20 dup(?),$ outphone db 8 dup(?),$ message1 db please input name:,$ message2 db please input a telephone number:,$ message3 db NAME,16 dup(20h),TEL.,1
20、3,10,$ errormessage1 db you should input 8 numbers!,13,10,$ errormessage2 db you input a wrong number!,13,10,$ flag db ? data ends prog segment main proc far assume cs:prog,ds:data start: push ds sub ax,ax push ax mov ax,data mov ds,ax mov flag,0 lea dx,message1 mov ah,09 int 21h call input_name cal
21、l crlf lea dx,message2 mov ah,09 int 21h call inphone call crlf cmp flag,1 je exit call printline exit: ret main endp input_name proc near push ax push dx push cx mov cx,0 mov cl,No_of_name call getchar mov ax,0 mov al,No_of_name sub ax,cx mov cx,ax mov si,0 next1: mov al,inbufsi mov outnamesi,al in
22、c si loop next1 pop cx pop dx pop ax ret input_name endp inphone proc near push ax push dx mov cx,0 mov cl,No_of_phone call getchar cmp cx,0 jnz error1 mov cl,No_of_phone mov si,0 next2: mov al,inbufsi cmp al,30h jl error2 cmp al,39h ja error2 mov outphonesi,al inc si loop next2 jmp exit2 error1: ca
23、ll crlf lea dx,errormessage1 mov ah,09 int 21h mov flag,1 jmp exit2 error2: call crlf lea dx,errormessage2 mov ah,09 int 21h mov flag,1 jmp exit2 exit2: pop dx pop ax ret inphone endp getchar proc near push ax push dx mov di,0 rotate: mov ah,01 int 21h cmp al,0dh je exit1 mov inbufdi,al inc di loop
24、rotate exit1: pop dx pop ax ret getchar endp crlf proc near push ax push dx mov dl,0dh mov ah,2 int 21h mov dl,0ah mov ah,2 int 21h pop dx pop ax ret crlf endp printline proc near push ax push dx lea dx,message3 mov ah,09 int 21h lea dx,outname mov ah,09 int 21h lea dx,outphone mov ah,09 int 21h pop
25、 dx pop ax ret printline endp prog ends end main = ;从键盘输入姓名及 8个字符的电话号码,并以一定的格式显示出来 datarea segment inbuf label byte ;name parameter list: maxnlen db 9 ;max.length namelen db ? ;no. char entered namefld db 9 dup(?) crlf db 13,10,$ messg1 db INPUT NAME:,13,10,$ messg2 db INPUT A TELEPHONE NUMBER:,13,1
26、0,$ messg3 db NAME TEL,13,10,$ OUTNAME db 21 dup(?),$ OUTPHONE db 8 dup(?),$ datarea ends prognam segment assume cs:prognam,ds:datarea start: push ds sub ax,ax push ax mov ax,datarea mov ds,ax mov es,ax TELIST proc far mov ah,09 lea dx,messg1 int 21h call INPUT_NAME mov ah,09 lea dx,messg2 int 21h c
27、all INPHONE call PRINTLINE ret TELIST endp INPUT_NAME proc near call GETCHAR mov bh,0 mov bl,namelen mov cx,21 sub cx,bx b20: mov namefldbx,20h inc bx loop b20 lea si,namefld lea di,OUTNAME mov cx,9 cld rep movsb ret INPUT_NAME endp INPHONE proc near call GETCHAR mov bh,0 mov bl,namelen mov cx,9 sub
28、 cx,bx b30: mov namefld bx,20h inc bx loop b30 lea si,namefld lea di,OUTPHONE mov cx,8 cld rep movsb ret INPHONE endp PRINTLINE proc near mov ah,09h lea dx,messg3 int 21h mov ah,09 lea dx,OUTNAME int 21h mov ah,09 lea dx,OUTPHONE int 21h ret PRINTLINE endp GETCHAR proc near mov ah,0ah lea dx,inbuf i
29、nt 21h mov ah,09 lea dx,crlf int 21h ret GETCHAR endp prognam ends end start = 10.编写子程序嵌套结构的程序,把整数分别用二进制和八进制形式显示出来.主 程序 BANDO:把整数字变量 VAL1存入堆栈,并调用子程序 PAIRS;子程序 PAIRS: 从堆栈中取出 VAL1;调用二进制显示程序 OUTBIN显示出与其等效的二进制数; 输出 8个空格;调用八进制显示程序 OUTOCT显示出与其等效的八进制数;调用输 出回车及换行符的子程序. .model small .stack 100h .data val1 dw
30、 0ffffh .code main proc far start: push ds sub ax,ax push ax mov ax,data mov ds,ax push val1 call pairs ret main endp pairs proc near push bp mov bp,sp mov bx,bp+4 call outbin mov cx,8 loop1: mov dl,20h mov ah,2 int 21h loop loop1 call outoct call crlf pop bp ret 2 pairs endp outbin proc near mov cx
31、,16 loop2: mov dl,0 rol bx,1 rcl dl,1 or dl,30h mov ah,2 int 21h loop loop2 ret outbin endp outoct proc near mov dl,0 rol bx,1 rcl dl,1 add dl,30h mov ah,2 int 21h mov ch,5 mov cl,3 loop3: rol bx,cl mov al,bl and al,07h add al,30h mov dl,al mov ah,2 int 21h dec ch jnz loop3 ret outoct endp crlf proc
32、 near mov dl,13 mov ah,2 int 21h mov dl,10 mov ah,2 int 21h ret crlf endp end start 11.假定一个名为 MAINPRO的程序要调用子程序 SUBPRO,试问: (1)MAINPRO中的什么指令告诉汇编程序 SUBPRO是在外部定义的? (2)SUBPRO怎么知道 MAINPRO要调用它? 解: (1)EXTRN SUBPRO: FAR (2)PUBLIC SUBPRO 12.假定程序 MAINPRO和 SUBPRO不在同一模块中,MAINPRO 中定义字节变量 QTY 和字变量 VALUE和 PRICE.SUB
33、PRO程序要把 VALUE除以 QTY,并把商存在 PRICE 中,试问: (1)MAINPRO怎么告诉汇编程序外部子程序要调用这三个变量? (2)SUBPRO怎么告诉汇编程序这三个变量是在另一个汇编语言程序中定义的? 解: (1)PUCLIC QTY,VALUE,PRICE (2)EXTRN QTY: BYTE, VALUE: WORD, PRICE: WORD 13.假设: (1)在模块 1中定义了双字变量 VAR1,首地址为 VAR2的字节数组和 NEAR标号 LAB1,它们将由模块 2和模块 3所使用; (2)在模块 2中定义了字变量 VAR3和 FAR标号 LAB2,而模块 1中要用
34、到 VAR3,模 块 3中要用到 LAB2; (3)在模块 3中定义了 FAR标号 LAB3,而模块 2中要用到它. 试对每个源模块给出必要的 EXTRN和 PUBLIC说明. ;模块 1 extrn var3:word public var1,var2,lab1 data1 segment var1 dd ? var2 db 10 dup(?) data1 ends code1 segment assume cs:code1, ds:data1 main proc far mov ax,data1 mov ds,ax . . . lab1: . . . mov ax,4c00h int 21
35、h main endp code1 ends end start ;模块 2 extrn var1:dword,var2:byte,lab1:near,lab3:far public var3,lab2 data2 segment var3 dw ? data2 ends code2 segment assume cs:code2, ds:data2 . . . lab2: . . . code2 ends end ;模块 3 extrn var1:dword,var2:byte,lab1:near,lab2:far public lab3 code3 segment assume cs:co
36、de3 . . . lab3: . . . code3 ends end 14.主程序 CALLMUL定义堆栈段,数据段和代码段,并把段寄存器初始化;数据段 中定义变量 QTY和 PRICE;代码段中将 PRICE装入 AX,QTY装入 BX,然后调用子程 序 SUBMUL.程序 SUBMUL没有定义任何数据,它只简单地把 AX中的内容(PRICE) 乘以 BX中的内容(QTY),乘积放在 DX,AX中.请编制这两个要连接起来的程序. datasg segment qty dw 2 price dw 4 datasg ends stacksg segment dw 100 dup(?) tos
37、 label word stacksg ends codesg segment main proc far assume cs:codesg,ds:datasg,ss:stacksg start: mov ax,datasg mov ds,ax mov ax,stacksg mov ss,ax mov sp,offset tos mov ax,price mov bx,qty call submul mov ax,4c00h int 21h main endp submul proc near mov dx,0 mul bx ret submul endp codesg ends end st
38、art 15.试编写一个执行以下计算的子程序 COMPUTE: R-X+Y-3 其中 X,Y及 R均为字数组.假设 COMPUTE与其调用程序都在同一代码段中,数据 段 D_SEG中包含 X和 Y数组,数据段 E_SEG中包含 R数组,同时写出主程序调用 COMPUTE过程的部分. 如果主程序和 COMPUTE在同一程序模块中,但不在同一代码段中,程序就如何修 改? 如果主程序和 COMPUTE不在同一程序模块中,程序就如何修改? (1) d_seg segment x dw 1 y dw 4 d_seg ends e_seg segment r dw ? e_seg ends c_seg s
39、egment main proc far assume cs:c_seg,ds:d_seg,es:e_seg start: mov ax,d_seg mov ds,ax mov ax,e_seg mov es,ax call compute mov ax,4c00h int 21h main endp compute proc near mov ax,x add ax,y sub ax,3 mov es:r,ax ret compute endp c_seg ends end start ;= (2) d_seg segment x dw 1 y dw 4 d_seg ends e_seg s
40、egment r dw ? e_seg ends c_seg segment main proc far assume cs:c_seg,ds:d_seg,es:e_seg start: mov ax,d_seg mov ds,ax mov ax,e_seg mov es,ax call far ptr compute mov ax,4c00h int 21h main endp c_seg ends prognam segment assume cs:prognam compute proc far mov ax,x add ax,y sub ax,3 mov es:r,ax ret com
41、pute endp prognam ends end start ;= (3) ;模块 1 extrn compute:far public x,y,r d_seg segment x dw 1 y dw 4 d_seg ends e_seg segment r dw ? e_seg ends c_seg segment main proc far assume cs:c_seg,ds:d_seg,es:e_seg start: mov ax,d_seg mov ds,ax mov ax,e_seg mov es,ax call far ptr compute mov ax,4c00h int 21h main endp c_seg ends end start ;模块 2 extrn x:word,y:word,r:word public compute prognam segment assume cs:prognam compute proc far mov ax,x add ax,y sub ax,3 mov es:r,ax ret compute endp prognam ends end