第四章 汇编语言程序设计
4-2 下列程序执行后,寄存器AX ,BX ,CX 的内容分别是多少?
ORG 0202H
DA_WORD DW 20H
MOV AX,DA_WORD ;(AX)=0020H
MOV BX,OFFSET DA_WORD ;(BX)=0202H (BX)=0,这是
书中的参考答案
MOV CL,BYTE PTR DA_WORD ;(CL)=20H(因PTR ,则字的第
一字节)
MOV CH,TYPE DA_WORD ;(CH)=2(变量类型数值)
;(CX )=0220H
4-4 试编制一程序(不是程序段), 把CHAR1中各小写字母分
别转换为对应的大写字母, 并存放在CHAR2开始的单元中
DDD0 SEGMENT
CHAR1 DB ‘abcdef ’
N EQU $-CHAR1; 变量必须先定义后使用, 而不能
相反
CHAR2 DB N DUP(0);不能把此句与上一句对调 DDD0 ENDS
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS ;P126(代码段和堆栈段是不可少的)
CSEG SEGMENT ASSUME CS:CSEG,DS:DDD0,SS:STACK START: MOV AX,DDD0
MOV DS,AX ;MOV DX,AX???
MOV ES,AX ;只要SI,DI 都用
MOV SI,0 ;LEA SI,CHAR1
MOV DI,0 ;LEA DI,CHAR2
MOV CX,N
AGAIN: MOV AL,CHAR1[SI] ; MOV AL,[SI]
SUB AL,20H
MOV CHAR2[DI],AL ; MOV [DI],AL
MOV DL ,AL ;不是必须的,但做实验是有用的。
MOV AH,2
INT21H
INC SI
INC DI LOOP AGAIN MOV AH,4CH INT 21H ;不是必须的 CSEG ENDS END START
第二种方法:
DDD0 SEGMENT
CHAR1 DB ‘abcdef ’
N EQU $-CHAR1
CHAR2 DB N DUP(0) DDD0 ENDS
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS ;P126(代码段和堆栈段是不可少的)
CSEG SEGMENT
ASSUME CS:CSEG,DS:DDD0,SS:STACK
START: MOV AX,DDD0
MOV DS,AX
MOV ES,AX
LEA SI,CHAR1
LEA DI,CHAR2
MOV CX,N
CLD ;不写(隐含) 也是0(递增)但不能STD
AGAIN: LODSB ;执行一次, 隐含修改SI
SUB AL,32
stosb ;MOV [DI],AL;执行一次, 隐含修改DI
nop ;INC DI
LOOP AGAIN ;LOOP指令只修改CX, 不管SI,DI
MOV AH,4CH
INT 21H ;不是必须的
CSEG ENDS
END START
4-6在BUF 地址处起,存放有100个字节的字符串,设其中有一个以上的“A ”字符,编程查找出第一个“A ”字符相对起始地址的距离,并将其存入LEN 单元。
方法1 DDD0 SEGMENT BUF DB‘qasdA%^9F26HsdfhA$#12345678’
DB ‘DFGH234546JII2334JI5467OPPAVG ’
DB ‘ASDFG45667RTY ’; 必须写实际的
LEN DW ?;为变量LEN 保留一个字 DDD0 ENDS
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
CSEG SEGMENT
ASSUME CS:CSEG,DS:DDD0,SS:STACK
START: MOV AX,DDD0
MOV DS,AX
MOV ES,AX
MOV CX,100
LEA DI,BUF ;MOV DI,OFFSET BUF
MOV AL,‘A ’
REPNE SCASB
DEC DI ;不必判断是否找到,一定找到
MOV LEN,DI ;MOV BX,OFFSET LEN MOV [BX],DI
MOV AH,4CH
INT 21H
CSEG ENDS
END START
4-8 某程序设置的数据区如下所示,画出该数据段内容在内存中的存放形式(要
用十六进制补码表示,按字节组织) DATA SEGMENT DB1 DB 12H,34H,0,56H DW1 DW 78H,90H,0AB46H,1234H 0004H DW1 ADR1 DW DB1 ADR2 DW DW1 AAA DW $-DB1 BUF DB 5 DUP(0) DATA ENDS
000CH ADR1
000EH ADR2 0010H AAA
0012H BUF
0000H DB1
4-10 以BUF1和BUF2开头的2个字符串,其长度均为LEN ,试编程实现:
(1)将BUF1开头的字符串送到BUF2开始的内存空间。 (2)将BUF1开始的内存空间全部清零。
(1) DDD0 SEGMENT
BUF1 DB ‘QWE233459JKGHGFHGF ’
BUF2 DB ‘ASD33459JKGHGFHGFI ’
LEN EQU LENGTH BUF2 ;DB $-BUF2 DDD0 ENDS
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
CSEG SEGMENT
ASSUME CS:CSEG,DS:DDD0,SS:STACK START: CLD
MOV AX,DDD0
MOV DS,AX
MOV ES,AX
MOV CX,LEN
LEA SI, BUF1 ;MOV SI,OFFSET BUF1
LEA DI, BUF2 ;MOV DI,OFFSET BUF2
REP MOVSB
CSEG ENDS
END START
(2)
DDD0 SEGMENT BUF1 DB ‘QWE233459JKGHGFHGF ’
LEN EQU LENGTH BUF1 DDD0 ENDS
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
CSEG SEGMENT
ASSUME CS:CSEG,DS:DDD0,SS:STACK
START: CLD
MOV AX,DDD0
MOV DS,AX
MOV CX,LEN
MOV AL,0
LEA DI, BUF1 ;MOV DI,OFFSET BUF1
LLL: STOSB
DEC CX
JNZ LLL CSEG ENDS
END START
第二种做法:
D SEGMENT
BUF1 DB ‘QWE233459JKGHGFHGF ’
BUF2 DB ‘ASD33459JKGHGFHGFI ’
D ENDS
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
CSEG SEGMENT
ASSUME CS:CSEG,DS:D,SS:STACK
BG : MOV AX,D
MOV DS,AX
MOV ES,AX
LEA SI,BUF1
LEA DI,BUF2
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 BG
4-14` 试编写一程序,找出BUF 数据区中带符号数的最大数和最小数,把最大数放到BH 单元,把最小数放到BL 单元。
DDD0 SEGMENT BUF DB 5,90,-45,100,99,„„„,-12
N EQU $-BUF
DDD0 ENDS
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
CSEG SEGMENT
ASSUME CS:CSEG,DS:DDD0,SS:STACK
START: MOV AX,DDD0
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]
LOOP AGAIN
JMP STOP
NEXT: CMP BL,BUF[SI]
JLE ABC
MOV BL,BUF[SI]
ABC :LOOP AGAIN
STOP: MOV AH,4CH
INT 21H
CSEG ENDS
END START
4-16 若AL 中的内容为2位压缩的BCD 数68H ,试编程:(1)
将其拆开成非压缩的BCD 数,高低位分别存入BH 和BL 中。
(2)将上述要求的2位BCD 码变换成对应的ASCII 码,并且存入CH 和CL 中。
(1)
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
CSEG SEGMENT
ASSUME CS:CSEG, SS:STACK
START: MOV BL,AL ;而不是AX
AND BL,0FH
MOV BH,AL
AND BH,0F0H
MOV CL,4
SHR BH,CL (逻辑右移)
CSEG ENDS
END START
(2)
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
CSEG SEGMENT
ASSUME CS:CSEG,SS:STACK
START: ADD BL,30H
MOV CL,BL
ADD BH,30H
MOV CH,BH
ENDS
END START 方法2
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
CSEG SEGMENT
ASSUME CS:CSEG,SS:STACK
START: MOV BL,AL
AND BL,0FH ;(BL )是低位非压缩的BCD 码
MOV DL,BL
ADD DL,30H ;(DL )是低位ASCII 码
MOV BH,AL ;(BH )将是高位非压缩的BCD 码 AND BH,0F0H
MOV CL,4
SHR BH,CL ;(BH )是高位非压缩的BCD 码
MOV CH,BH
ADD CH,30H ;(CH )是高位ASCII 码
MOV CL,DL ;(CL )是低位ASCII 码
CSEG ENDS
4-18试用子程序结构编写一程序:从键盘输入一个2位十
进制的月份数(01~12),然后显示出相应的英文缩写名。 提示:根据题目要求实现的功能,可编写用一个主程序MAIN 分别调用几个子程序。
(1) INPUT 从键盘接收一个2位数,并把它转换为对应的
二进制数。
(2) LOCATE 把输入的月份数与其英文缩写名(如JAN ,
FEB ,MAR ,APP ,MAY ,JUN 等)对应起来,制成一个字
符表以便查找。
(3) DISPLAY 将找到的缩写字母在屏幕上显示出来,显
示可用DOS 所提供的显示功能(INT 21H 的09号功能)。
DDD0 SEGMENT
D1 DB "Please input month from the
keyboad",0DH,0AH,"$"
D2 DB 3, ?,3 DUP(?) END START
D3 DB "ERROR",0DH,0AH,"$"
MONTH0 DB "JAN",0DH,0AH,"$"
DB "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,"$"
DDD0 ENDS
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
CSEG SEGMENT ASSUME CS:CSEG,DS:DDD0,SS:STACK START:CLD
MOV AX,DDD0
MOV DS,AX
CALL INPUT
CALL LOCATE
CALL DISPLAY
MOV AH,4CH
INT 21H
CSEG ENDS ;不可少
END START
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
RET
INPUT ENDP
LOCATE PROC NEAR
DEC AL ;
CMP AL,0CH
JNC ERROR ;≥12(原13), 输入错误
MOV BL,06H
MUL BL
MOV AH,0
MOV SI,Ax ;AX 里放的是月份-1
MOV DX,word ptr MONTH0[SI];制成一个字符表以便查找。
ret
ERROR:LEA DX,D3 ;将D3表示的相对地址送DX RET
LOCATE ENDP
DISPLAY PROC NEAR
MOV AH,09H;将找到的缩写字母在屏幕上显示出来
INT 21H
RET
DISPLAY ENDP
CSEG ENDS
END START
关于串操作指令与循环指令的说明:
1. 串操作指令MOVSB/MOVSW、CMPSB/CMPSW、
SCASB/SCASW、LODSB/LODSW、STOSB/STOSW每执行一次,指针(SI 、DI )都自动±1或±2,但这条指令不管计数器CX 的修改。
2. 串操作指令的重复前缀REP (无条件重复)、
REPE/REPZ(当相等/为0时重复)、REPNE/REPNZ(当不相等/不为0时重复),每重复一次,计数器CX 自动减1/减2。
3. 循环指令LOOP (循环)、LOOPE/LOOPZ(等于/结果为0循环)、LOOPNE/LOOPNZ(不等于/结果不为0循环):每循环一次,计数器CX 都自动减1,并且,CX
为0时退出循环的一个条件。但这些指令不管数据指针(SI 、DI )的修改。
注意:第三章作业和第四章作业的要求区别:
第三章作业是编写程序段,不必按段结构写;
第四章作业是编写程序,必须按段结构写
有的同学的作业太潦草.