《IBM-PC汇编语言程序设计》(第2版)【沈美明 温冬婵】——第十章——自编解析与答案

10.1 写出指令,选择显示方式10H,并将背景设为绿色。
答: MOV AH, 00H
MOV AL, 10H ;选择显示方式10H(16色图形)
INT 10H
MOV AH, 10H
MOV AL, 00H
MOV BH, 10H ;背景设为绿色(02H也可以,是用DEBUG调试出来的)
MOV BL, 0 ;选择0号调色板
INT 10H
设置背景色也可用:
MOV AH, 0BH ;设置背景色和调色板
MOV BH, 0 ;设置背景色功能
MOV BL, 8 ;绿色背景
INT 10H
10.2 如何使用INT 10H的功能调用改变显示方式?
答:在AH中设置功能号00H,在AL中设置显示方式值,调用INT 10H即可。
10.3 VGA独有的一种显示方式是什么?

答:像素值为640×480,可同时显示16种颜色,这种显示方式(12H)是VGA独有的。
10.4 对于EGA和VGA显示适配器,使用显示方式13H时(只有VGA有),显示数据存在哪里?
答:显示数据存在显示存储器里。
10.5 对于VGA的显示方式13H时存放一屏信息需要多少字节的显存?
答:需要64000个字节。
10.6 利用BIOS功能编写图形程序:设置图形方式10H,选择背景色为蓝色,然后每行(水平方向)显示一种
颜色,每4行重复一次,一直到整个屏幕都显示出彩条。
答:程序如下:
TITLE GRAPHIX.COM
codeseg segment
assume cs:codeseg, ds:codeseg, ss:codeseg
org 100h
main proc far
mov ah, 00h
mov al, 10h ;选择显示方式10h(16色图形)
int 10h
mov ah, 0bh
mov bh, 00h
mov bl, 01h ;背景设为蓝色
int 10h
mov ah, 0bh
mov bh, 01h
mov bl, 00h ;设置调色板0#
int 10h
mov bx, 0 ;显存的第0页
mov cx, 0 ;起始列号为0列
mov dx, 0 ;起始行号为0行
line: mov ah, 0ch ;写像素点
mov al, bl

int 10h
inc cx
cmp cx, 640
jne line
mov cx, 0 ;起始列号为0列
inc bl
and bl, 03h ;只显示四种颜色(因此保留最低两位)
inc dx
cmp dx, 350
jne line
int 20h
main endp
codeseg ends
end main
10.7 修改10.6题的程序,使整个屏幕都显示出纵向的彩条。
答:程序如下:
TITLE GRAPHIX.COM
codeseg segment
assume cs:codeseg, ds:codeseg, ss:codeseg
org 100h
main proc far
mov ah, 00h
mov al, 10h ;选择显示方式10h(16色图形)
int 10h
mov ah, 0bh
mov bh, 00h
mov bl, 01h ;背景设为蓝色
int 10h
mov ah, 0bh

mov bh, 01h
mov bl, 00h ;设置调色板0#
int 10h
mov bx, 0 ;显存的第0页
mov cx, 0 ;起始列号为0列
mov dx, 0 ;起始行号为0行
line: mov ah, 0ch ;写像素点
mov al, bl
int 10h
inc dx
cmp dx, 350
jne line
mov dx, 0 ;起始行号为0行
inc bl
and bl, 03h ;只显示四种颜色(因此保留最低两位)
inc cx
cmp cx, 640
jne line
int 20h
main endp
codeseg ends
end main
10.8 按动键盘上的光标控制键,在屏幕上下左右任一方向上绘图,每画一点之前,由数字键0~3指定该点
的颜色值,按动ESC键,绘图结束,返回DOS。
答:程序如下:
;DRAW—Program to draw on screen with sursor arrows
;For 640*350 color mode
up equ 48h ;向上键的扫描值
down equ 50h ;向下键的扫描值

left equ 4bh ;向左键的扫描值
right equ 4dh ;向右键的扫描值
escape equ 1bh ;“Esc” character
codeseg segment
main proc far
assume cs:codeseg
;clear screen by scrolling it, using ROM call
start: mov ah, 06h
mov al, 00h
mov cx, 00h
mov dl, 79
mov dh, 24
int 10h
;screen pointer will be in CX,DX registers;row number (0 to 350d) in DX
;coumn number (0 to 640d) in CX
mov ah, 00h
mov al, 10h ;选择显示方式10h(16色图形)
int 10h
mov ah, 0bh
mov bh, 00h
mov bl, 01h ;背景设为蓝色
int 10h
mov ah, 0bh
mov bh, 01h
mov bl, 00h ;设置调色板0#
int 10h
mov dx, 175 ;设在屏幕中心
mov cx, 320
;get character from keyboard

get_char: mov ah, 0 ;键盘输入
int 16h
cmp al, escape
jz exit
cmp al, 33h ;>‘3’吗?
jg plot
cmp al,30h ;<‘0’吗?
jl plot
mov bl, al ;是‘0’~‘3’,设置颜色
and bl, 03
jmp get_char
;figure out which way to go, and draw new line
plot: mov al, ah
cmp al, up
jnz not_up
dec dx
not_up: cmp al, down
jnz not_down
inc dx
not_down: cmp al, right
jnz not_right
inc cx
not_ right: cmp al, left
jnz write
dec cx
;use ROM routine to write dot,reguires row# in DX,col in CX,color in AL
write: mov al, bl
mov ah, 0ch
int 10h

jmp get_char
exit: int 20h
main endp
codeseg ends
end start
10.9 位屏蔽寄存器的作用是什么?在16色,640×480显示方式中如何使用位屏蔽寄存器?
答:位屏蔽寄存器的作用是决定了新的像素值产生的方法。当位屏蔽寄存器的某位设为0时,相对应的像素值
直接由锁存器写入显存;位屏蔽寄存器的某位为1时,所对应的像素值由锁存器中的像素值与CPU数据或置位/
重置寄存器中相应位合并之后产生。
10.10 读映像选择寄存器的作用是什么?如果4个位面的内容都需要读取,读映像选择寄存器应如何设置?
答:读映像选择寄存器的作用是用于选择哪一个位面的字节读入CPU。读映像选择寄存器的0和1位,用来指定
哪个位面的锁存器内容读到CPU。如果4个位面的内容都需要读取,则必须对同一地址执行4次读操作,在每次
读之前,用指令分别设置读映像选择寄存器。
10.11 编写程序使一只“鸟”飞过屏幕。飞鸟的动作可由小写字母v (ASCII码76H)变为破折号(ASCII码
0C4H)来模仿,这个字符先后交替在两列显示。鸟的开始位置是0列20行,每个字符显示0.5秒,然后消失。
答:程序段如下:
TITLE Flier.EXE ;飞鸟程序
;******************************************
DSEG SEGMENT ;定义数据段
BIRD DB 76H, 07 ;小写字母v及属性
DB 0C4H, 07 ;破折号及属性
DSEG ENDS ;以上定义数据段
;******************************************
CSEG SEGMENT ;定义代码段
MAIN PROC FAR
ASSUME CS: CSEG, DS: DSEG
START: PUSH DS ;设置返回DOS
SUB AX, AX
PUSH AX

MOV AX, DSEG
MOV DS, AX ;给DS赋值
MOV AH, 0FH ;取当前显示方式
INT 10H
PUSH AX ;保存当前显示方式(AL)
MOV AH, 0 ;设置彩色80×25文本方式
MOV AL, 3
INT 10H
MOV DH, 20 ;20行
MOV DL, 0 ;0列
BEGIN: MOV SI, 2 ;字符v和破折号“-”交替显示
MOV CX, 1 ;一次显示一个字符及属性
LEA DI, BIRD
DISP: CMP DL, 79 ;飞到79列就退出
JAE EXIT
MOV AH, 2 ;置光标位置
INT 10H
MOV AH, 9 ;在光标位置显示字符及属性
MOV AL, [DI] ;取显示字符及属性
MOV BL, [DI+1]
INT 10H
CALL DELAY ;延时0.5秒
MOV AH, 9 ;在光标位置显示字符及属性
MOV AL, ‘ ’ ;显示空格,擦除该位置的字符
MOV BL, 7
INT 10H
INC DL ;飞到下一列
ADD DI, 2

DEC SI
JNZ DISP
JMP BEGIN
EXIT: POP AX ;恢复当前显示方式(AL)
MOV AH, 0
INT 10H
RET ;返回DOS
MAIN ENDP
;----------------------------------------------------------------------------------
DELAY PROC NEAR ;延时0.5s子程序
PUSH CX
PUSH DX
MOV DX, 50 ;延时0.5s
DEL1: MOV CX, 2801 ;延时10ms
DEL2: LOOP DEL2
DEC DX
JNZ DEL1
POP DX
POP CX
RET
DELAY ENDP ;DELAY子程序结束
;----------------------------------------------------------------------------------
CSEG ENDS ;以上定义代码段
;******************************************
END START ;汇编语言源程序结束
10.12 用图形文本的方法设计“Name=XXX”(X为你自己姓名的缩写),并将其数据编码定义在一个数组中。

答:用图形文本的方法设计“NAME=YQS”的程序和数组如下:
显示格式如下:
S h o o t i n g
TITLE NAME_YQS.EXE ;显示“NAME=YQS”的程序
;******************************************
;Graphics block message for the words shooting NAME=YQS
;00H→end of massage,0FFH→end of screen line
DSEG SEGMENT ;定义数据段
NAME_YQS DB 2 ;Start row(开始行)
DB 2 ;Start column(开始列)
DB 1000 0011B ;Color attribute
DB ‘Shooting’,0FFH,0FFH ;显示“Shooting”
DB 7 DUP(0DCH),0FFH,0FFH
;Graphics encoding of the word NAME=YQS using IBM character set
DB 0DEH, 0DBH, 4 DUP(20H), 0DBH, 0DDH, 20H, 0DBH, 0DFH, 0DBH
DB 20H, 20H, 0DBH, 5 DUP(20H), 0DBH, 20H, 2 DUP(0DFH, 0DBH)
DB 8 DUP(20H), 0DFH, 0DBH, 20H, 20H, 0DBH, 0DFH, 20H, 20H
DB 3 DUP(0DBH), 3 DUP(20H), 3 DUP(0DBH), 0DCH, 0FFH
DB 0DEH, 0DBH, 0DBH, 3 DUP(20H), 0DBH, 0DDH, 2 DUP(20H, 0DBH)
DB 20H, 20H, 0DBH, 0DBH, 3 DUP(20H), 0DBH, 0DBH, 20H, 20H, 0DBH
DB 11 DUP(20H), 3 DUP(0DBH, 20H, 20H), 20H, 0DBH, 20H, 0DBH
DB 3 DUP(20H), 0DFH, 0FFH
DB 0DEH, 0DBH, 20H, 0DBH, 20H, 20H, 0DBH, 0DDH, 2 DUP(20H, 0DBH)
DB 20H, 4 DUP(20H, 0DBH), 20H, 20H, 0DBH, 0DCH, 0DBH, 20H
DB 7 DUP(0DFH), 3 DUP(20H, 20H, 0DBH), 3 DUP(20H), 0DBH, 20H, 0DBH
DB 3 DUP(0DCH), 20H, 0FFH

DB 0DEH, 0DBH, 20H, 20H, 0DBH, 20H, 0DBH, 0DDH, 20H, 0DBH, 0DFH
DB 0DBH, 4 DUP(20H, 20H, 0DBH), 20H, 0DFH, 20H, 7 DUP(0DCH), 20H
DB 20H, 0DFH, 0DBH, 0DBH, 0DFH, 20H, 20H, 0DBH, 3 DUP(20H), 0DBH
DB 20H, 20H, 3 DUP(0DFH), 0DBH, 0FFH
DB 0DEH, 0DBH, 3 DUP(20H), 0DBH, 0DBH, 0DDH, 2 DUP(20H, 0DBH), 20H
DB 20H, 0DBH, 5 DUP(20H), 2 DUP(0DBH, 20H, 20H), 10 DUP(20H), 0DBH
DB 0DBH, 3 DUP(20H), 0DBH, 20H, 0DCH, 20H, 0DBH, 20H, 0DCH
DB 3 DUP(20H), 0DBH, 0FFH
DB 0DEH, 0DBH, 4 DUP(20H), 0DBH, 0DDH, 0DCH, 0DBH, 20H, 0DBH
DB 0DCH, 20H, 0DBH, 5 DUP(20H), 0DBH, 20H, 2 DUP(0DCH, 0DBH)
DB 9 DUP(20H), 0DCH, 0DBH, 0DBH, 0DCH, 3 DUP(20H), 0DFH, 0DFH
DB 0DBH, 20H, 20H, 0DFH, 3 DUP(0DBH), 20H, 0FFH
DB 00 ;结束显示标志
START_COL DB ?
DSEG ENDS ;以上定义数据段
;******************************************
;Text display procedures: display a message on the graphics screen
CSEG SEGMENT ;定义代码段
MAIN PROC FAR
ASSUME CS: CSEG, DS: DSEG
START: PUSH DS ;设置返回DOS
SUB AX, AX
PUSH AX
MOV AX, DSEG
MOV DS, AX

LEA DI, NAME_YQS
MOV DH, [DI] ;Get row into DH
INC DI ;Bump pointer
MOV DL, [DI] ;And column into DL
MOV START_COL, DL ;Store start column
MOV AH, 2 ;Set cursor position
MOV BH, 0 ;Page 0
INT 10H
INC DI ;Bump pointer to attribute
MOV BL, [DI] ;Get color code into BL
Char_write: INC DI ;Bump to message start
MOV AL, [DI] ;Get character
CMP AL, 0FFH ;End of line?
JE BUMP_ROW ;Next row
CMP AL, 0 ;Test for terminator
JE END_TEXT ;Exit routine
CALL SHOW_CHAR
JMP CHAR_WRITE
END_TEXT: RET ;返回DOS
Bump_row: INC DH ;Row control register
MOV DL, START_COL ;Column control to start column
MOV AH, 2 ;Set cursor position
MOV BH, 0 ;Page 0
INT 10H
JMP CHAR_WRITE
MAIN ENDP
;----------------------------------------------------------------------------------
;Display character in AL and using the color code in BL
Show_char PROC NEAR ;显示字符子程序

MOV AH, 9 ;BIOS service request number
MOV BH, 0 ;Page 0
MOV CX, 1 ;No repeat
INT 10H
;Bump cursor
INC DL
MOV AH, 2 ;Set cursor position
MOV BH, 0 ;Page 0
INT 10H
RET
Show_char ENDP ;SHOW_CHAR子程序结束
;----------------------------------------------------------------------------------
CSEG ENDS ;以上定义代码段
;******************************************
END START ;汇编语言源程序结束
10.13 游戏程序常常用随机数来控制其图形在屏幕上移动。请编写一程序,用随机数来控制笑脸符(ASCII码
02H)显示的位置。笑脸符每次显示的列号总是递增1。而行的位置可能是前次的上一行,下一行或同一行,这
根据随机数是0、1或2来决定,当行号变为0、24或列号变为79时显示结束。笑脸在每个位置上显示0.25s。(提
示:INT 1AH的AH=0是读当前时间的功能调用,利用该功能返回的随时都在变化的时间值作为产生随机数的基
数。)
答:程序段如下:
TITLE Disp_Laugh.EXE ;笑脸显示程序
;******************************************
CSEG SEGMENT ;定义代码段
MAIN PROC FAR
ASSUME CS: CSEG
START: PUSH DS ;设置返回DOS
SUB AX, AX
PUSH AX

MOV AH, 0FH ;取当前显示方式
INT 10H
PUSH AX ;保存当前显示方式(AL)
MOV AH, 0 ;设置彩色80×25文本方式
MOV AL, 3
INT 10H
MOV CX, 1 ;一次显示一个笑脸字符及属性
MOV DH, 12H ;12行,从屏幕左边的中间开始
MOV DL, 0 ;0列
BEGIN: CMP DL, 79 ;移到79列就退出
JAE EXIT
CMP DH, 0 ;移到第0行就退出
JBE EXIT
CMP DH, 24 ;移到第24行就退出
JAE EXIT
MOV AH, 2 ;置光标位置
INT 10H
MOV AH, 9 ;在光标位置显示字符及属性
MOV AL, 02H ;取笑字符及属性
MOV BL, 7
INT 10H
CALL DELAY ;延时0.25秒
MOV AH, 9 ;在光标位置显示字符及属性
MOV AL, ‘ ’ ;显示空格,擦除该位置的字符
MOV BL, 7
INT 10H
INC DL ;移到下一列

PUSH DX
MOV AH, 0 ;读当前时间, CH:CL=时:分,DH:DL=秒:1/100秒
;产生随机数基数
INT 1AH
MOV AX, DX
POP DX
AND AL, 03H ;随机数为1/100秒的最低两位
JZ DOWN ;随机数的最低两位为0则下降一行
CMP AL, 1
JNZ LEVEL ;随机数的最低两位为≥2则水平移动
DEC DH ;随机数的最低位为1则上跳一行
JMP BEGIN
DOWN: INC DH
LEVEL: JMP BEGIN
EXIT: POP AX ;恢复当前显示方式(AL)
MOV AH, 0
INT 10H
RET ;返回DOS
MAIN ENDP
;----------------------------------------------------------------------------------
DELAY PROC NEAR ;延时0.25s子程序
PUSH CX
PUSH DX
MOV DX, 25 ;延时0.25s
DEL1: MOV CX, 2801 ;延时10ms
DEL2: LOOP DEL2
DEC DX
JNZ DEL1
POP DX

POP CX
RET
DELAY ENDP ;DELAY子程序结束
;----------------------------------------------------------------------------------
CSEG ENDS ;以上定义代码段
;******************************************
END START ;汇编语言源程序结束
10.14 分配给PC机主板上的8253/54定时器的端口地址是什么?
答:8253/54定时器的3个独立计数器Counter0、Counter1和Counter2的端口地址分别为40H、41H和
42H。8253/54内部还有一个公用的控制寄存器,端口地址为43H。
10.15 8253/54定时器的三个计数器,哪一个用于扬声器?它的端口地址是什么?
答:8253/54定时器的计数器Counter2用于扬声器,它的端口地址为42H。
10.16 下面的代码是利用监控端口61H的PB4来产生延迟时间的,它适用于所有的286、386、Pentium PC及兼
容机。请指出该程序的延迟时间是多少?
MOV DL, 200
BACK: MOV CX, 16572
WAIT: IN AL, 61H
AND AL, 10H
CMP AL, AH
JE WAIT
MOV AH, AL
LOOP WAIT
DEC DL
JNZ BACK
答:该程序的延迟时间是200×16572×15.08μs=49981152μs≈50s。
10.17 在PC机上编写乐曲程序“Happy Birthday”,乐曲的音符及音频如下:
歌词 音符 音频 节拍 歌词 音符 音频 节拍 歌词 音符
音频 节拍
hap C 262 1/2 day C 262 1 so D 294 3

py C 262 1/2 to G 392 1 hap Bb 466 1/2
birth D 294 1 you F 349 2 py Bb 466 1/2
day C 262 1 hap C 262 1/2 birth A 440 1
to F 349 1 py C 262 1/2 day C 262 1
you E 330 2 birth D 294 1 to G 392 1
hap C 262 1/2 day A 440 1 you F 349 2
py C 262 1/2 dear F 349 1
birth D 294 1 so E 330 1
答:程序如下:
TITLE MUSIC — A music of ‘Happy Birthday’ ;连接时需加上GENSOUND程序
EXTRN SOUNDF: FAR ;SOUNDF是外部过程——通用发声程序
;******************************************
STACK SEGMENT PARA STACK ‘STACK’ ;定义堆栈段
DB 64 DUP (‘STACK.’)
STACK ENDS ;以上定义堆栈段
;******************************************
DSEG SEGMENT PARA ‘DATA’ ;定义数据段
MUS_FREQ DW 262, 262, 294, 262, 349, 330, 262, 262, 294, 262,392, 349, 262, 262
DW 294, 440, 349, 330, 294, 466, 466,440,262, 392, 349, -1
MUS_TIME DW 25, 25, 50, 50, 50, 100
DW 25, 25, 50, 50, 50, 100
DW 25, 25, 50, 50, 50, 50, 150
DW 25, 25, 50, 50, 50, 100
DSEG ENDS ;以上定义数据段
;******************************************
CSEG SEGMENT PARA ‘CODE’ ;定义代码段
ASSUME CS: CSEG, DS: DSEG, SS: STACK
MUSIC PROC FAR
PUSH DS ;设置返回DOS

SUB AX, AX
PUSH AX
MOV AX, DSEG
MOV DS, AX ;给DS赋值
LEA SI, MUS_FREQ ;取发声的频率(音阶)表首地址
LEA BP, MUS_TIME ;取发声的节拍(时间)表首地址
FREQ: MOV DI, [SI] ;读取频率值
CMP DI, -1 ;歌曲结束了吗?
JE END_MUS
MOV BX, DS:[BP] ;读取节拍
CALL SOUNDF ;调通用发声子程序
ADD SI, 2
ADD BP, 2
JMP FREQ
END_MUS: RET ;返回DOS
MUSIC ENDP
CSEG ENDS ;以上定义代码段
;******************************************
END MUSIC ;汇编语言源程序结束
以下是SOUNDF ——外部的通用发声子程序(教材392页)
TITLE SOUNDF —— 通用发声子程序
;******************************************
PUBLIC SOUNDF ;定义为公共过程
;******************************************
CSEG1 SEGMENT PARA ‘CODE’ ;定义代码段
ASSUME CS: CSEG1
SOUNDF PROC FAR

PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
MOV AL, 0B6H ;写定时器8253的工作方式
OUT 43H, AL
MOV DX, 12H ;根据频率求8253的计数值,即533H*896/freq
MOV AX, 533H*896 ;(DX),(AX)=123280H=533H*896
DIV DI ;(DI) = freq
OUT 42H, AL ;向8253送计数值
MOV AL, AH
OUT 42H, AL
IN AL, 61H ;取8255的PB口当前内容,并保护
MOV AH, AL
OR AL, 3 ;开始发声,PB1=1,PB0=1
OUT 61H, AL
WAIT1: MOV CX, 663 ;延时(BX)×10ms
CALL WAITF
MOV AL, AH
AND AL, 0FCH ;停止发声,PB1=0,PB0=0
OUT 61H, AL
POP DI
POP DX
POP CX
POP BX
POP AX
RET
SOUNDF ENDP

;******************************************
WAITF PROC NEAR
PUSH AX
WAITF1: IN AL, 61H
AND AL, 10H
CMP AL, AH
JE WAITF1
MOV AH, AL
LOOP WAITF1
POP AX
RET
WAITF ENDP
CSEG1 ENDS ;以上定义代码段
;******************************************
END
10.18 编写用键盘选择计算机演奏歌曲的程序。首先在屏幕上显示出歌曲名单如下:
A MUSIC 1
B MUSIC 2
C MUSIC 3
当从键盘上输入歌曲序号A,B或C时,计算机则演奏所选择的歌曲,当在键盘上按下0键时,演奏结束。
答:程序段如下:
MUS_LST DB ‘A MUSIC 1’, 0DH, 0AH
DB ‘B MUSIC 2’, 0DH, 0AH
DB ‘C MUSIC 3’, 0DH, 0AH
DB ‘0 END’, 0DH, 0AH, ‘$’

MOV AH, 09 ;显示字符串的DOS功能调用
LEA DX, MUS_LIST
INT 21H

INPUT: MOV AH, 1 ;键盘输入一个字符的DOS功能调用
INT 21H
CMP AL, ‘0’ ;结束演奏吗?
JE EXIT
OR AL, 0010 0000B ;变为小写字母
CMP AL, ‘a’ ;演奏歌曲a吗?
JNZ B0
CALL MUSIC1 ;去演奏歌曲A
JMP INPUT
B0: CMP AL, ‘b’ ;演奏歌曲b吗?
JNZ C0
CALL MUSIC2 ;去演奏歌曲B
JMP INPUT
C0: CMP AL, ‘c’ ;演奏歌曲c吗?
JNZ INPUT
CALL MUSIC3 ;去演奏歌曲C
JMP INPUT
EXIT: RET ;返回

 

参考文章

http://blog.sina.com.cn/s/blog_77f58b350100q4dv.html

https://wenku.baidu.com/view/303e0e114431b90d6c85c720.html

https://shentuzhigang.blog.csdn.net/article/details/106560578

你可能感兴趣的:(#,汇编语言)