微机原理作业与答案第四章

更新时间:2023-11-12 11:37:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第四章 汇编语言程序设计

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(变量类型数值) ;(CX)=0220H

4-4 试编制一程序,把CHAR1中各小写字母分别转换为对应的大写字母,并存放在CHAR2开始的单元中(题目要求:不改变CHAR1的内容)

方法1,小写字母转换一个输出显示一个,前3种方法均使用了AL寄存器

D SEGMENT CHAR1 DB \

N EQU $-CHAR1;变量必须先定义后使用,而不能相反 CHAR2 DB N DUP(0) ; ;不能把此句与上一句对调,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 ;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 MOV AH,4CH

INT 21H ; ;不是必须的

C ENDS

END START

方法2:使用通用数据传送指令MOV

D SEGMENT CHAR1 DB ‘abcdefghijklmnopqrstuvwxyz’

N EQU $-CHAR1;变量必须先定义后使用,而不能相反

CHAR2 DB N DUP(0);不能把此句与上一句对调 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

MOV DS,AX

MOV ES,AX ;只要用到串操作指令且DI MOV SI,0 ; MOV DI,0 ; MOV CX,N

AGAIN: MOV AL,CHAR1[SI] ;

SUB AL,20H MOV CHAR2[DI],AL ; INC SI

INC DI

LOOP AGAIN

MOV AH,4CH

INT 21H ;不是必须的

C ENDS

END START

第3种方法:使用串的读写指令LODSB STOSB

D SEGMENT CHAR1 DB ‘abcdef’ N EQU $-CHAR1

CHAR2 DB $-CHAR1 DUP(0) 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

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

SUB AL,32 STOSB ;MOV [DI],AL;执行一次, 隐含修改DI INC DI LOOP AGAIN ;LOOP指令只修改CX,不管SI,DI MOV AH,4CH

INT 21H ;不是必须的

C ENDS

END START

第四种方法2006级,没有显示使用MOVSB指令

D SEGMENT CHAR1 DB \N 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,D MOV DS,AX MOV ES,AX LEA SI,CHAR1 LEA DI,CHAR2 MOV CX,N

AGAIN:MOVSB ; SUB [SI],20H DEC DI ; MOVSB

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 \N 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,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

END START

有的同学按数据是由键盘录入的来考虑的,也可行,程序中还有不少问题

方法6:由键盘输入小写字母再转换输出,回车符也占一个字节,输入需要小写转换成大写字母的内容从输入串的第3个元素开始

D SEGMENT

A DB\

B DB\

CHAR1 DB 11,?,11 DUP(0);准备输入10个小写字母

CHAR2 DB 10 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,D MOV DS,AX MOV ES,AX

MOV DX,OFFSET A MOV AH,9 INT 21H

LEA DX,CHAR1 MOV AH,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],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”字符相对起始地址的距离,并将其存入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 SEGMENT 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-1]错在哪里 ,

MOV LEN,OFFSET BUF[DI-1]对不对 或LEA LEN,BUF[DI-1] MOV AH,4CH INT 21H

C ENDS

END START

4-8 某程序设置的数据区如下所示,画出该数据段内容在内存中的存放形式(要用十六进制补码表示,按字节组织) DATA SEGMENT 0000H DB1 12H DB1 DB 12H,34H,0,56H 34H 00H DW1 DW 78H,90H,0AB46H,1234H

56H ADR1 DW DB1 ;取变量DB1的偏移地址 0004H DW1 78H ADR2 DW DW1 ;;取变量DW1的偏移地址

00H AAA DW $-DB1 ;计算当前变量到DB1变量的字节数 90H BUF DB 5 DUP(0) 00H DATA ENDS 46H 有的同学认为0AB46H是负数,并取了它的补码 ABH 34H 12H 00H 2 000CH ADR1

00H 000EH ADR2 04H 00H 0010H AAA 10H 00H 0012H BUF 00H 00H

4-10 以BUF1和BUF2开头的2个字符串,其长度均为LEN,试编程实现: (1)将BUF1开头的字符串送到BUF2开始的内存空间。 (2)将BUF1开始的内存空间全部清零。

经过调试的:方法1:数据段与附加段重叠,利用MOVSB指令实现数据传的

复制

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 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%^9F26HsdfhA$#12345678' LEN EQU $-D1 D ENDS E SEGMENT

D2 DB \必须写

实际的,

;与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

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 INT 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 SEGMENT 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 DS,AX MOV AX,E

MOV ES,AX

MOV AH,4CH INT 21H

CSEG ENDS END STAR

方法4;4-10-4从键盘输入初值,并显示

D SEGMENT

BUF1 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

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 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+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' MOV 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 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

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 ;这句不要也行 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码,并且存入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)是高位非压缩的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 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 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 将找到的缩写字母在屏幕上显示出来,显示可用DOS所提供的显

示功能(INT 21H的09号功能)。

方法1:与方法2的不同主要在数据表的制定

D SEGMENT

D1 DB \keyboad\

D2 DB 4, ?,4 DUP(?);分配键盘输入缓冲区,回车符占一个字节,但实际输入的字符数中不包含它,即输入2位数至少需预留3个字节的空间,输入完成后,实际输入的字符数为2 D3 DB \MONTH0 DB \

DB \DB \DB \DB \DB \DB \

DB \DB \DB \DB \DB \

D ENDS

S SEGMENT STACK DB 200 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 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];输入的月份低字节(个位数) 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 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 \D2 DB 4, ?,3 DUP(?) ;准备接收键盘输入,只输入2个字符,为什么必须设定最大输入字符数为3,算回车符吗? D3 DB \

MONTH1 DB 01H

DB \MONTH2 DB 02H

DB \MONTH3 DB 03H

DB \MONTH4 DB 04H

DB \MONTH5 DB 05H

DB \MONTH6 DB 06H

DB \MONTH7 DB 07H

DB \MONTH8 DB 08H

DB \MONTH9 DB 09H

DB \MONTH10 DB 0AH

DB \MONTH11 DB 0BH

DB \MONTH12 DB 0CH

DB \

D ENDS

S SEGMENT STACK DB 200 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 CALL DISPLAY ;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];输入的月份低字节(个位数)

XOR AX,3030H ;将ASCII码变成BCD码,高位是1或0 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

本文来源:https://www.bwwdw.com/article/l9lv.html

Top