程序说明:
说明
运行可执行程序CAR.exe,选择1,小鸟飞过;选择2,汽车开过;选择3,退出。
函数图:
DATA SEGMENT ;数据段
INFO1 DB 0DH,0AH,'INPUT 1,2,OR 3:(1:bird,2:car,3:exit) $' ;字符串数据
INFO2 DB 0DH,0AH,'hairi $'
BUFA DB 200 ;存200?
DB ? ;存未确定的数,是定义在 RAM 中的,不是定义在 ROM。所以不修改时也有值,而且值会任意变化。
DB 200 DUP(0) ;数组数据
BUFB DB 200 DUP(?) ;数组数据
BIRD DB 76H,10,0,0 ;小鸟的字符图形表
DB 0C4H,07,0,1
DB 76H,10,-2,2
DB 0C4H,07,0,1
DB 76H,10,-2,2
DB 0C4H,07,0,1
DB 76H,10,-2,2
DB 0C4H,07,0,1
DB 76H,10,2,-2
DB 0C4H,07,0,1
DB 76H,10,2,-2
DB 0C4H,07,0,1
DB 76H,10,2,-2
DB 0C4H,07,0,1
CAR DB 7 ;小汽车的字符图形表
DB 52H,7,0,0
DB 0B1H,7,0,1
DB 0DBH,7,0,1
DB 0DBH,7,0,1
DB 4FH,7,1,0
DB 4FH,7,0,-3
DB 2,7,-2,1
CHAR_CNT DW ?
POINTER DW ?
LINE_ON DB ?
COL_ON DB ?
DATA ENDS
STACK SEGMENT stack ;堆栈段
DB 200 DUP(0)
STACK ENDS
CODE SEGMENT ;代码段
ASSUME CS:CODE,DS:DATA,SS:STACK
start:mov ax,data ;把data的数据给了ds
mov ds,ax
mov ah,0 ;设置显示方式为320*200彩色图形方式
mov al,4
int 10h ;BIOS 对屏幕及显示器所提供的服务程序
lea dx,info1 ;在显示器上显示字符串提示信息
mov ah,9
int 21h
mov ah,0 ;从键盘读取字符到AL寄存器
int 16h
CMP AL,31H ;比较AL是否等于1
JNE A ;不等跳转a
CALL XIAO ;调用子函数xiao
A: CMP AL,32H ;比较AL是否等于2
JNE B ;不等跳转b
CALL QICHE ;调用子函数qiche
B: CMP AL,33H ;比较AL是否等于3
JNE START ;跳转start
MOV AH,4CH ;终止当前程序并返回调用程序
INT 21H
CLEAR MACRO pch,pcl,pdh,pdl,pbh ;清屏宏定义
MOV AH,0
MOV AL,4
INT 10H
MOV AH,6 ;调用6号功能
MOV AL,0 ;设置整个屏幕为空白
MOV CH,pch
MOV CL,pcl ;窗口左上角(0行,0列)
MOV DH,pdh
MOV DL,pdl ;窗口右下角(24行,79列)
MOV BH,pbh ;正常属性显示
INT 10H
ENDM
xiao proc ;小鸟子程序
PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA ;把data给ds
MOV DS,AX
MOV AH,0 ;Sets the current video mode(al)
MOV AL,4
INT 10H
MOV AH,0BH ;设置背景色,bios内的调用
MOV BH,0
MOV BL,1
INT 10H
MOV AH,0BH ;设置彩色组
MOV BH,1
MOV BL,1
INT 10H
CLEAR 0,0,24,79,7
MOV AH,0FH ;读当前显示状态
INT 10H
MOV DH,10
MOV DL,0
BEGIN: MOV SI,2
MOV CX,1
LEA DI,BIRD ;DI指向小鸟字符表的首字母
DISP: CMP DL,80 ;执行80次disp
JAE exit1 ;cf=0时跳转
MOV AH,2 ;设置光标位置
INT 10H
MOV AH,9 ;显示小鸟字符图形
MOV AL,[DI]
;<character>8-bit ASCII character to put; if none
;given, AL used.
;
;<attrib>8-bit attribute to put; if none given,
; BL used.
;<page>8-bit page to put on; if none given, 0
; assumed.
MOV BL,[DI+1]
INT 10H
CALL DLY ;延时
MOV AH,9
MOV AL,' ' ;bios 9号函数,设置汉字和属性
MOV BL,04
INT 10H
INC DL
ADD DI,2
DEC SI
JNZ DISP ;si不为0就跳转disp
JMP BEGIN ;无条件跳转begin
exit1: RET
xiao endp
DLY PROC NEAR ;延时子程序
PUSH CX ;保护现场
PUSH DX
;PUSH AX
MOV DX,10000
DL1: MOV CX,6801
DL2:
;lea dx,INFO2
;mov ah,09
;int 21h
;mov ah,0B ;检测键盘状态
;INT 21h
;CMP AL,00 如果有输入就跳到dl3
;JE DL3
LOOP DL2
DEC DX ;消耗10000*6801个loop的时间,先loop dl2,后loop dl1
JNZ DL1
DL3: POP DX ;恢复现场
POP CX
;POP AX
RET
DLY ENDP
QICHE PROC near ;汽车子程序
PUSH AX ;保护现场
PUSH BX
PUSH CX
PUSH DX
MOV AH,0 ;bios的中断,设置显示模式
;Sets the current video mode
MOV AL,4
INT 10H
MOV AH,0BH ;设置彩色组颜色为绿、红、黄
MOV BH,01
MOV BL,00 ;Sets the cursor size and shape by specifying active scan
;lines. For color adapters, the lines are 0-7. For the
;monochrome adapter, the lines are 0-13.
INT 10H
CLEAR 0,0,24,79,7 ;清屏宏调用
LEA DI,CAR ;DI指向字符图形表
MOV DH,5 ;从第5行5列位置开始显示汽车
MOV DL,0
CALL MOVE_SHAPE ;调用函数MOVE_SHAPE
RET
QICHE ENDP
MOVE_SHAPE PROC NEAR
PUSH AX ;保护现场
PUSH BX
PUSH CX
PUSH DX
PUSH DI
MOV AH,0FH ;取当前显示方式
INT 10H
SUB CH,CH ;清空ch
MOV CL,[DI] ;CL放字符个数
INC DI ;DI指向字符图形表中的第一个字符
MOV CHAR_CNT,CX ;cx给CHAR_CNT
MOV POINTER,DI ;字符图形表中的第一个字符给pointer
MOV LINE_ON,DH
MOV COL_ON,DL
PLOT_NEXT:
ADD DH,[DI+2] ;改变行列坐标
ADD DL,[DI+3]
CMP DL,80 ;出屏否?
JB MOV_CRSR
Pop DI ;恢复现场
Pop DX
Pop CX
Pop BX
Pop AX
jmp exit2 ;无条件跳转
MOV_CRSR:
MOV AH,2 ;设置窗口位置Sets the cursor position dh,dl
INT 10H
MOV AL,[DI] ;取字符值
MOV BL,[DI+1] ;取字符属性
PUSH CX
MOV CX,1
MOV AH,09 ;显示字符
INT 10H
POP CX
ADD DI,4 ;DI指向下一个字符
LOOP PLOT_NEXT ;不断前进
CALL DLY ;跳转dly隔多长时间前进一次
CALL ERASE ;跳转erase
JMP SHORT PLOT_NEXT ;段内转移到标记处
exit2: ret
MOVE_SHAPE ENDP
ERASE PROC NEAR
MOV CX,CHAR_CNT ;保护窗口设置
MOV DI,POINTER
MOV DH,LINE_ON
MOV DL,COL_ON
ERASE_NEXT:
ADD DH,[DI+2]
ADD DL,[DI+3]
MOV AH,2
INT 10H
MOV AL,[DI]
MOV BL,0
PUSH CX ;保护cx
MOV CX,1
MOV AH,9
INT 10H
POP CX ;恢复cx
ADD DI,4
LOOP ERASE_NEXT
MOV CX,CHAR_CNT ;在下一行恢复窗口
MOV DI,POINTER
MOV DH,LINE_ON
INC COL_ON ;下移一行
MOV DL,COL_ON
RET
ERASE ENDP
CODE ENDS
END start
参数传递
程序调用关系如下:
主函数调用xiao, qiche;
xiao调用dly;
qiche调用move_shape; move_shape调用dly, erase。
与xiao之间无参数传递。与qiche之间无参数传递。
与move_shape之间的参数传递:约定单元法,为CHAR_CNT、POINTER、LINE_ON、和COL_ON。
主程序main与erase之间的参数传递:约定单元法,为CHAR_CNT、POINTER、LINE_ON、和COL_ON。
与dly之间的参数传递:无参数传递。
子程序qiche与move_shape之间的参数传递:寄存器法,为dx。
中断向量计算
本题用到了10H、21H函数库的函数调用。
10H号函数库:CS=410h+2h=42h , IP=410h=40h 。中断向量为0:40H。
21H号函数库:CS=421h+2h=86h , IP=421h=84h 。中断向量为0:84h。