0%

中断例程装载程序源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
; 安装新的 7ch 中断例程,实现如下功能的子程序:
; 1) 清屏
; 2) 设置前景色
; 3) 设置背景色
; 4) 向上滚动一行

; 入口参数:
; ah=功能号:0清屏,1前景色,2背景色,3向上滚动一行
; 对于1、2号功能,用al传递颜色值,范围0~7的整数

assume cs:code
code segment
start:
mov ax,cs
mov ds,ax
mov si,offset setscreent ; ds:si指向中断例程的代码

mov ax,0
mov es,ax
mov di,200h ; es:di指向中断例程装载位置
mov cx,offset setsrcend - offset setscreent ; 中断例程长度
cld
rep movsb ; 串传输

; 设置 7ch 号中断向量
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

; 中断处理程序开始
setscreent:
jmp short set ; 此指令占2字节
; 此dw数据开始地址为 0:200h入口地址+2 即0:202h
; sub1为数据标号,dw sub1相当于dw offset sub1
dw 200h+sub1-setscreent,200h+sub2-setscreent,200h+sub3-setscreent,200h+sub4-setscreent
set:
push bx
cmp ah,3 ; 判断功能号是否大于3
ja sret
mov bl,ah
mov bh,0
add bx,bx ; ah中的功能号*2=table表中的偏移
call word ptr cs:[bx+202h] ; 此中断执行时,cs=0
sret:
pop bx
iret

sub1: ; 清屏
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0 ; 显存的偶地址单元为字符
mov cx,2000
sub1s:
mov byte ptr es:[bx],' ' ; 空格填充屏幕
add bx,2
loop sub1s
pop es
pop cx
pop bx
ret

sub2: ; 设置字体颜色
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1 ; 显存的奇地址单元为属性
mov cx,2000
sub2s:
and byte ptr es:[bx],11111000b
or es:[bx],al
add bx,2
loop sub2s
pop es
pop cx
pop bx
ret

sub3: ; 设置背景色
push bx
push cx
push es
mov cl,4
shl al,cl
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub3s:
and byte ptr es:[bx],10001111b
or es:[bx],al
add bx,2
loop sub3s
pop es
pop cx
pop bx
ret

sub4: ; 向上滚动一行
push cx
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si,160 ; ds:si指向n+1行
mov di,0 ; es:di指向n行
cld
mov cx,24 ; 共复制24行
sub4s:
push cx
mov cx,160
rep movsb ; 一行复制完,si+=160,di+=160
pop cx
loop sub4s
mov cx,80
mov si,0
sub4s1:
mov byte ptr [160*24+si],' ' ; 最后一行清空
add si,2
loop sub4s1
pop ds
pop es
pop di
pop si
pop cx
ret
; 中断处理程序结束

setsrcend:
nop

code ends
end start
阅读全文 »

从 CMOS RAM 读取时间并显示到屏幕。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
; 显示CMOS中当前日期时间
assume cs:code
code segment
src:
db 9,8,7,4,2,0 ; 年月日时分秒的地址
dst:
db 'yy/mm/dd hh:mm:ss',0

start:
mov ax,cs
mov ds,ax
mov si,offset src
mov di,offset dst
mov cx,6
s:
mov dx,cx
mov al,[si]
out 70h,al ; 70h为地址端口
in al,71h ; 71h为数据端口
mov ah,al
mov cl,4
shr ah,cl ; 右移4位,ah为十进制的十位数
and al,00001111b ; al为十进制的个位数
add ah,30h
add al,30h ; 数值转字符形式
xor ah,al
xor al,ah
xor ah,al ; 交换ah al的值
mov [di],ax
add di,3
inc si
mov cx,dx
loop s

mov ax,0b800h
mov es,ax
mov di,0
mov si,offset dst
s1:
mov ch,0
mov cl,[si]
jcxz ok
mov ch,2 ; 绿色字
mov es:[di],cx
inc si
add di,2
jmp s1
ok:
mov ax,4c00h
int 21h
code ends
end start
阅读全文 »

1、编写安装7ch号中断例程,显示0结尾的字符串

中断例程装载程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
; 8086实模式 中断例程装载程序
; 中断号 7ch
; 装载位置 0:200h

assume cs:code
code segment
start:
mov ax,cs
mov ds,ax
mov si,offset handler ; ds:si指向中断例程的代码

mov ax,0
mov es,ax
mov di,200h ; es:di指向中断例程装载位置
mov cx,offset handlerend - offset handler ; 中断例程长度
cld
rep movsb ; 串传输

; 设置 7ch 号中断向量
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

handler:
; 注意!下文中断例程装载程序,只提供 handler 标号的部分,即,
; 中断处理程序开始 与 中断处理程序结束 包裹的部分

; 中断处理程序开始
; 显示0结尾的字符串
; dh 行号、dl 列号、cl 颜色、ds:si指向字符串首
push si
push es
push di
push ax
push dx
push cx

mov ax,0b800h ; 显存开始位置
mov es,ax
mov al,dh
mov dh,160
mul dh ; ax=行号*160
mov dh,0
add dx,dx ; dx=列号*2
add ax,dx
mov di,ax ; di=行号*160+列号*2

s:
mov al,[si]
cmp al,0
je ok
mov ah,cl
mov es:[di],ax
add di,2
inc si
jmp s

ok:
pop cx
pop dx
pop ax
pop di
pop es
pop si
iret
; 中断处理程序结束
handlerend:
nop

code ends
end start
阅读全文 »

可以修改IP,或者同时修改CS与IP的指令统称为转移指令

因为CS:IP是指令寄存器,比较特殊,且CS无法用其他寄存器直接赋值,如:mov cs,ax。

所以需要jmp,call,ret,loop等指令来修改IP或同时修改CS与IP。

CS:IP的组合用来实现8086CPU的20位寻址(虽然8086的寄存器是16位的,但8086内部有20位地址加法器)。

另外,8086CPU是小端模式。内存高地址存放数据高位,内存低地址存放数据低位。

转移指令种类

8086转移指令种类:

  • 无条件转移指令(如 jmp)

  • 条件转移指令(如 jcxz)

  • 循环指令(如 loop)

  • 过程(如 call、ret、retf)

  • 中断

伪指令offset

offset 是伪指令,由汇编器识别并处理,用于取得标号的偏移地址。如:

阅读全文 »

题目

在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串 welcome to masm!

这里的屏幕指的是,显卡文本模式下的屏幕,屏幕尺寸 80x25,可以显示彩色、高亮、闪烁的ASCII字符。

文本模式下一个字符由2个字节组成,即 ASCII+属性 = 2字节。属性字节的格式:

属性字节格式

阅读全文 »