汇编语言程序设计 程学先 汇编第2、3,4章作业参考答案 下载本文

2.16编写程序段,使(AH)与( AL)中的内容互换。 解1

MOV BL,AL MOV AL,AH. MOV AH,BL 解2

XCHG AH,AL

2.17编写程序段,使 (BL) 中高 4 位与低 4 位内容互换。 解1 MOV CL,4 MOV BH,0 SHL BX,CL ADD BL,BH 解2

MOV CL,4 ROL BL,CL

2.18编写程序段,实现当(DL)是奇数时使(AL)=31H,否则使(AL)=30H。 SHR DL,1 MOV AL,0 RCL AL,1

ADD AL,30H

2.20设寄存器AX中存放 1234H,BX寄存器中存放 1 ,执行 DIV BL 指令后,会发生什么现象?为什么?

溢出,商超过8位,在AL中存放不下商。

2.21设 DX 寄存器中存放值为 0 ,AX中存放 1234H,BX中存放 1 ,执行 DIV BX 后,是否会出现与 2.20 相同现象?为什么? 不会,因为是16位除法,商未超过16位

2.22一字数据压栈时堆栈指针如何改变?弹出一字数据时堆栈指针如何改变? 压栈时堆栈指针减2;弹出一字数据时堆栈指针加2 2.23 已知(SP)=2088H,(AX)=1A89H,(BX)=90CDH。依次执行以下三条指令后,画图说明堆栈中数据情况,及SP、AX、BX中数据。 PUSH AX

PUSH BX POP AX (SP)=2086H,(AX)=90CDH,(BX)=90CDH。 *2.25编写程序段求8!(8的阶乘)。

MOV AX,8

MOV BX,7 NEXT:DX,0 MUL BX DEC BX

JNZ NEXT

2.27假设(AX)=07EH,变量BUFFER中存放的内容为B5H,求下列各条指令单独执行后的结果。

(1) AND AX,BUFFER 34H (2) XOR AX,BUFFER CBH (3) OR AX,BUFFER 0FFH (4) AND AX,0 0 (5) XOR AX,OFFH 81H

(6) TEST AX,8000H 相与结果为0时。AX为正,值不变

*2.28编写程序段,判断(AL)中的有符号数是正数还是负数,正数在CL中写0,否则写1。

CMP AL,0 MOV CL,0

JGE NEXT MOV CL,1 NEXT:??

2.29编写程序段,对存放在(DX)、(AX)中的双字数据求补。 MOV BX,0 SUB BX,AX MOV AX,BX MOV BX,0 SBB BX,DX

MOV DX,BX

2.31假设(DX)=78D5H,(CL)=5,CF=0,确定下列各条指令单独执行后(DX)中的值。 (1)SHL DH,1 (DX)=F0D5H (2)SAL DX, CL (DX)=1AA0H (3)SHR DX,CL (DX)=03C6H (4)SAR DL,1 (DX)=78EAH (5)ROL DX,CL (DX)=1AAFH (6)RCR DL,1 (DX)=786AH (7)RCL DH,CL (DX)=0FD5H 2.32按下列要求编写指令序列。

(1)清除DH中最低3位而不改变其他位,结果存入BH。 AND DH,0F8H

(2)将DI中最高3位置1而不改变其他位。 OR DI,0E000H

(3)将AX中0~3位置1、7~9位取反、其他位清0。 OR AX,0FH XOR AX,380H

AND AX,38FH

(4)检查BX中第2、5、9位是否至少有1位是1。 TEST AX,224H 如果结果非0

(5)检查CX中第1、6、11位是否同时为1。

NOT CX

TEST CX,842H 如果结果为0

(6)检查BX中第0、2、9、13位是否至少有1位是0。 NOT BX

TEST BX,2205H 如果结果非0

(7)检查DX中第1、4、11、14位是否同时是0。 TEST DX,4812H 如果结果为0 2.33编写指令序列分别实现下述功能。 (1)右移DI3位,并将0移入最高位。 MOV CL,3

SHR DI,CL

(2)将AL左移一位,将0移入最低位。 SHL AL,1

(3)DX右移6位且保持正负特性不变。

MOV CL,6 SAR DX,CL

(4)将AL中压缩BCD码变成AX中的非压缩BCD码。 MOV AH,0 MOV CL,4 SHL AL,CL

MOV CL,4 SHR AL,CL

2.34分析下面的程序段完成什么功能?

MOV CL,4 SHR AX,CL MOV BL,DL SHR DX,CL SHL BL,CL OR AH,BL

将双字(DX,AX)逻辑右移4位

*2.35设数据段偏移地址1000H处开始存放有10个字节数据,将其求和,结果存放在AX中。

MOV CX,10 MOV SI,1000H MOV AX,0 CLC

LOOP1:ADC AX,[SI] INC SI

LOOP LOOP1

2.37 从键盘输入0到9之间某数字字符,利用列表法将该数字的平方值放到AL中。 SUB DB 0,1,4,9,16,25,36,49,64,81

MOV AH,1 INT 21H SUB AL,30H MOV BL,AL MOV BH,0

MOV AL,SUB[BX]

2.38 已知X、Y、Z、P、K均为16位带符号数,求计算 (1000+X*Y-Z)/P的程序段。注明结果的商与余数所存放的位置。

MOV AX, X

IMUL Y ; x*y MOV CX, AX MOV BX, DX

MOV AX, Z

CWD ;符号扩展,AX中符号扩展到DX中 SUB CX, AX

SBB BX, DX MOV AX, 1000 MOV DX,0 SUB AX, CX

SBB DX, BX MOV BX, P

IDIV BX

x*y-z ;(1000+X*Y-Z)/P ; 4.1编制程序计算Y=5X+7,设X值在DAX字节单元,结果存入RLT字节单元。X为带符号整数。 DATA SEGMENT DAX DB 15H RLT DB 0 DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX MOV AL,DAX

MOV BL,5 ;X*5

IMUL BL ;有符号数乘法 ADD AL,7 MOV RLT,AL MOV AH,4CH INT 21H CODE ENDS

END START

;DAX绝对值不能超过18H (0-18H或0FFH-0E9H)。 ;否则,RLT得为字类型,ADD AL,7改为ADD AX,7 ;因为7已知为正,无需符号扩展。

4.3 编制程序计算X-Y。设X、Y分别在DAX、DAY单元,结果存入RESULT单元。 (1)X、Y为字节数据 (2)X、Y为字数据 (3)X、Y为双字节数据 要求:存取数据时至少使用三种不同的寻址方式。 1、用直接寻址 DATA SEGMENT DAX DB 18H DAY DB 65H RESULT DB 0 DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS

CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE START:MOV AX,DATA

MOV DS,AX

MOV AL,DAX ; 源操作数为直接寻址 SUB AL,DAY MOV RESULT,AL

MOV AH,4CH INT 21H CODE ENDS

END START 2、换间接寻址与相对寻址 DATA SEGMENT DAX DW 18H DAY DW 65H RESULT DW 0 DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE START:MOV AX,DATA

MOV DS,AX MOV SI,DAX MOV DI,RESULT

MOV AX,[SI] ;源操作数为间接寻址 SUB AX,[SI+2] ; 源操作数为相对寻址

MOV [DI],AX MOV AH,4CH INT 21H CODE ENDS

END START

3、X、Y为双字节数据,必须分高16位与低16位分别运算 方法1

DATA SEGMENT

DAX DD 2A341928H DAY DD 6873BC25H RESULT DD 0 DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX

MOV AX,WORD PTR DAX ;减低16位 SUB AX,WORD PTR DAY MOV WORD PTR RESULT,AX

MOV AX,WORD PTR DAX+2 ;减高16位

SUB AX,WORD PTR DAY+2 MOV WORD PTR RESULT+2,AX MOV AH,4CH INT 21H CODE ENDS

END START ;特别注意加“WORD PTR”

;注意低16位与高16位各是如何表示的。

;还要注意,本题要求出现三种以上寻址方式。目前解中用到了寄存器寻址、直接寻址、间接寻址与相对寻址4种方式。 方法2:

LEA SI,DAX LEA DI,DAY

LEA BX, RESULT

MOV AX,[SI]

SUB AX, [DI] ;减低16位 MOV [BX],AX MOV AX,[SI+2]

SBB AX, [DI+2] ;减高16位 MOV [BX+2],AX

4.4设内存OPCD单元存放一个16位代码,编制程序将其中15~13,12~8,7~3,2~0位的代码分别存入WCD开始的单元。每段代码的最低位与单元的第0位对齐。 解法1:

DATA SEGMENT OPCD DW 2A5CH WCD DW ?,?,?,? DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX MOV AX,OPCD

MOV CL,13 ;逻辑右移13位 SHR AX,CL MOV WCD,AX

MOV AX,OPCD

AND AX,1FFFH ;屏蔽高3位 MOV CL,8 ;逻辑右移13位 SHR AX,CL

MOV WCD+2,AX

MOV AX,OPCD AND AX,0FFH MOV CL,3 SHR AX,CL MOV WCD+4,AX

MOV AX,OPCD AND AX,7 MOV WCD+6,AX

MOV AH,4CH INT 21H

CODE ENDS

END START

解法2:下面一种方法是4个字生成的程序段全一样,可以类似于逻辑尺建立一个数据表,变成循环来做。 MOV AX,OPCD

MOV CL,3

ROR AX ;循环右移3位 MOV BX,AX ;暂存AX AND AX,07H ;保留低3位 MOV WCD,AX

MOV AX,BX ;恢复AX MOV CL,5

ROR AX ;循环右移5位 MOV BX,AX ;暂存AX AND AX,1F

MOV WCD+2,AX ;保留低5位

MOV AX,BX MOV CL,5 ROR AX MOV BX,AX AND AX,1F MOV WCD+4,AX

MOV AX,BX MOV CL,3 ROR AX MOV BX,AX AND AX,07H

MOV WCD+6,AX

4.5利用查表的方法计算S=X2+Y2,设0≤X≤15,0≤Y≤15,且分别在DAX、DAY字节单元存放,结果存入RLT单元。

DATA SEGMENT

TAB DB 0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225 ;建立平方值表 DAX DB 11 ;假设X的值 DAY DB 13 ;假设Y的值 RLT DW ? DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX MOV AL,DAX

LEA BX,TAB ;指向平方值表 XLAT ;根据X的值查表 MOV AH,0

MOV RLT,AX

MOV AL,DAY ;根据Y的值查表 XLAT

MOV AH,0

ADD RLT,AX ;求S=X2+Y2 MOV AH,4CH INT 21H CODE ENDS

END START

4.6编程实现把键入的一个字符,用二进制形式(0/1)显示出它的ASCII代码值。 MOV AH,1 ; 键入一个字符 INT 21H MOV CX,8

NEXT: ROL AL,1 ;循环左移一位 MOV DL,AL

AND DL,1 ;保留最低1位 ADD DL,30H ;显示一位 MOV AH,2

INT 21H LOOP NEXT

4.7编写一个程序,把从键盘输入的一个小写字母用大写字母显示出来。

MOV AH,1 ; 键入一个字符 INT 21H

CMP AL,’a’ ;小于a(小A)退出 JB EXIT CMP AL,’z’

JA EXIT ;大于 z(小z)退出 SUB AL,20H ;小写变大写 MOV DL,AL ;显示

MOV AH,2 INT 21H EXIT: MOV AH,4CH INT 21H

4.9设有如下程序段: LLL :?

?

JC LLL

若 JC LLL 指令与 LLL :处指令间相隔 1000H个存储单元,这个程序段将出现何种异常现象?如何改造这个程序段?

转移超出范围,编译失败。可以给JC之后的语句加标号:NEXT,如下所示

JC LLL NEXT:?? 则程序改为:

JNC NEXT JMP LLL NEXT:??

4.13编写程序,当DL是奇数时使AL=30H,否则使AL=31H。

分析,如果DL是奇数,最低位应为1,将DL右移1位到CF中,CF将为1。 NOT DL ;将DL最低位1变0,0变1 SHR DL,1 ; 将DL最低位移到CF中 MOV AL,0 ; AL予清0

RCL AL,1 ; 将CF移到AL最低位中

ADD AL,30H

说明,本解巧妙地不使用条件语句达到题目要求。

4.16编写一个程序,把变量BUFX和BUFY中较大者存入BUFZ;若两者相等,则把其中之一存入BUFZ中。假设变量存放的是8位无符号数。 MOV AL, BUFX

MOV BUFZ, AL ;予将BUFX放到BUFZ中

CMP AL, BUFY JAE EXIT

MOV AL, BUFY ;如果BUFX小

XCHG AL, BUFZ ;将BUFY换到BUFZ中 EXIT: MOV AH, 4CH

4.17 BUFX、BUFY和BUFZ是3个有符号16进制数,编写程序实现 (1)如果这3个数都不相等,则显示0;

(2)如果这3个数中有两个数相等,则显示1; (3)如果这3个数都相等,则显示2。 MOV CL, 0 ;计数 MOV AX, BUFX

CMP AX, BUFY

JNE NEXT1

INC CL ;如果 BUFX和BUFY相等,将CL加1

NEXT1:MOV AX, BUFY

CMP AX, BUFZ

JNE NEXT2

INC CL ;如果 BUFY和BUFZ相等,将CL加1

NEXT2:MOV AX, BUFX

CMP AX, BUFZ JNE NEXT3

INC CL ;如果 BUFX和BUFZ相等,将CL加1

NEXT3: CMP CL, 3

JNE NEXT4

DEC CL ;如果CL为3,减为2

NEXT4: ;

4.18已知三个无符号数A、B、C,存放在ADR开始的连续单元,编写程序完成下述功能,若A、B、C同时为偶数,将FLAG单元置1;若同时为奇数,将FLAG单元置0;否则FLAG单元置全1。

解法1:如果ABC为字节类型:

MOV CL, 0 ;计数

MOV AL, ADR

SHR AL, 1 ;右移A,如果A为偶,CF将为0,否则为1

JC NEXT1

INC CL ;A为偶,将CL加1

NEXT1: MOV AL, ADR+1 ;字节类型加1

SHR AL, 1

JC NEXT 2

INC CL ;B为偶,将CL加1

NEXT2: MOV AL, ADR+2

SHR AL, 1 JC NEXT 3

INC CL ;C为偶,将CL加1

NEXT3: CMP CL, 3 ;以下判断CF,为3,则将FLAG单元置1 JNE NEXT4 MOV FLAG,1 JMP EXIT

NEXT4: CMP CL,0 ;以下判断CF,为0,则将FLAG单元置0 JNE NEXT5 MOV FLAG,0 JMP EXIT NEXT5: MOV FLAG,-1 EXIT:

解法2,如果ADR为字类型

MOV CL,0 MOV AX,ADR

TEST AX,0001H ;与上一方法不同点,改为测试第0位 JNZ NEXT1

INC CL

NEXT1: MOV AX,ADR+2 ;字类型加2 TEST AX,0001H JNZ NEXT2 INC CL

NEXT2:MOV AX,ADR+4 TEST AX,0001H JNZ NEXT3 INC CL

NEXT3: CMP CX,0 JZ NEXT5 CMP CL,3 JZ NEXT4

MOV CL,0FFH JMP NEXT5 NEXT4:MOV CL,1

NEXT5:MOV FLAG,CL

4.20要求A、B、C三数的中间数(中间数即该数小于一数而大于另一数),其中A、B、C及中间数的存储单元自行定义。假设A、B和C为无符号数,编写相关程序。若A、B和C为有符号数,则应如何修改程序。

A DB 39H B DB 54H C DB 6AH

D DB ? ??

;只要将A、B、C从小到大排序,中间位置的就是中间数 MOV AL, A

CMP AL, B

JBE NEXT1

XCHG AL,B ;A>B.交换AB的位置 MOV A,AL NEXT1: MOV AL, B CMP AL, C

JBE NEXT2

XCHG AL,C ;B>C.交换BC的位置 MOV B,AL

NEXT2: MOV AL, A ;再比较AB

CMP AL, B JBE NEXT3

XCHG AL,B ;A>B.交换AB的位置 MOV A,AL

NEXT3: MOV AL, B MOV D, AL

; 有符号数题解见下题解,只将JBE换为JLE就可以了。

4.21已知A、B和C存放在ADR开始单元,编制程序使之按递增顺序存放在NEW开始的单元。设A、B和C为带符号数。 MOV AL, A

CMP AL, B

JLE NEXT1

XCHG AL,B ;A>B.交换AB的位置 MOV A,AL NEXT1: MOV AL, B

CMP AL, C JLE NEXT2

XCHG AL,C ;B>C.交换BC的位置 MOV B,AL

NEXT2: MOV AL, A ;再比较AB

CMP AL, B JLE NEXT3

XCHG AL,B ;A>B.交换AB的位置 MOV A,AL

4.23 编制程序计算:

X*Y (Y>=0,X>=0) S= X/Y (X<0,Y<0 ∣X+Y∣ (其它)

设X,Y为双字节带符号数据,分别存放在DAX,DAY单元,计算结果存入RLT单元。 RLT DW ? DAX DW ? DAY DW ?

MOV CX,0

MOV AX, DAX CMP AX,0 JL NEXT1 INC CX ;X>=0 NEXT1:MOV BX, DAY CMP BX,0 JL NEXT2 INC CX ;Y>=0 NEXT2:CMP CX,2

JZ NEXT3 ; X*Y CMP CX,0

JZ NEXT4 ; X/Y ADD AX,BX JO NEXT5 CMP AX,8000H JL NEXT5 NEG AX NEXT5:MOV DAX,AX JMP EXIT1 NEXT4:MOV DX,0 IDIV BX

MOV DAX,AX JMP EXIT1 NEXT3:IMULBX

MOV DAX,AX

MOV DAY,DX EXIT1:

4.24编写程序,将一个包含有20个有符号数据的数组ARRAYM分成两个数组,正数数组ARRAYP和负数数组ARRAYN,并分别把这两个数组中的数据个数显示出来。 ARRAYM DB 20,48,149,212,33,200,198,23,25,53,199,214,225,245,123,1,12,43,54,165 COUNT EQU $-ARRAYM ARRAYP DB COUNT DUP(0) ARRAYN DB COUNT DUP(0) ??

MOV BX,OFFSET ARRAYM ;源数据 MOV SI,OFFSET ARRAYP ;存正数 MOV DI,OFFSET ARRAYN ;存负数 MOV DH,0 ; 正数个数 MOV DL,0 ; 负数个数 MOV CX, COUNT

LOOP1:MOV AL,[BX] ; 源数据中取1个数

SHL AL,1 ; 看最高位

JC NEXT1 ; 最高位为1则CF为1,有进位是负数 MOV [SI],AL ;存正数

INC SI ; 正数指针加1 INC DH ; 正数个数加1 JMP NEXT2

NEXT1: MOV [DI],AL ;存负数

INC DI

INC DL NEXT2:INC BX LOOP LOOP1

4.25 已知内存DATA开始的存储区存放若干个字节数据,数据个数在COUNT单元中存放。编制程序求其中正数平均值及负数平均值,并分别存入MEANP和MEANM单元。 BUF DB 27H,59H,0B3H,32H,8AH COUNT EQU $-BUF

MEANP DB ? ;存正数平均值 MEANM DB ? ;存负数平均值

LEA SI,BUF ;指向BUF MOV CX,COUNT MOV DI,0 MOV BP,0 MOV DX,0 MOV BX,0

MOV AH,0

CLC ;清进位位 L1:MOV AL,[SI]

CMP AL,0

JL NEXT1 ;负数在NEXT1处理 ADC DL,AL

ADC DH ;正数加到DX中 INC DI ;正数个数加1 JMP NEXT2

NEXT1: NEG AL ;负数求其绝对值 ADC BL,AL ;加到BX中 ADC BH

INC BP ;负数个数加1

NEXT2: INC SI ;准备取下一个数 LOOP L1

NEG BX ;负数之和

MOV CX,DI ;正数个数

MOV AX,DX ;正数总和 IDIV CL ;正数平均值 MOV MEANP,AL

MOV AX,BX ;负数之和 MOV CX,BP ;负数个数 IDIV CL ;负数平均值

MOV MEANM,AL

4.26 已知内存DATA单元开始连续存放若干个字符,编制程序求这些字符中出现次数最多的字符,将其出现次数及ASCII码分别存入NUMB和DATAM单元。

分析:如果每出现一个字符,就设置一个变量存放其出现次数,最后再找出现最多的字符,在循环过程中要不停地设置新变量,这样的程序不好设计。本解建立一个长度和ASCII码表相等(127)的数组,每一元素的地址就对应一个ASCII码值,每一元素存放该元素地址对应的ASCII码代表的字符出现次数。找到一个字符,就以其ASCII码值为地址,将该地址对应的存储单元中的数据加1.这样只对原串从始到终扫描一次,就能完成统计,再求最大值就容易了。这个方法我们称之为对号入座法。 DATA SEGMENT

A DB \ COUNT EQU $-A

B DB 127 DUP(0) ;对应某字符的ASCII码的地址中存放该字符出现次数 NUMB DB 0 DATAM DB 0 DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS

CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX

LEA SI,A ;指向字符串的指针 LEA DI,B ;存放相应字符出现次数

MOV CX,COUNT

NEXT: MOV BL,[SI] ;取一个字符的ASCII码到BX中 MOV BH,0

INC B[BX] ;对应某字符的ASCII码的地址中存放该字符出现次数加1 INC SI

LOOP NEXT ;完成对所有字符的统计,以下求出现次数最多的 MOV SI,0 MOV CX,127

MOV DL,0

NEXT1:CMP DL,B[SI] ;求B区中最大的数 JAE NEXT2 MOV DL,B[SI] MOV DI,SI

NEXT2:INC SI

LOOP NEXT1 MOV NUMB,DL MOV AX,DI MOV DATAM,AL DATAM ADD DL,30H ;显示B区中最大的数 MOV AH,2

INT 21H

MOV DX,DI ;相应地址数送DL准备显示出现最多的那个字符 MOV AH,2 INT 21H

MOV AH,4CH INT 21H CODE ENDS

END START

4.27已知内存WORD单元开始存放两个字母个数相同的英文单词,词间用逗号分隔,编制程序将两个单词按字典顺序存放在DICT开始的存储区。

分析:比较二个串的大小应当从第一个字符开始比较,直到找到一个不相同的字符为止,此时那个串的该字符大,该串就大,要排在后面。本程序先找大串,找到后将小串传DICT,再将大串接传DICT,最后显示DICT串。如果二串到最后一个字符还是一样大,表示二串一样大,则不移动原串,直接显示ORD1串。

方法1,用传送指令完成

DATA SEGMENT

WORD1 DB \ COUNT EQU ($-WORD1)/2 DICT DB COUNT*2 DUP(0) DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX

LEA SI,WORD1 ;指向第一个字符串的指针

LEA DI,WORD1+COUNT ;存放相应字符出现次数 MOV CX,COUNT

NEXT1: MOV BL,[SI] ;取一个字符的ASCII码到BX中

CMP BL,[DI]

JA NEXT2 ;如果找到第一个不相同的字符前串大转next1 JB NEXT5 ;如果找到第一个不相同的字符前串小转next2 INC SI INC DI

LOOP NEXT1 ;如果字符相同继续向下找不同字符,完成对所有字符的统计 LEA DI,WORD1 ;以下显示原WORD1串

MOV CX,COUNT*2

JMP NEXT8 ;如果二串相同,转退出程序显示原WORD1串

NEXT2:LEA SI,WORD1+COUNT ;先将较小的后串转存DICT,再将较大的前串转存DICT

MOV CX,COUNT LEA DI,DICT NEXT3:MOV BL,[SI] MOV [DI],BL INC SI INC DI LOOP NEXT3 LEA SI,WORD1 MOV CX,COUNT NEXT4:MOV BL,[SI] MOV [DI],BL INC SI INC DI

LOOP NEXT4

JMP NEXT7 ;排完序后转显示

NEXT5:LEA SI,WORD1 ;原串顺序已经符合字典顺序,直接全部转存DICT MOV CX,COUNT*2 LEA DI,DICT NEXT6:MOV BL,[SI] MOV [DI],BL INC SI

INC DI

LOOP NEXT6

NEXT7: LEA DI,DICT ;以下显示排好序的DICT串 MOV CX,COUNT*2 NEXT8: MOV DL,[DI] MOV AH,2 INT 21H INC DI

LOOP NEXT8 MOV AH,4CH INT 21H CODE ENDS

END START 方法2,用串操作指令完成

DATA SEGMENT

WORD1 DB \ COUNT EQU ($-WORD1)/2

DICT DB COUNT*2 DUP(0) DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT

ASSUME DS:DATA,ES:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX

NEXT2: NEXT5: MOV ES,AX

LEA SI,WORD1 ;指向第一个字符串的指针

LEA DI,WORD1+COUNT ;存放相应字符出现次数 MOV CX,COUNT

CLD ;清DF

REPZ CMPSB

;NEXT1: MOV BL,[SI] ;取一个字符的ASCII码到BX中 ;CMP BL,[DI]

JA NEXT2 ;如果找到第一个不相同的字符前串大转next1 JB NEXT5 ;如果找到第一个不相同的字符前串小转next2 ;INC SI ;INC DI

;LOOP NEXT1

LEA SI,WORD1 ;以下显示原WORD1串

MOV CX,COUNT*2

JMP NEXT8 ;如果二串相同,转退出程序显示原WORD1串 LEA SI,WORD1+COUNT ;将后串转存DICT,再将前串转存DICT

MOV CX,COUNT LEA DI,DICT

;NEXT3:MOV BL,[SI]

;MOV [DI],BL ;INC SI ;INC DI ;LOOP NEXT3 REP MOVSB

LEA SI,WORD1

MOV CX,COUNT

;NEXT4:MOV BL,[SI]

;MOV [DI],BL ;INC SI ;INC DI ;LOOP NEXT4

REP MOVSB

JMP NEXT7 ;排完序后转显示

LEA SI,WORD1 ;原串顺序已经符合字典顺序,直接全部转存DICT

MOV CX,COUNT*2 LEA DI,DICT

;NEXT6:MOV BL,[SI]

;MOV [DI],BL ;INC SI ;INC DI ;LOOP NEXT6

REP MOVSB

NEXT7: LEA SI,DICT ;以下显示排好序的DICT串,欲使用LODSB,要用SI指针

MOV CX,COUNT*2

NEXT8: LODSB ;MOV DL,[DI]

MOV DL,AL

MOV AH,2 INT 21H

;INC DI LOOP NEXT8 MOV AH,4CH INT 21H CODE ENDS

END START

4.28 编制程序求X、Y的最小公倍数并存入CMTM单元,已知X、Y为字节类型正整数且分别存放在ADRX和ADRY单元。

分析:求最小公倍数的数学方法是找出X和Y的所有因子,再将所有相同的因子取其一个,连同所有不同的因子乘起来,乘积就是。另外一种方法是数值之积除以最大公约数,这时要求先求最大公约数,方法是辗转相除法:始终用较大数除以较小数,然后用余数代替较大数,整除时的除数就是最大公约数。方法3:用大数翻倍法,将较大数依次乘2、3、4??,到某个积能整除较小数时该积就是最小公倍数。以下分别用2、3二种方法来解。

数值之积除以最大公约数方法:(要求最小公倍数之大小不超过1个字大小) 假定X>Y,如果X

CODE SEGMENT

ASSUME DS:DATA,ES:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX

MOV AX,X MOV DX,0

MOV BX,Y

LOOP1:DIV BX CMP DX,0

JZ NEXT2 ;如果除尽,表示找到最大公约数(等于BX中数)

NEXT1:MOV AX,DX ;AX大于BX,用DX换AX

MOV DX,0

CMP AX,BX ;找AX与BX中较大的数为下一次的被除数 JA LOOP1 ;AX大为被除数,转回做下一次除法 XCHG AX,BX JMP LOOP1

NEXT2:MOV AX,X MUL Y

DIV BX

; MOV SI,AX ;调16进制显示程序 ; CALL DISPLAY16

LEA SI,BUF+5 ; 调10进制显示程序 CALL TRANSFORM

MOV AH,4CH INT 21H

;子程序名:DISPLAY16

;功能:以移位方式显示16进制数

;占用寄存器:BX,CL,AX,DX(均已保护) ;输入参数:要显示数据在SI中 ;输出参数:无

DISPLAY16 PROC PUSH AX PUSH BX

PUSH CX PUSH DX

MOV BX,4 ;每个字显示4个16进制字符 CHANGE10:MOV CL,4 ;准备左移4位(除以16) ROL SI,CL ;SI循环移4位 MOV DX,SI ;转存到DX AND DX,0FH ;清高12位

ADD DL,30H ;一个16进制数变为ASCII码值 CMP DL,3AH ;是否小于10?

JB CHANGE12 ;如果小于10转显示

ADD DL,7 ;否则为A到F之间数,加7 CHANGE12:MOV AH,2 ;显示1个字符 INT 21H

DEC BX ;处理下一个字符 CMP BX,0 ;是否为0?

JNZ CHANGE10 ;不为0转CHANGE10 POP DX POP CX POP BX POP AX RET DISPLAY16 ENDP

;* * * * * * * ;子程序名:TRANSFORM

;功能:将16位无符号二进制数转换为十进制数ASCII码显示 ;入口参数:16位二进制数=>AX

; 存放ASCII码值末地址=>SI ;出口参数:在ASC开始的存贮单元中 ;* * * * * * * TRANSFORM PROC NEAR

PUSH CX PUSH DX PUSH BX

MOV CX,5 ;最多5位数

MOV BX,10 ;除数为10 MOV DX,0

AGAIN:DIV BX MOV [SI],DL

ADD [SI],BYTE PTR 30H ;余数变ASCII码放SI所指位置 DEC SI

MOV DX,0

LOOP AGAIN

MOV CX,5 ;最多5位数 NEXT:INC SI MOV DL,[SI] MOV AH,2 INT 21H LOOP NEXT

POP BX POP DX POP CX

RET

TRANSFORM ENDP

CODE ENDS

END START

大数翻倍法: DATA SEGMENT X DW 200 Y DW 44 BUF DB 6 DUP(0) DATA ENDS STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT

ASSUME DS:DATA,ES:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX

MOV CX,Y ;最小公倍数最大为X与Y的乘积,因此试到乘数为Y为止

MOV BX,2 ;乘数从2开始试

LOOP1:MOV AX,X

MUL BX ;求X与BX的乘积,看该乘积能否被Y除尽 PUSH AX ;保存该乘积,如果是最小公倍数就送显示 DIV Y ;看X与BX的乘积能否被Y除尽 CMP DX,0

POP AX

JZ NEXT2 ;如果除尽,表示找到最大公约数(等于AX中数)

INC BX ;未找到最大公约数将BX中数加1后继续 LOOP LOOP1

NEXT2:LEA SI,BUF+5 ; 调10进制显示程序 CALL TRANSFORM

MOV AH,4CH INT 21H

;* * * * * * * ;子程序名:TRANSFORM

;功能:将16位无符号二进制数转换为十进制数ASCII码显示 ;入口参数:16位二进制数=>AX

; 存放ASCII码值末地址=>SI

;出口参数:在ASC开始的存贮单元中 ;* * * * * * *

TRANSFORM PROC NEAR PUSH CX PUSH DX

PUSH BX

MOV CX,5 ;最多5位数 MOV BX,10 ;除数为10 MOV DX,0 AGAIN:DIV BX

MOV [SI],DL

ADD [SI],BYTE PTR 30H ;余数变ASCII码放SI所指位置 DEC SI

MOV DX,0

LOOP AGAIN

MOV CX,5 ;最多5位数 NEXT:INC SI MOV DL,[SI] MOV AH,2 INT 21H LOOP NEXT

POP BX POP DX POP CX RET

TRANSFORM ENDP

CODE ENDS

END START

分析:第二个程序比较短小、简单,容易设计,但可能会比较慢。

4.29采用查表法,将0到15中某数变为十六进制数字的ASCII码,并将结果用16进制形式显示出来。

DATA SEGMENT X DB 13 TABEL

DB

30H,31H,32H,33H,34H,35H,36H,37H,38H,39H,41H,42H,43H,44H,45H,46H

DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0)

STACK ENDS CODE SEGMENT

ASSUME DS:DATA,ES:DATA,SS:STACK,CS:CODE

START:MOV AX,DATA

MOV MOV MOV MOV

DS,AX

BL,X ;取数,8位2进制数放BL中 BH,0 ;准备用BX间址,因而将BH清0 DL,TABEL[BX] ;查表

MOV DH,0

MOV SI,DX ;所用子程序显示一个字,如果只显示8位,需另设计子程序 CALL DISPLAY16 MOV DL,'H' MOV AH,2 INT 21H

MOV AH,4CH INT 21H

;子程序名:DISPLAY16

;功能:以移位方式显示16进制数

;占用寄存器:BX,CL,AX,DX(均已保护) ;输入参数:要显示数据在SI中 ;输出参数:无

DISPLAY16 PROC PUSH AX PUSH BX PUSH CX

PUSH DX

MOV BX,4 ;每个字显示4个16进制字符 CHANGE10:MOV CL,4 ;准备左移4位(除以16) ROL SI,CL ;SI循环移4位 MOV DX,SI ;转存到DX

AND DX,0FH ;清高12位

ADD DL,30H ;一个16进制数变为ASCII码值 CMP DL,3AH ;是否小于10?

JB CHANGE12 ;如果小于10转显示 ADD DL,7 ;否则为A到F之间数,加7 CHANGE12:MOV AH,2 ;显示1个字符 INT 21H

DEC BX ;处理下一个字符 CMP BX,0 ;是否为0?

JNZ CHANGE10 ;不为0转CHANGE10 POP DX POP CX POP BX POP AX

RET

DISPLAY16 ENDP

CODE ENDS

END START

4. 30编制程序求一组数据中的最大值与最小值及其存放地址。

分析:假定数据均为无符号数。在数据区准备4个变量分别存放最大值、最小值、最大值存放地址与最小值存放地址,初始值为0、OFFFFH、0、0。从第一个数开始将数据放到AX中,分别与最大值、最小值比较,如果出现新的最大值、最小值,就代换有关变量的值。

DATA SEGMENT

X DW 2314H,122AH,3A5BH,33EDH,0A344H,4453H,3EDAH,6ADEH COUNT EQU ($-X)/2 ;X中字的个数 MAX DW 0 MIN DW 0FFFFH MAXADDI DW 0 MINADDI DW 0 DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS

CODE SEGMENT

ASSUME DS:DATA,ES:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX MOV SI,OFFSET X MOV CX,COUNT NEXT: MOV AX,[SI] CMP AX,MAX JNA NEXT1 MOV MAX,AX MOV MAXADDI,SI NEXT1:CMP AX,MIN JNB NEXT2 MOV MIN,AX

MOV MINADDI,SI NEXT2:ADD SI,2 LOOP NEXT MOV SI,MAX CALL DISPLAY16 MOV SI,MIN CALL DISPLAY16

MOV AH,4CH

INT 21H

;子程序名:DISPLAY16

;功能:以移位方式显示16进制数

;占用寄存器:BX,CL,AX,DX(均已保护) ;输入参数:要显示数据在SI中 ;输出参数:无

DISPLAY16 PROC PUSH AX PUSH BX PUSH CX

PUSH DX

MOV BX,4 ;每个字显示4个16进制字符 CHANGE10:MOV CL,4 ;准备左移4位(除以16) ROL SI,CL ;SI循环移4位

MOV DX,SI ;转存到DX AND DX,0FH ;清高12位

ADD DL,30H ;一个16进制数变为ASCII码值 CMP DL,3AH ;是否小于10?

JB CHANGE12 ;如果小于10转显示 ADD DL,7 ;否则为A到F之间数,加7 CHANGE12:MOV AH,2 ;显示1个字符 INT 21H

DEC BX ;处理下一个字符 CMP BX,0 ;是否为0?

JNZ CHANGE10 ;不为0转CHANGE10 POP DX POP CX POP BX POP AX RET DISPLAY16 ENDP

CODE ENDS

END START

4.31内存自BUFF单元开始的存储区连续存放100个学生的某科分数,编制循环程序统计100,90~99,80~89,70~79,60~69,50~59,40~49,30~39,20~29,10~19, 0~9等各分数段的学生人数,并把结果连续存放在RESULT开始的单元。

分析:如果对每一个数都判断属于那个段,再将相应的变量加1,程序太麻烦。可以类似于4.26题采用对号入座法。准备一个数组,长11,其中各元素分别对应某个分数段的人数。可以依次取分数,除以10,以商为数组中相对开始元素的偏移地址,将该地址中数加1,就可以完成统计。

DATA SEGMENT

X DB 64,87,98,56,34,100,99,36,68,76,78,66,0,0 COUNT EQU $-X ;X中分数的个数

TABEL DB 11 DUP(0) ;统计各个分数段人数 BUF DB 5 DUP(0) ;十进制显示程序用 DATA ENDS

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT

ASSUME DS:DATA,ES:DATA,SS:STACK,CS:CODE START:MOV AX,DATA MOV DS,AX

MOV SI,OFFSET X MOV CX,COUNT

MOV BL,10 ;除数,除以10 NEXT1: MOV AL,[SI] MOV AH,0 DIV BL MOV AH,0 MOV DI,AX INC TABEL[DI]

INC SI

LOOP NEXT1

MOV DI,OFFSET TABEL ;以下准备显示各分数段的人数情况 MOV CX,11 ;从0到100共分11个分数段

NEXT2:MOV AL,[DI]

MOV SI,OFFSET BUF CALL TRANSFORM1 MOV DL,',' MOV AH,2 INT 21H INC DI LOOP NEXT2

MOV AH,4CH INT 21H

;* * * * * * *

;子程序名:TRANSFORM1

;功能:将8位无符号二进制数转换为十进制数格式显示 ;入口参数:8位二进制数=>AL ; 存放ASCII码值末地址=>SI ;出口参数:

;* * * * * * *

TRANSFORM1 PROC NEAR

PUSH CX PUSH DX PUSH BX PUSH DI

MOV CX,3 ;最多3位数 MOV BX,10 ;除数为10

MOV DI,0 AGAIN:MOV AH,0

DIV BL

MOV [SI],AH ;余数存显示数据区

ADD [SI],BYTE PTR 30H ;余数变ASCII码放SI所指位置 INC DI ;余数个数计数,为显示准备 DEC SI

CMP AL,0 ;如果商已经为0,就不再求余了 JZ NEXT0

LOOP AGAIN ;完成求余数过程

NEXT0:MOV CX,DI NEXT:INC SI MOV DL,[SI] MOV AH,2 INT 21H LOOP NEXT POP DI POP BX POP DX POP CX RET

TRANSFORM1 ENDP

CODE ENDS

END START

4.32下列程序执行完后,物理地址单元01070H的内容是什么?

MOV AX,00E0H ;设置DS段地址为00E0H

MOV DS,AX

MOV BX,0200H ;BL从0开始 MOV CX,BX ;共计200H个单元

NEXT: MOV [BX],BL ;开始是0放到E0H:200H中

INC BL ;以后是1放到E0H:201H中

LOOP NEXT ;直到200H放到E0H:400H中 MOV AH,4CH INT 21H

从上面分析可见,从E00H+200H=01000H到E00H+400H=01200H中顺序放0到200H,因此推断,物理地址单元01070H的内容是70H。

4.33设 CX 寄存器中存放数据为 100H,SI寄存器中存放数据为 100H,DI寄存器中存放数据为 2000 H ,数据段中偏移地址 100 H 处开始存放有 100 H 个字节数据,附加段中偏移址 2000 H 处开始存放有另 100 H 个字节数据。这时执行 REPNZ CMPSB 指令,问:

( 1 )指令结束条件是什么?

结束条件是(CX)=0或(CX)<>0但ZF<>0,即出现了比较值为0(比较的二字符相同)的情况。得到结论是:

一种可能是CX为0,数据段中偏移地址 100 H 处开始的长度为 100 H 个字节的串和附加段中偏移址 2000 H 处起的同样长度的串对应字符全都不相同。另一种可能是CX不为0,那么在数据段中偏移地址 100 H 处开始的串从串尾倒数(CX)的字符和附加段中偏移址 2000 H 处起的对应位置的字符是相同的。

( 2 )指令执行前若 DF=0 ,指令结束后,上述三个寄存器内容有何关系? 如果(CX)=0,那么(SI)=200H,(DI)=2100H;如果(CX)<>0,那么,(SI)=200H-(CX),(DI)=2100H-(CX)。

4.34阅读下面的程序段,描述其完成的功能。 LEA BX,BUF MOV CX,N

MOV AX,0

LOPA:CMP BYTE PTR [BX],0 JGE NEXT INC AX NEXT:INC BX LOOP LOPA

本程序段分析BUF中N个字节数据,统计其中负数的个数放到AX中。

4.35如何使 DF 标志清零,这时会带来何种影响?如何使 DF 标志置 1 ,这时又会带来何种影响?

CLT使 DF 标志清零,在串操作中每一步操作之后使指针寄存器的值加1或加2。STD使 DF 标志置 1,在串操作中每一步操作之后使指针寄存器的值减1或减2。

4.36已知当前的DS和ES指向同一个段,且当前数据段从0000H到00FFH单元的内容分别为01,02,03,??,0FEH,0FFH,00H,问下列程序执行后,0000H~00FFH单元的内容有什么变化?

MOV DI,0001H

MOV SI,0000H MOV CX,0080H CLD

REP MOVSW

从0000到0082H中内容变为:01,01,02,02,04,04,06,06,08,08,?? 4.37设BEG为起始地址的存储区域中放有100个字节的数据,现将其首、尾颠倒过来重新排放这100个字节数据。

data segment

beg db 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20?? count equ ($-beg)/2 data ends code segment

assume cs:code,ds:data start: mov ax,data mov ds,ax mov es,ax lea si,beg

lea di,beg+ count*2-1 mov cx,count cld next: mov al,[di] xchg al,[si] mov [di],al inc si dec di loop next mov ah,4ch int 21h code ends

end start

4.40编写程序:由键盘输入一个字符串,统计其中‘MOV’出现的次数。 data segment a db 100 b db ?

c db 100 dup (0) m db 'mov' data ends code segment assume cs:code,ds:data start: mov ax,data mov ds,ax mov es,ax mov dx,offset a mov ah,10 int 21h mov bl,b mov bh,0 cld lea si,c lea di,m next1: push si mov cx,3

next2: repz cmpsb

jz next3 pop si inc si lea di,m

dec bl jnz next1 jmp exit next3: inc bh sub bl,3 jz exit lea di,m jmp next1 exit: mov dl,bh add dl,30h mov ah,2 int 21h mov ah,4ch int 21h code ends

end start

4.43编制计算S=X+Y+Z的程序。已知X、Y、Z为用DT伪指令定义的带符号十进制数。

提示:请注意DT伪指令定义的十进制数的存储格式。

data segment x dt -35876237 y dt 98976532 z dt 62143526 s dt 0 data ends

code segment

assume cs:code,ds:data start: mov ax,data mov ds,ax mov es,ax mov cx,10

mov si,0

cmp byte ptr x[si+9],80h ;判断是否为负 jnz next1

clc ;X为负的处理,清进位位 loop1: mov al,0 ;做减法求补码 sbb al,byte ptr x[si]

das ;压缩BCD码减法调整 mov byte ptr x[si],al

pushf ;保存标志寄存器 inc si popf

loop loop1

next1: mov cx,10

mov si,0

cmp byte ptr y[si+9],80h ;y为负的处理,判断是否为负 jnz next2

clc ;清进位位 loop2: mov al,0 ;做减法求补码 sbb al,byte ptr y[si]

das ;压缩BCD码减法调整 mov byte ptr y[si],al

pushf ;保存标志寄存器 inc si popf

loop loop2

next2: mov cx,10

mov si,0

cmp byte ptr z[si+9],80h ;z为负的处理,判断是否为负 jnz next3

clc ;清进位位 loop3: mov al,0 ;做减法求补码 sbb al,byte ptr z[si]

das ;压缩BCD码减法调整 mov byte ptr z[si],al

pushf ;保存标志寄存器 inc si popf

loop loop3

next3: clc ;计算X加Y,存放S中 mov cx,9 ;加9位,符号位不再考虑 mov si,0

loop4: mov al,byte ptr x[si] adc al,byte ptr y[si] daa

mov byte ptr s[si],al pushf inc si popf

loop loop4

next4: mov cx,9 ;计算s加z,存放S中 mov si,0

loop5: mov al,byte ptr s[si] adc al,byte ptr z[si] daa

mov byte ptr s[si],al pushf inc si popf loop loop5

mov ah,4ch int 21h code ends end start