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

发布时间:2010-11-13 12:47:53

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中存放 1234HBX寄存器中存放 1 ,执行 DIV BL 指令后,会发生什么现象?为什么?

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

2.21 DX 寄存器中存放值为 0 AX中存放 1234HBX中存放 1 ,执行 DIV BX 后,是否会出现与 2.20 相同现象?为什么?

不会,因为是16位除法,商未超过16

2.22一字数据压栈时堆栈指针如何改变?弹出一字数据时堆栈指针如何改变?

压栈时堆栈指针减2;弹出一字数据时堆栈指针加2

2.23 已知(SP=2088H,(AX=1A89H,(BX=90CDH。依次执行以下三条指令后,画图说明堆栈中数据情况,及SPAXBX中数据。

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 AXBUFFER 34H

(2) XOR AXBUFFER CBH

(3) OR AXBUFFER 0FFH

(4) AND AX0 0

(5) XOR AXOFFH 81H

(6) TEST AX8000H 相与结果为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=5CF=0,确定下列各条指令单独执行后(DX)中的值。

1SHL DH1 DX=F0D5H

2SAL DX, CL DX=1AA0H

3SHR DXCL DX=03C6H

4SAR DL1 DX=78EAH

5ROL DXCL DX=1AAFH

6RCR DL1 DX=786AH

7RCL DHCL DX=0FD5H

2.32按下列要求编写指令序列。

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

AND DH,0F8H

2)将DI中最高3位置1而不改变其他位。

OR DI,0E000H

3)将AX0~3位置17~9位取反、其他位清0

OR AX,0FH

XOR AX,380H

AND AX,38FH

4)检查BX中第259位是否至少有1位是1

TEST AX,224H 如果结果非0

5)检查CX中第1611位是否同时为1

NOT CX

TEST CX,842H 如果结果为0

6)检查BX中第02913位是否至少有1位是0

NOT BX

TEST BX,2205H 如果结果非0

7)检查DX中第141114位是否同时是0

TEST DX,4812H 如果结果为0

2.33编写指令序列分别实现下述功能。

1)右移DI3位,并将0移入最高位。

MOV CL,3

SHR DI,CL

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

SHL AL,1

3DX右移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 CL4

SHR AXCL

MOV BLDL

SHR DXCL

SHL BLCL

OR AHBL

将双字(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 从键盘输入09之间某数字字符,利用列表法将该数字的平方值放到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 已知XYZPK均为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 x*y-z

MOV AX, 1000

MOV DX,0

SUB AX, CX

SBB DX, BX

MOV BX, P

IDIV BX (1000+X*Y-Z)/P

4.1编制程序计算Y5X7,设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-18H0FFH-0E9H)

;否则,RLT得为字类型,ADD AL,7改为ADD AX,7

;因为7已知为正,无需符号扩展。

4.3 编制程序计算XY。设XY分别在DAXDAY单元,结果存入RESULT单元。

1XY为字节数据 2XY为字数据 3XY为双字节数据

要求:存取数据时至少使用三种不同的寻址方式。

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

3XY为双字节数据,必须分高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位代码,编制程序将其中15131287320位的代码分别存入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利用查表的方法计算SX2Y2,设0X150Y15,且分别在DAXDAY字节单元存放,结果存入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 ;SX2Y2

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最低位1001

SHR DL,1 ; DL最低位移到CF

MOV AL,0 ; AL予清0

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

ADD AL,30H

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

4.16编写一个程序,把变量BUFXBUFY中较大者存入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 BUFXBUFYBUFZ3个有符号16进制数,编写程序实现

1)如果这3个数都不相等,则显示0

2)如果这3个数中有两个数相等,则显示1

3)如果这3个数都相等,则显示2

MOV CL, 0 ;计数

MOV AX, BUFX

CMP AX, BUFY

JNE NEXT1

INC CL ;如果 BUFXBUFY相等,将CL1

NEXT1:MOV AX, BUFY

CMP AX, BUFZ

JNE NEXT2

INC CL ;如果 BUFYBUFZ相等,将CL1

NEXT2:MOV AX, BUFX

CMP AX, BUFZ

JNE NEXT3

INC CL ;如果 BUFXBUFZ相等,将CL1

NEXT3: CMP CL, 3

JNE NEXT4

DEC CL ;如果CL3,减为2

NEXT4: ;

4.18已知三个无符号数ABC,存放在ADR开始的连续单元,编写程序完成下述功能,若ABC同时为偶数,将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为偶,将CL1

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

SHR AL, 1

JC NEXT 2

INC CL ;B为偶,将CL1

NEXT2: MOV AL, ADR+2

SHR AL, 1

JC NEXT 3

INC CL ;C为偶,将CL1

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要求ABC三数的中间数(中间数即该数小于一数而大于另一数),其中ABC及中间数的存储单元自行定义。假设ABC为无符号数,编写相关程序。若ABC为有符号数,则应如何修改程序。

A DB 39H

B DB 54H

C DB 6AH

D DB ?

……

;只要将ABC从小到大排序中间位置的就是中间数

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已知ABC存放在ADR开始单元,编制程序使之按递增顺序存放在NEW开始的单元。设ABC为带符号数。

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=0X=0

S XY X0Y0

XY (其它)

XY为双字节带符号数据,分别存放在DAXDAY单元,计算结果存入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 ; XY

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 ; 最高位为1CF1,有进位是负数

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单元中存放。编制程序求其中正数平均值及负数平均值,并分别存入MEANPMEANM单元。

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码分别存入NUMBDATAM单元。

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

DATA SEGMENT

A DB "ASESRFGDGRESDSSDDSXDREGHRD43RBVFB2S3432"

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 "PRINT","PRINT"

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 "PRINT","PRINT"

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

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

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

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 ;排完序后转显示

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

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 编制程序求XY的最小公倍数并存入CMTM单元,已知XY为字节类型正整数且分别存放在ADRXADRY单元。

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

数值之积除以最大公约数方法:(要求最小公倍数之大小不超过1个字大小)

假定X>Y如果X的交换程序请自己完成。

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 AX,X

MOV DX,0

MOV BX,Y

LOOP1:DIV BX

CMP DX,0

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

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

MOV DX,0

CMP AX,BX ;AXBX中较大的数为下一次的被除数

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进制数

;占用寄存器:BXCLAXDX(均已保护)

;输入参数:要显示数据在SI

;输出参数:

DISPLAY16 PROC

PUSH AX

PUSH BX

PUSH CX

PUSH DX

MOV BX,4 ;每个字显示416进制字符

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 ;否则为AF之间数,7

CHANGE12:MOV AH,2 ;显示1个字符

INT 21H

DEC BX ;处理下一个字符

CMP BX,0 ;是否为0

JNZ CHANGE10 ;不为0CHANGE10

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 ;最小公倍数最大为XY的乘积,因此试到乘数为Y为止

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

LOOP1:MOV AX,X

MUL BX ;XBX的乘积,看该乘积能否被Y除尽

PUSH AX ;保存该乘积,如果是最小公倍数就送显示

DIV Y ;XBX的乘积能否被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采用查表法,015中某数变为十六进制数字的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 DS,AX

MOV BL,X ;取数,82进制数放BL

MOV BH,0 ;准备用BX间址,因而将BH0

MOV 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进制数

;占用寄存器:BXCLAXDX(均已保护)

;输入参数:要显示数据在SI

;输出参数:

DISPLAY16 PROC

PUSH AX

PUSH BX

PUSH CX

PUSH DX

MOV BX,4 ;每个字显示416进制字符

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 ;否则为AF之间数,7

CHANGE12:MOV AH,2 ;显示1个字符

INT 21H

DEC BX ;处理下一个字符

CMP BX,0 ;是否为0

JNZ CHANGE10 ;不为0CHANGE10

POP DX

POP CX

POP BX

POP AX

RET

DISPLAY16 ENDP

CODE ENDS

END START

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

分析:假定数据均为无符号数。在数据区准备4个变量分别存放最大值、最小值、最大值存放地址与最小值存放地址,初始值为0OFFFFH00。从第一个数开始将数据放到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进制数

;占用寄存器:BXCLAXDX(均已保护)

;输入参数:要显示数据在SI

;输出参数:

DISPLAY16 PROC

PUSH AX

PUSH BX

PUSH CX

PUSH DX

MOV BX,4 ;每个字显示416进制字符

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 ;否则为AF之间数,7

CHANGE12:MOV AH,2 ;显示1个字符

INT 21H

DEC BX ;处理下一个字符

CMP BX,0 ;是否为0

JNZ CHANGE10 ;不为0CHANGE10

POP DX

POP CX

POP BX

POP AX

RET

DISPLAY16 ENDP

CODE ENDS

END START

4.31内存自BUFF单元开始的存储区连续存放100个学生的某科分数,编制循环程序统计100909980897079606950594049303920291019 09等各分数段的学生人数,并把结果连续存放在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 ;0100共分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 AX00E0H ;设置DS段地址为00E0H

MOV DSAX

MOV BX0200H ;BL0开始

MOV CXBX ;共计200H个单元

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

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

LOOP NEXT ;直到200H放到E0H:400H

MOV AH4CH

INT 21H

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

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

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

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

一种可能是CX0,数据段中偏移地址 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  BXBUF

           MOV CXN

           MOV AX0

LOPACMP BYTE PTR [BX]0

           JGE NEXT

           INC AX

NEXTINC BX

       LOOP LOPA

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

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

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

4.36已知当前的DSES指向同一个段,且当前数据段从0000H00FFH单元的内容分别为010203,……,0FEH0FFH00H,问下列程序执行后,0000H00FFH单元的内容有什么变化?

MOV DI0001H

MOV SI0000H

MOV CX0080H

CLD

REP MOVSW

00000082H中内容变为:01010202040406060808,……

4.37BEG为起始地址的存储区域中放有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编制计算SXYZ的程序。已知XYZ为用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 ;计算XY,存放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 ;计算sz,存放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


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

相关推荐