(1)
;==========================================================================
;编写并安装int 7CH中断例程,功能为显示一个用0结尾的字符串,
;中断例程安装在0:200H处.
;参数:(DH)=行号,(DL)=列号,(CL)=颜色,DS:SI指向字符串首地址.
;以上中断例程安装成功后,对下面的程序进行单步跟踪,尤其注意
;int、iret指令执行前后CS、IP和栈中的状态.
;==========================================================================
ASSUME CS:CODE
DATA SEGMENT
DB "Welcome to masm!",0
DATA ENDS
CODE SEGMENT
START:
;安装7ch中断
MOV AX,CS
MOV DS,AX ;(DS)=CODE段段地址
MOV SI,OFFSET SHOW_STR ;(SI)=传送原始位置的起始偏移地址
MOV AX,0
MOV ES,AX ;(ES)=0
MOV DI,200H ;(DI)=200H,一段不会被使用的空间,用来存放中断处理程序
MOV CX,OFFSET SHOW_STR_END-OFFSET SHOW_STR ;(CX)=要复制的中断处理程序的长度
CLD ;DF标志位置零,正向传送
REP MOVSB ;将CX个字节的内容从DS:SI复制到ES:DI
;(将中断处理程序从CS段复制到0:200H处)
;设置中断向量表
MOV AX,0
MOV ES,AX ;(ES)=0
MOV WORD PTR ES:[4*7CH],200H ;设置0号中断的偏移地址为200H
MOV WORD PTR ES:[4*7CH+2],0 ;设置0号中断的段地址为0
;输出字符串,测试7ch中断
MOV AX,DATA
MOV DS,AX ;初始化DS
MOV SI,0 ;SI=0,DS:SI指向字符串
MOV DH,10 ;行号
MOV DL,10 ;列号
MOV CL,2 ;颜色
INT 7CH ;调用INT 7CH中断
MOV AX,4C00H
INT 21H
;7ch中断处理程序
;----------------------------------------------------------------------------
;功能:显示一个用0结尾的字符串
;参数:DS:SI指向字符串的首地址,(DH)=行号,(DL)=列号,(CL)=颜色
;返回:无
SHOW_STR:
PUSH SI ;保护现场
PUSH DI
PUSH AX
PUSH DX
PUSH CX
PUSH ES
MOV AX,0B800H
MOV ES,AX ;(ES)=显示缓冲区段地址
MOV AL,0A0H ;以下计算初始字符的偏移地址
MUL DH ;行数×0A0H(160个字节)
MOV DI,AX ;转移到DI中
MOV AL,2 ;显示缓冲区中一个字符占两个字节空间
MUL DL ;2×列号
ADD DI,AX ;获得初始字符的偏移地址
BEGIN_SHOW:
MOV AL,[SI] ;(AL)=[SI]=字符的ASCII码
CMP AL,0 ;和0比较,是不是结尾符
JE SHOW_STR_RET ;是,则跳转到SHOW_STR_RET
MOV ES:[DI],AL ;不是,则转移到显示缓冲区(显示到屏幕)
INC SI ;SI+1,指向下一个字符
INC DI ;DI+1,准备写入字符的属性
MOV ES:[DI],CL ;写入字符的属性
INC DI ;DI+1,指向下一个字符在显示缓冲区(屏幕上)的位置
JMP BEGIN_SHOW ;继续输出下一个字符
SHOW_STR_RET:
POP ES ;恢复现场
POP CX
POP DX
POP AX
POP DI
POP SI
IRET ;中断返回
SHOW_STR_END:
NOP
;----------------------------------------------------------------------------
CODE ENDS
END START
(2)
;==========================================================================
;编写并安装int 7CH中断例程,功能为完成loop指令的功能,
;中断例程安装在0:200H处.
;参数:(CX)=循环次数,(BX)=位移.
;以上中断例程安装成功后,对下面的程序进行单步跟踪,尤其注意
;int、iret指令执行前后CS、IP和栈中的状态.
;在屏幕中间显示80个'!'.
;==========================================================================
ASSUME CS:CODE
DATA SEGMENT
DATA ENDS
CODE SEGMENT
START:
;安装7ch中断
MOV AX,CS
MOV DS,AX ;(DS)=CODE段段地址
MOV SI,OFFSET LP ;(SI)=传送原始位置的起始偏移地址
MOV AX,0
MOV ES,AX ;(ES)=0
MOV DI,200H ;(DI)=200H,一段不会被使用的空间,用来存放中断处理程序
MOV CX,OFFSET LPEND-OFFSET LP ;(CX)=要复制的中断处理程序的长度
CLD ;DF标志位置零,正向传送
REP MOVSB ;将CX个字节的内容从DS:SI复制到ES:DI
;(将中断处理程序从CS段复制到0:200H处)
;设置中断向量表
MOV AX,0
MOV ES,AX ;(ES)=0
MOV WORD PTR ES:[4*7CH],200H ;设置0号中断的偏移地址为200H
MOV WORD PTR ES:[4*7CH+2],0 ;设置0号中断的段地址为0
;输出字符,测试7ch中断
MOV AX,DATA
MOV DS,AX ;初始化DS
MOV AH,2 ;置光标
MOV BH,0 ;第0页
MOV DH,12 ;中间一行
MOV DL,0 ;让80个'!'在屏幕中间,第一个在最左边
INT 10H
MOV CX,80 ;循环次数=80
MOV BX,OFFSET EXCL-OFFSET EXCL_END ;转移位移
EXCL:
PUSH BX ;保存(BX)和(CX),后面执行INT 7CH时要用到
PUSH CX
MOV AH,2 ;置光标
MOV BH,0 ;第0页
INT 10H
MOV AH,9 ;在光标位置显示字符
MOV AL,'!' ;字符
MOV BL,2 ;颜色
MOV BH,0 ;第0页
MOV CX,1 ;重复1次
INT 10H
INC DL ;右移一列
POP CX ;恢复(BX)和(CX),作为INT 7CH中断的参数
POP BX
INT 7CH ;调用INT 7CH中断,实现LOOP功能
EXCL_END:
NOP
MOV AX,4C00H
INT 21H
;7ch中断处理程序
;----------------------------------------------------------------------------
;功能:完成loop指令的功能
;参数:(CX)=循环次数,(BX)=位移
;返回:(CX)=循环次数
LP:
PUSH BP ;因为要用到BP,先压入
MOV BP,SP ;(BP)=(SP)=栈顶,此时栈顶为BP原来的值
;必先执行这两句,如果先执行下面两句,有可能造成POP时没有对应的PUSH.
DEC CX ;循环次数-1
JCXZ LPRET ;如果为0,跳转到LPRET
ADD [BP+2],BX ;原来[BP+2]=IP=OK处的偏移地址 ,(IP)+(BX)=S处的偏移地址
LPRET:
POP BP ;恢复BP的值
IRET ;中断返回
LPEND:
NOP
;----------------------------------------------------------------------------
CODE ENDS
END START
(3)
;==========================================================================
;下面的程序,分别在屏幕的2、4、6、8行显示4句英文诗,补全程序.
;完成后编译运行,体会其中的思想.
;==========================================================================
ASSUME CS:CODE
CODE SEGMENT
;书上S1、S2、S3、S4、S、ROW后面有冒号":",
;然而这样在有的编译器里编译貌似通不过的说
;MASM2015的编译器ML.EXE 6.11版不行,MASM.EXE可以
S1 DB "Good,better,best,",'$'
S2 DB "Never let itrest,",'$'
S3 DB "Till good isbetter,",'$'
S4 DB "Andbetter,best.",'$'
S DW OFFSET S1,OFFSET S2,OFFSET S3,OFFSET S4
ROW DB 2,4,6,8
START:
MOV AX,CS ;DS和CS使用同一段
MOV DS,AX
MOV BX,OFFSET S ;BX用来寻址字符串的首地址
MOV SI,OFFSET ROW ;SI用来寻址行数
MOV CX,4 ;循环次数4
OK:
MOV BH,0 ;0页
MOV DH,BYTE PTR CS:[SI] ;(DH)=行数
MOV DL,0 ;(DL)=列数
MOV AH,2 ;置光标
INT 10H
MOV DX,CS:[BX] ;DS:DX指向字符串的首地址
MOV AH,9 ;输出以"$"结尾的字符串
INT 21H
INC SI ;SI指向下一句诗的行数
ADD BX,2 ;BX指向下一句诗的字符串的首地址
LOOP OK ;输出下一句诗
MOV AX,4C00H
INT 21H
CODE ENDS
END START