编写并安装 int 7ch 中断例程,
功能:显示一个用 0 结束的字符串,中断例程安装在 0:200 处
|
参数:(dh)=行号,(dl)=列号,(cl)=颜色,ds:si 指向字符串首地址 |
assume cs:code
code segment
start: mov ax , cs
mov ds , ax
mov si , offset show_str
mov ax , 0
mov es , ax
mov di , 200h
mov cx , offset show_strend - offset show_str
cld
rep movsb
mov ax , 0
mov es , ax
mov word ptr es:[7ch*4] , 200h
mov word ptr es:[7ch*4+2] , 0
mov ax , 4c00h
int 21h
show_str: push dx
push cx
push si
mov ax , 0b800h
mov es , ax
mov ah , 0 ; 确保高8位为0
mov al , 160 ; 每行160个字符
mul dh ; al*行号dh->ax
mov bx , ax ; 暂存行偏移
mov ax , 0
mov al , 2
mul dl ; 列的偏移是2,1个存字符,一个存显示属性
add bx , ax ; 得到偏移地址
mov di , 0
mov al , cl ; 字符显示属性放到al中
mov ch , 0 ; cx 高8位设置为0
show: mov cl , ds:[si] ; 将字符串单个字符读入cl中
jcxz ok
mov es:[bx+di] , cl
mov es:[bx+di+1] , al
add di , 2
inc si
jmp short show
ok: pop si
pop cx
pop dx
iret
show_strend: nop
code ends
end start
|
assume cs:code
data segment
db 'Welcome to masm!' , 0
data ends
code segment
start: mov dh , 12 ; 要显示的所在行
mov dl , 32 ; 要显示的所在列
mov cl , 2 ; 要传递的显示属性
mov ax , data
mov ds , ax
mov si , 0 ; 入口参数DS:SI指向字符串
int 7ch ; 调用自己重写的中断
mov ax , 4c00h
int 21h
code ends
end start
|
编写并安装 int 7ch 中断例程 功能:完成loop指令功能 |
参数:(cx)=循环次数,(bx)=位移 |
assume cs:code
code segment
start: mov ax , cs
mov ds , ax
mov si , offset lp ; 中断例程安装
mov ax , 0
mov es , ax
mov di , 200h
mov cx , offset lpend - offset lp
cld
rep movsb
mov ax , 0 ; 设置中断向量表
mov es , ax
mov word ptr es:[7ch*4] , 200h
mov word ptr es:[7ch*4+2] , 0
mov ax , 4c00h
int 21h
lp: push bp ; 后面用到bp,保证退出不修改,先暂存
mov bp , sp ; 堆栈指针赋值给bp,bp对应的段寄存器和sp一样是ss
dec cx ; 中断实现cx-1
jcxz lpret
add [bp+2] , bx ; 中断入栈的时候最后入栈的是IP,刚才bp入栈,
; 由于mov后bp==sp,所以+2得到IP的栈中存储位置,加上bx,实现向上跳转完成loop功能
lpret: pop bp
iret
lpend: nop
code ends
end start
|
assume cs:code
code segment
start: mov ax , 0b800h
mov es , ax
mov di , 160*12
mov bx , offset s - offset se ; 负位移,实现向上跳转
mov cx , 80 ; 循环次数80
s: mov byte ptr es:[di] , '!'
mov byte ptr es:[di+1] , 10001100b ; 设置显示属性,闪烁高亮红色
add di , 2
int 7ch ; 修改后的 7ch 中断,实现loop s功能
se: nop
mov ax , 4c00h
int 21h
code ends
end start
|
// 在屏幕的第2、4、6、8行显示4句英文诗
assume cs:code
code segment
s1: db 'Good,better,best,' , '$'
s2: db 'Never let it rest,' , '$'
s3: db 'Till good is better,' , '$'
s4: db 'And better,best.' , '$'
s: dw offset s1 , offset s2 , offset s3 , offset s4
row: db 2 , 4 , 6 , 8
start: mov ax , 3
int 10h ; 调用10h号中断中的3号功能实现清屏
mov ax , cs
mov ds , ax
mov si , offset s ; si == 存储标号s:表示的数据段偏移
mov di , offset row ; di == 存储标号row:表示的数据段偏移
mov cx , 4
ok: mov bh , 0 ; 显示在0页
mov dh , [di] ; 显示在第2行
mov dl , 0 ; 0 列
mov ah , 2 ; 设置光标位置
int 10h
mov dx , [si] ; [si]==offset s,取出值就是s1的位移
mov ah , 9 ; 9号功能,显示ds:dx处以'$'结尾的字符串
int 21h
add si , 2 ; 偏移设置下一个要显示的字符串
inc di ; 偏移设置下一个行要显示的位置
loop ok
mov ax , 4c00h
int 21h
code ends
end start
|
10h 号中断的2号设置光标位置功能不会自动偏移光标,所以必须每次dl+1
改进:不用21h号中断的一次显示一行字符串,全用10h号中断显示,并设定相应的颜色 assume cs:code
code segment
s1: db 'Good,better,best,' , 0
s2: db 'Never let it rest,' , 0
s3: db 'Till good is better,' , 0
s4: db 'And better,best.' , 0
s: dw offset s1 , offset s2 , offset s3 , offset s4
row: db 0 , 2 , 4 , 6
start: mov ax , 3
int 10h ; 调用10h号中断中的3号功能实现清屏
mov ax , cs
mov ds , ax
mov si , offset s ; si == 存储标号s:表示的数据段
mov di , offset row ; di == 存储标号row:表示的数据段
mov cx , 4
num1: push cx ; 待会子程序要显示字符还要用到,先压栈保存
mov bh , 0 ; 显示在0页
mov dh , [di] ; 显示在第ds:[di]行
mov dl , 0 ; 0 列
mov ah , 2 ; 设置光标位置
int 10h
push si ; si相当于一个指针;本来si是指向标号s的,里面存的是4个字符串的偏移量;
;但是后面子程序要用10h号中断挨个输出字符串中的字符,如果[si+1]得到的只是s:中s2的偏移量,一个常数
;所以只能让这个指针si指向第一个s1:处的字符串,要设置si的值为s1:的偏移量
mov ax , [si]
mov si , ax
|
num3: mov ah , 9 ; 调用10h中断的9号功能显示字符
mov al , [si]
mov bh , 0
mov bl , 01001010b
mov cx , 1
int 10h
mov ah , 2 ; 调用10h中断的2号功能设置光标,10号中断显示字符只会在光标位置显示
add dl , 1
int 10h
cmp byte ptr [si] , 0 ; 如果读到0表示一行已经显示完成,跳转准备开始读取下一行
jz ok
inc si ; 一行没有读完就si偏移一个位置读取下一个字符
jmp num3 ; 跳转从新设置光标和显示对应字符
ok: pop si ; 恢复主程序si和cx
pop cx
add si , 2 ; si偏移2读取下一个常数(s2:的偏移量)
inc di ; di偏移1读取下一个字符串要显示的行
loop num1
mov ax , 4c00h
int 21h
code ends
end start
|