1、第四章 汇编语言程序设计 4-2 下列程序执行后,寄存器AX,BX,CX的内容分别是多少? D SEGMENT AT 0202H;定位数据段地址 ORG 0202H ;定位偏移地址 DA_WORD DW 20H MOV AX,DA_WORD ;(AX)=0020H MOV BX,OFFSET DA_WORD ;(BX)=0202H MOV CL,BYTE PTR DA_WORD ;(CL)=20H(将变量DA_WORD的属性改变为字节型) MOV CH,TYPE DA_WORD ;(CH)=2(变量类型数值)
2、 ;(CX)=0220H 4-4 试编制一程序,把CHAR1中各小写字母分别转换为对应的大写字母,并存放在CHAR2开始的单元中(题目要求:不改变CHAR1的内容) 方法1,小写字母转换一个输出显示一个,前3种方法均使用了AL寄存器 D SEGMENT CHAR1 DB "abcdefghijklmnopqrstuvwxyz" N EQU $-CHAR1;变量必须先定义后使用,而不能相反 CHAR2 DB N DUP(0) ; ;不能
3、把此句与上一句对调,CHAR2 DB $-CHAR1有;的同学这样写,错在哪 D ENDS S SEGMENT STACK DB 200 DUP(0) S ENDS C SEGMENT ASSUME CS:C,DS:D,SS:S ;ASSUME是伪指令,后面不能写冒号 START: MOV AX,D MOV DS,AX ;MOV ES,AX ;只要用到串操作指令且DI LEA SI,CHAR1
4、MOV SI,OFFSET CHAR1 LEA DI,CHAR2 ; MOV DI,OFFSET CHAR2 MOV CX,N ;$-CHAR1,不可以 AGAIN:MOV AL,[SI] SUB AL,20H ;AND AL,5FH 有的同学是这样实现的 MOV [DI],AL MOV DL,AL MOV AH,2 INT 21H ;从屏幕显示 INC SI INC DI LOOP AGAIN
5、 MOV AH,4CH INT 21H ; ;不是必须的 C ENDS END START 方法2:使用通用数据传送指令MOV D SEGMENT CHAR1 DB ‘abcdefghijklmnopqrstuvwxyz’ N EQU $-CHAR1;变量必须先定义后使用,而不能相反 CHAR2 DB N DUP(0);不能把此句与上一句对调
6、 D ENDS STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS ;P126(代码段和堆栈段是不可少的) C SEGMENT ASSUME CS:C ,DS:D ,SS:S START: MOV AX,D
7、 MOV DS,AX MOV ES,AX ;只要用到串操作指令且DI MOV SI,0 ; MOV DI,0 ; MOV CX,N AGAIN: MOV AL,CHAR1[SI] ; SUB AL,20H20什么意思 MOV CHAR2[DI],AL ; INC SI
8、 INC DI LOOP AGAIN MOV AH,4CH INT 21H ;不是必须的 C ENDS END START 第3种方法:使用串的读写指令LODSB STOSB D SEGMENT
9、 CHAR1 DB ‘abcdef’ N EQU $-CHAR1 CHAR2 DB $-CHAR1 DUP(0) D ENDS STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS C SEGMENT ASSUM
10、E CS:C,DS:D,SS:S START: MOV AX,D MOV DS,AX MOV ES,AX MOV SI,OFFSET CHAR1 ;LEA SI,CHAR1 MOV DI, OFFSET CHAR2 ;LEA DI,CHAR2 MOV CX,N CLD ;不写(隐含)也是0(递增)但不能STD AGAIN: LODSB ;执行一次,隐含修改SI
11、 SUB AL,32 STOSB ;MOV [DI],AL;执行一次, 隐含修改DI INC DI LOOP AGAIN ;LOOP指令只修改CX,不管SI,DI MOV AH,4CH INT 21H ;不是必须的 C ENDS END STAR
12、T 第四种方法2006级,没有显示使用MOVSB指令 D SEGMENT CHAR1 DB "abcdefghijklmnopqrstuvwxyz" N EQU $-CHAR1 CHAR2 DB N DUP(0) D ENDS S SEGMENT STACK DB 200 DUP(0)
13、S ENDS C SEGMENT ASSUME CS:C,DS:D,SS:S START: MOV AX,D MOV DS,AX MOV ES,AX LEA SI,CHAR1 LEA DI,CHAR2 MOV CX,N AGAIN:MOVSB ; SUB [SI],20H DEC DI ; MOVSB
14、 SUB BYTE PTR[DI],20H ;LOOP AGAIN 错在哪里?结果如何? INC DI LOOP AGAIN MOV AH,4CH INT 21H C ENDS END START 方法5: 只用一个地址指针SI D SEGMENT CHAR1 DB "abcdefghijklmnopqrstuvwxyz" N
15、 EQU $-CHAR1 CHAR2 DB N DUP(0) D ENDS S SEGMENT STACK DB 200 DUP(0) S ENDS C SEGMENT ASSUME CS:C,DS:D,SS:S START: MOV AX
16、D MOV DS,AX MOV ES,AX MOV SI,0 MOV CX,N AGAIN:MOV AL,CHAR1[SI] ;只用一个地址指针,SI[CHAR1]是错误的 SUB AL,20H MOV CHAR2[SI],AL INC SI LOOP AGAIN int 3 MOV AH,4CH INT 21H C ENDS
17、 END START 有的同学按数据是由键盘录入的来考虑的,也可行,程序中还有不少问题 方法6:由键盘输入小写字母再转换输出,回车符也占一个字节,输入需要小写转换成大写字母的内容从输入串的第3个元素开始 D SEGMENT A DB"CHAR1",0DH,0AH,"$" B DB"CHAR2",0DH,0AH,"$" CHAR1 DB 11,?,11 DUP(0);准备输入10个小写字母 CHAR2 DB 10 DUP(0) D ENDS
18、 S SEGMENT STACK DB 200 DUP(0) S ENDS C SEGMENT ASSUME CS:C,DS:D,SS:S START: MOV AX,D MOV DS,AX MOV ES,AX MOV DX,OFFSET A MOV AH,9 INT 21H LEA DX,CHAR1 MOV AH
19、0AH INT 21H ;由键盘输入字符串,10个字母(显示),1个回车,共11个字节 LEA SI,CHAR1[2] LEA DI,CHAR2 MOV CX,10 ;需要转换的字符长度为10个字节 AGAIN:MOV AL,[SI] SUB AL,20H MOV [DI],AL INC SI INC DI LOOP AGAIN ; 将小写字母字符串转换成大写字母字符串 MOV BYTE PTR[DI],0DH INC DI MOV BYTE PTR[DI]
20、0AH INC DI MOV BYTE PTR[DI],'$' ;必须指明数据类型 MOV DX,OFFSET CHAR2 MOV AH,9 INT 21H ;输出'$'结尾的大写字母字符串 int 3 MOV AH,4CH INT 21H C ENDS END START 4-6在BUF地址处起,存放有100个字节的字符串,设其中有一个以上的“A”字符,编程查找出第一个“A”字符相对起始地址的距离,并将其存
21、入LEN单元。 方法1,经过调试,数据串长N D SEGMENT BUF DB 'qasdA%^9F26HsdfhA$#12345678' DB 'DFGH234546JII2334JI5467OPPAVG' DB 'ASDFG45667RTY' ; 必须写实际的 N EQU $-BUF LEN DW 0;为变量LEN保留一个字,必须先定义后使用,LEN DW ? D ENDS S SEGMENT STACK DB 200 DUP(0) S ENDS C SEGM
22、ENT ASSUME CS:C,DS:D,SS:S START: MOV AX,D MOV DS,AX MOV ES,AX ;这条指令是必须的 MOV CX,N LEA DI,BUF ;MOV DI,OFFSET BUF MOV AL,41H ;MOV AL,‘A’ REPNE SCASB ;有的同学用的比较指令 MOV LEN,[DI
23、1]错在哪里 , MOV LEN,OFFSET BUF[DI-1]对不对 或LEA LEN,BUF[DI-1] MOV AH,4CH INT 21H C ENDS END START 4-8 某程序设置的数据区如下所示,画出该数据段内容在内存中的存放形式(要用十六进制补码表示,按字节组织) 12H 34H 00H 56H 78H 00H 90
24、H 00H 46H ABH 34H 12H 00H 00H 04H 00H 10H 00H 00H 00H 00H 00H 00H 0000H DB1 0004H DW1 000CH ADR1 000EH ADR2 0010H AAA 0012H BUF DATA SEGMENT DB1 DB 12H,34H,0,56H DW1 DW 78H,90H,0AB46H,1234H
25、 ADR1 DW DB1 ;取变量DB1的偏移地址 ADR2 DW DW1 ;;取变量DW1的偏移地址 AAA DW $-DB1 ;计算当前变量到DB1变量的字节数 BUF DB 5 DUP(0) DATA ENDS 有的同学认为0AB46H是负数,并取了它的补码
26、 2 4-10 以BUF1和BUF2开头的2个字符串,其长度均为LEN,试编程实现: (1)将BUF1开头的字符串送到BUF2开始的内存空间。 (2)将BUF1开始的内存空间全部清零。 经过调试的:方法1:数据段与附加段重叠,利用MOVSB指令实现数据传的复
27、制 D SEGMENT D1 DB 'BUF1QWE233459JKGHGFHGF';看清题目要求,写出实际内容对存储器初始化,分配内存空间,不能偷懒 LEN DB $-D1 D2 DB ' BUF2ASD33459JKGHGFHGFI';长度与D1相同 D ENDS S SEGMENT STACK DB 200 DUP(0) S ENDS C SEGMENT ASSUME CS:C,DS:D,SS:S STAR: MOV AX,D MOV
28、DS,AX MOV ES,AX ;附加段与数据段重叠,是允许的 LEA SI,D1 LEA DI,D2 MOV CX,LEN REP MOVSB LEA DI,D1 MOV CX,LEN ;这条语句不能少 MOV AL,00H ;MOV AX,0错在哪 REP STOSB MOV AH,4CH INT 21H C ENDS END STAR 经过调试的:方法2;数据段与附加段分开,串读一个写一个实现数据的传送,再利用串写指令使指定存储区清零 D SEGMENT D1 DB 'BUF1qasdA%^9F26Hsd
29、fhA$#12345678' LEN EQU $-D1 D ENDS E SEGMENT D2 DB "BUF2abcdefghijklmnopqrstuvwxyz0" ; 必须写实际的, ;与D1长度相同 E ENDS S SEGMENT STACK DB 200 DUP(0) S ENDS C SEGMENT ASSUME CS:C,DS:D,SS:S START: MOV AX,D
30、 MOV DS,AX MOV AX,E MOV ES,AX MOV CX,N LEA SI,D1 ;MOV SI,OFFSET D1 LEA DI,D2 LP: LODSB STOSB LOOP LP ;LOOP只是使CX减1,不改变SI DI LEA DI,D1 MOV CX,N ;这条语句不能少 MOV AL,00H REP STOSB MOV AH,4CH IN
31、T 21H C ENDS END START 第3种做法:传送一个字节清零一个字节,再向下一个字节进行 D SEGMENT D1 DB 'BUF1QWE233459JKGHGFHGF';看清题目要求,写出实际内容对存储器初始化,分配内存空间,不能偷懒 LEN DB $-D1 D2 DB ' BUF2ASD33459JKGHGFHGFI';长度与D1相同 D ENDS S SEGMENT STACK DB 200 DUP(0) S ENDS C SEGMEN
32、T ASSUME CS:C,DS:D,SS:S STAR: MOV AX,D MOV DS,AX MOV ES,AX LEA SI,D1 LEA DI,D2 MOV CX,LEN NEXT:MOV AL,[SI] MOV [DI],AL MOV [SI],00H INC SI INC DI LOOP NEXT MOV AH,4CH INT 21H CSEG ENDS END STAR 方法4;4-10-4从键盘输入初值,并显示 D SEGMENT BUF1
33、 DB 101,?,101 DUP(0) BUF2 DB 100 DUP(0) BUF3 DB 100 DUP(0) A DB 'BUF1',0DH,0AH,'$' B DB 'BUF2',0DH,0AH,'$' D ENDS S SEGMENT STACK DB 200 DUP(0) S ENDS C SEGMENT ASSUME CS:C,DS:D,SS:S START: MOV AX,D
34、 MOV DS,AX MOV ES,AX MOV DX,OFFSET A MOV AH,9 INT 21H ;输出显示'BUF1' MOV DX,OFFSET BUF1 MOV AH,0AH INT 21H ;键盘输入字符串 MOV CL,[BUF1+1] ;实际输入的字符串长度送CL,取相应单元的内容需加方括号 MOV CH,0 PUSH CX
35、 CLD LEA SI,BUF1+2 LEA DI,BUF2 REP MOVSB ;将输入的字符串传送到BUF2 MOV BYTE PTR[DI],0DH INC DI MOV BYTE PTR[DI],0AH INC DI MOV BYTE PTR[DI],'$';在BUF2末尾输入回车换行和‘$' MOV SI,OFFSET BUF3 MOV DI,OFFSET BUF1+
36、2;取变量的偏移地址,不能加方括号 POP CX REP MOVSB ;用BUF3替换BUF1 MOV BYTE PTR[DI],0DH INC DI MOV BYTE PTR[DI],0AH INC DI MOV BYTE PTR[DI],'$';在BUF1末尾输入回车换行和‘$' MOV DX,OFFSET A MOV AH,9 INT 21H ;输出显示’BUF1' MO
37、V DX,OFFSET BUF1+2 MOV AH,9 INT 21H ;输出空格,因为BUF1已经清零了 MOV DX,OFFSET B MOV AH,9 INT 21H ;输出显示’BUF2' MOV DX,OFFSET BUF2 MOV AH,9 INT 21H ;输出BUF2,即键盘输入的内容 MOV AH,4CH INT 21H C ENDS
38、 END START 4-14` 试编写一程序,找出BUF数据区中带符号数的最大数和最小数,把最大数放到BH单元,把最小数放到BL单元。 D SEGMENT BUF DB 5,90,-45,100,99,………,-12 N EQU $-BUF D ENDS STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS
39、 C SEGMENT ASSUME CS:C,DS:D,SS:S START: MOV AX,D MOV DS,AX MOV CX,N-1 MOV SI,0 MOV BH,BUF[SI] MOV BL,BUF[SI] AGAIN: INC SI CMP BH,BUF[SI] JGE NEXT ;JAE NEXT错(无符号数) MOV BH,BUF[SI] ABC: LOOP AGAIN
40、 ;这句不要也行 NEXT: CMP BL,BUF[SI] JLE ABC MOV BL,BUF[SI] LOOP AGAIN C ENDS END START 4-16 若AL中的内容为2位压缩的BCD数68H,试编程:(1)将其拆开成非压缩的BCD数,高低位分别存入BH和BL中。 (2)将上述要求的2位BCD码变换成对应的ASCII码,并且
41、存入CH和CL中。 方法1,经过调试的 S SEGMENT STACK DB 10 DUP(?) S ENDS C SEGMENT ASSUME CS:C,SS:S,DS:D STAR:MOV AX,D MOV DS,AX MOV AL,68H MOV BH,AL AND AL,0FH MOV BL,AL ;(BL)是低位非压缩的BCD码 AND BH,0F0H ;(BH)将是高位非压缩的BCD码 MOV CL,4 SHR BH,CL ; (BH)是高位非
42、压缩的BCD码 MOV CL,BL ADD CL,30H ;(CL)是低位ASCII码 MOV CH,BH ADD CH,30H ; (CH)是高位ASCII码 MOV AH,4CH INT 21H C ENDS END STAR 方法2 D SEGMENT D1 DB 1,2,3 D ENDS S SEGMENT STACK DB 10 DUP(?) S ENDS C SEGMENT ASSUME CS:C,SS:S,DS:D STAR:MOV AX,D MOV
43、DS,AX MOV SI,OFFSET D1 MOV DL,68H MOV AL,68H AND AL,0FH MUL BYTE PTR[SI] AAM ;乘法的ASCII码调整指令,P99 MOV BL,AL MOV BH,DL AND BH,0F0H MOV CL,4 SHR BH,CL MOV AL,BH MUL BYTE PTR[SI] AAM MOV BH,AL MOV CL,BL
44、 ADD CL,30H MOV CH,BH ADD CH,30H C ENDS END STAR 4-18试用子程序结构编写一程序:从键盘输入一个2位十进制的月份数(01~12),然后显示出相应的英文缩写名。 提示:根据题目要求实现的功能,可编写用一个主程序MAIN分别调用几个子程序。 (1) INPUT从键盘接收一个2位数,并把它转换为对应的二进制数。 (2) LOCATE 把输入的月份数与其英文缩写名(如JAN,FEB,MAR,APP,MAY,JUN等)对应起来,制成一个字符表以便查找。 (3) DISPLAY 将找到的缩写字母在屏幕上显示出
45、来,显示可用DOS所提供的显示功能(INT 21H的09号功能)。 方法1:与方法2的不同主要在数据表的制定 D SEGMENT D1 DB "Please input month from the keyboad",0DH,0AH,"$" D2 DB 4, ?,4 DUP(?);分配键盘输入缓冲区,回车符占一个字节,但实际输入的字符数中不包含它,即输入2位数至少需预留3个字节的空间,输入完成后,实际输入的字符数为2 D3 DB "ERROR",0DH,0AH,"$" MONTH0 DB "JAN",0DH,0AH,"$" D
46、B "FEB" ,0DH,0AH,"$" DB "MAR" ,0DH,0AH,"$" DB "APP" ,0DH,0AH,"$" DB "MAY" ,0DH,0AH,"$" DB "JUN" ,0DH,0AH,"$" DB "JUL" ,0DH,0AH,"$" DB "AUG" ,0DH,0AH,"$" DB "SEP" ,0DH,0AH,"$" DB "OCT" ,0DH,0AH,"$" DB "NOV" ,0DH,0AH,"$" DB "DEC" ,0DH,0AH,"$" D ENDS S SEGMENT STACK DB 20
47、0 DUP(0) S ENDS C SEGMENT ASSUME CS:C,DS:D,SS:S START:CLD MOV AX,D MOV DS,AX CALL INPUT CALL LOCATE CALL DISPLAY MOV AH,4CH INT 21H INPUT PROC NEAR LEA DX, D1 ;将D1表示的相对地址送DX
48、MOV AH,9 INT 21H ;显示‘Please input month from the keyboad’并换行 ww2:LEA DX,D2 ;输入月份 MOV AH,0AH INT 21H LEA DI,D2 ;将D2表示的相对地址送DI CMP byte ptr [DI+1],2 JNE ww2 ;输入的如果不是二位数,是错误 MOV AH,[DI+2];输入的月份高字节(十位数) MOV AL,[DI+3];输
49、入的月份低字节(个位数) XOR AX,3030H ;将ASCII码变成BCD码 MOV BX,AX MOV AL,BH mov dl,0ah MUL dl ;变成二进制数 MOV BH,AL MOV AL,BL ;输入的月份低字节(个位数) ADD AL,BH ;AL=1-12 RET ;是必须的 INPUT ENDP ;是必须的 LOCATE PROC NEAR DEC AL CMP AL,0CH JNC ERROR ;≥12(正确的情况应该是0-11),输入错误 MOV BL,06H MUL BL LEA
50、SI,MONTH0 ADD SI,AX MOV DX,SI;制成一个字符表以便查找。 RET ERROR:LEA DX,D3 ;将D3表示的相对地址送DX RET LOCATE ENDP DISPLAY PROC NEAR MOV AH,09H;将找到的缩写字母在屏幕上显示出来 INT 21H RET DISPLAY ENDP C ENDS END START 方法2:数据表的制定与方法1有所不同 D SEGMENT D1 DB "Please input month from the






