调用9号中断和调用16号中断的一些问题

qnapjiujiu 2015-01-13 11:18:14
assume cs:code 
stack segment
dw 100 dup(0)
stack ends
code segment;主程序的功能为把shanqu1的程序(标号内的程序)写入软盘的扇区1
;把shanqu2的程序(单独一个段)写入软盘的扇区2开始的区域
start:

mov ax, stack
mov ss,ax
mov sp,100

mov ax,code
mov es,ax
mov bx,offset shanqu1;把shanqu1的程序写入软盘的扇区1

mov al,1;写入1个扇区
mov ch,0
mov cl,1
mov dl,0
mov dh,0
mov ah,3
int 13h

mov ax,shanqu2;把shanqu2的程序写入软盘的扇区2开始的区域
mov es,ax
mov bx,0

mov al,15;写入15个扇区
mov ch,0
mov cl,2
mov dl,0
mov dh,0
mov ah,3
int 13h
mov ax,4c00h
int 21h
shanqu1:;写入扇区1
mov ax,2000h
mov es,ax
mov bx,0

mov al,15
mov ch,0
mov cl,2
mov dl,0
mov dh,0
mov ah,2
int 13h

mov ax,0
mov [bx],ax
mov word ptr [bx+2],2000h
jmp dword ptr [bx]
shanqu1end:nop

code ends;主程序结束


shanqu2 segment;写入扇区2开始的区域
org 20000h
assume cs:shanqu2
call clean
jmp start1
str1 db 'welcome',0
str2 db '1) reset pc',0
str3 db '2) start system',0
str4 db '3) clock',0
str5 db '4) set clock',0
str6 db 'Please input time like "yy/mm/dd hh:mm:ss.',0
str7 db 'Set clock successful! Press enter key to return...',0
stack1 dw 128 dup(0)
start1:
mov ax,cs
mov ss,ax
mov sp,offset stack1 +127
mov ax,cs
mov ds,ax

mov dh,1; ;显示主菜单-开始
mov dl,1;
mov cl,02h
mov bx,offset str1
call show_str;

mov dh,12;
mov dl,15
mov cl,2h
mov bx,offset str2
call show_str

mov dh,14
mov dl,15
mov cl,2h
mov bx,offset str3
call show_str

mov dh,16;
mov dl,15;
mov cl,2h
mov bx,offset str4
call show_str;
mov dh,18;
mov dl,15
mov cl,2h
mov bx,offset str5
call show_str ;显示主菜单-结束
shuru: mov ah,0 ;选择菜单:
int 16h
mov al,ah
cmp al,5;
ja shuru
cmp al,2;扫描到的按键值大于5或小于2(输入1~4以外的字符)都需要重新输入
jb shuru
jmp short set1
table0 db 0,1,2,3;对应0,1,2,3
table1 db 2,3,4,5;1,2,3,4的案件通码
set1:push bx
mov bx,0
s9:cmp al,table1[bx]
je s8
inc bx
jmp s9
s8:
mov al,table0[bx]
pop bx
mov ah,al
mov al,2
jmp set
table dw sys_restart,sys_start,sys_showclock,sys_setclock
set:push bx
mov bl,ah
mov bh,0
add bx,bx;选择程序

call word ptr table[bx]
jmp quit
;下面为4个子程序
sys_restart:;重新启动
mov ax,0
mov [bx],ax
mov word ptr [bx+2],0ffffh
jmp dword ptr [bx]
ret

sys_start:;正常启动计算机
call clean
mov ax,0h
mov es,ax
mov bx,7c00h

mov al,2
mov ch,0
mov cl,1
mov dl,80h
mov dh,0
mov ah,2
int 13h

mov ax,7c00h
mov [bx],ax
mov word ptr [bx+2],0
jmp dword ptr [bx]

ret

sys_showclock:;显示时钟
call clean
mov dl,2
push cs
pop ds

mov ax,0
mov es,ax

mov si,offset int9
mov di,204h
mov cx,offset int9end-offset int9
cld
rep movsb

push es:[9*4]
pop es:[200h]
push es:[9*4+2]
pop es:[202h]

cli
mov word ptr es:[9*4],204h
mov word ptr es:[9*4+2],0
sti
jmp ssc

int9:
push ax
push bx
push cx
push es
in al,60h

pushf
call dword ptr cs:[200h]

cmp al,3bh
jne nf1
dec dl

nf1:
cmp al,1h
jne int9ret

push es:[8000h];当这个中断不需要时,恢复原来的中断程序
pop es:[9*4];不过有没有这个,对于本程序都没有影响
push es:[8002h]
pop es:[9*4+2]

pop es
pop cx
pop bx
pop ax


mov ax,2000h
push ax
mov ax,0h
push ax
retf


int9ret:
pop es
pop cx
pop bx
pop ax
iret
int9end:nop
fh db '// ::';用到的符号
ssc: ;读取时钟,显示到屏幕上
mov al,9
out 70h,al
in al,71h

mov bl,al
mov cl,4
and bl,00001111b
shr al,cl

add al,30h
add bl,30h

mov es:[si+4],al
mov byte ptr es:[si+5],dl
mov es:[si+6],bl
mov byte ptr es:[si+7],dl

mov al,fh[0]
mov es:[si+10],al
mov byte ptr es:[si+11],dl

mov al,8
out 70h,al
in al,71h
mov bl,al
mov cl,4
and bl,00001111b
shr al,cl
add al,30h
add bl,30h

push dx
mov dx,0b800h
mov es,dx
pop dx
mov si,160*2
mov es:[si+16],al
mov byte ptr es:[si+17],dl
mov es:[si+18],bl
mov byte ptr es:[si+19],dl

mov al,fh[1]
mov es:[si+22],al
mov byte ptr es:[si+23],dl

mov al,7
out 70h,al
in al,71h
mov bl,al
mov cl,4
and bl,00001111b
shr al,cl
add al,30h
add bl,30h

push dx
mov dx,0b800h
mov es,dx
pop dx
mov si,160*2
mov es:[si+28],al
mov byte ptr es:[si+29],dl
mov es:[si+30],bl
mov byte ptr es:[si+31],dl
mov al,fh[2]
mov es:[si+34],al
mov byte ptr es:[si+35],dl

mov al,4
out 70h,al
in al,71h
mov bl,al
mov cl,4
and bl,00001111b
shr al,cl
add al,30h
add bl,30h

push dx
mov dx,0b800h
mov es,dx
pop dx
mov si,160*2
mov es:[si+40],al
mov byte ptr es:[si+41],dl
mov es:[si+42],bl
mov byte ptr es:[si+43],dl

mov al,fh[3]
mov es:[si+46],al
mov byte ptr es:[si+47],dl

mov al,2
out 70h,al
in al,71h
mov bl,al
mov cl,4
and bl,00001111b
shr al,cl
add al,30h
add bl,30h

push dx
mov dx,0b800h
mov es,dx
pop dx
mov si,160*2
mov es:[si+52],al
mov byte ptr es:[si+53],dl
mov es:[si+54],bl
mov byte ptr es:[si+55],dl

mov al,fh[4]
mov es:[si+58],al
mov byte ptr es:[si+59],dl

mov al,0
out 70h,al
in al,71h
mov bl,al
mov cl,4
and bl,00001111b
shr al,cl
add al,30h
add bl,30h

push dx
mov dx,0b800h
mov es,dx
pop dx
mov si,160*2
mov es:[si+64],al
mov byte ptr es:[si+65],dl
mov es:[si+66],bl
mov byte ptr es:[si+67],dl

jmp ssc
ret

sys_setclock:;设置时钟
call clean
mov dh,4;显示的行号
mov dl,13;显示的列号
mov cl,2h
mov bx,offset str6
call show_str;调用显示字符串函数
startsc:jmp getstr
string dw 50 dup(0);盛放输入的字符串
getstr: mov ax,string
mov ds,ax
mov si,offset string
push ax
getstrs:mov ah,0
int 16h
cmp al,20h
jb nochar
mov ah,0
call charstack
mov ah,2
call charstack
jmp getstrs
nochar: cmp ah,0eh
je backspace
cmp ah,1ch
je enter1
jmp getstrs
backspace:mov ah,1
call charstack
mov ah,2
call charstack
jmp getstrs
enter1: mov al,0;按enter键结束字符的输入
mov ah,0
call charstack
mov al,[si][0];把字符串解析后写入记录时钟的cmos ram中
mov bl,[si][1]
sub al,30h
sub bl,30h
mov cl,4
shl al,cl
and al,11110000b
and bl,00001111b
add al,bl
mov bl,al
mov al,9
out 70h,al
mov al,bl
out 71h,al

mov al,[si][3];把字符串解析后写入记录时钟的cmos ram中
mov bl,[si][4]
sub al,30h
sub bl,30h
mov cl,4
shl al,cl
and al,11110000b
and bl,00001111b
add al,bl
mov bl,al
mov al,8
out 70h,al
mov al,bl
out 71h,al

mov al,[si][6];把字符串解析后写入记录时钟的cmos ram中
mov bl,[si][7]
sub al,30h
sub bl,30h
mov cl,4
shl al,cl
and al,11110000b
and bl,00001111b
add al,bl
mov bl,al
mov al,7
out 70h,al
mov al,bl
out 71h,al

mov al,[si][9];把字符串解析后写入记录时钟的cmos ram中
mov bl,[si][10]
sub al,30h
sub bl,30h
mov cl,4
shl al,cl
and al,11110000b
and bl,00001111b
add al,bl
mov bl,al
mov al,4
out 70h,al
mov al,bl
out 71h,al

mov al,[si][12];把字符串解析后写入记录时钟的cmos ram中
mov bl,[si][13]
sub al,30h
sub bl,30h
mov cl,4
shl al,cl
and al,11110000b
and bl,00001111b
add al,bl
mov bl,al
mov al,2
out 70h,al
mov al,bl
out 71h,al

mov al,[si][15];把字符串解析后写入记录时钟的cmos ram中
mov bl,[si][16]
sub al,30h
sub bl,30h
mov cl,4
shl al,cl
and al,11110000b
and bl,00001111b
add al,bl
mov bl,al
mov al,0
out 70h,al
mov al,bl
out 71h,al

mov dh,6;显示的行号
mov dl,13;显示的列号
mov cl,2h
mov bx,offset str7
call show_str;调用显示字符串函数

shuru1: mov ah,0
int 16h
cmp ah,1ch;
jne shuru1;按enter键返回主程序

mov top,0
pop ax
mov ax,2000h;返回主程序
push ax
mov ax,0h
push ax
retf ;根据地址转移cpu执行位置

ret

charstack:jmp short charstart;处理输入、输出、显示的子程序

tablesr dw charpush,charpop,charshow
top dw 0

charstart:push bx
push dx
push di
push es

mov bx,cs
mov ds,bx
mov si,offset string
cmp ah,2
ja sret
mov bl,ah
mov bh,0
add bx,bx
mov dh,4
mov dl,12
jmp word ptr tablesr[bx]
charpush:mov bx,top
mov [si][bx],al
inc top
jmp sret
charpop:cmp top,0
je sret
dec top
mov bx,top
mov al,[si][bx]
jmp sret
charshow:mov bx,0b800h
mov es,bx
mov al,160
mov ah,0
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx

mov bx,0
charshows:cmp bx,top
jne noempty
mov byte ptr es:[di],' '
jmp sret
noempty:mov al,[si][bx]
mov es:[di],al
mov byte ptr es:[di+2],' '
inc bx
add di,2
jmp charshows
sret:pop es
pop di
pop dx
pop bx
ret

clean:;清屏的子程序
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
;显示字符串函数\/
show_str:
push ax
push bx
push cx
push dx
push es
push si
push cx
mov al,160
dec dh
mul dh
push ax
mov al,2
dec dl
mul dl
pop si
add si,ax
mov ax,0b800h
mov es,ax
pop dx

mov ch,0
;pop si

s: mov cl,ds:[bx]
jcxz ok
mov al,ds:[bx]
mov es:[si],al
mov es:[si+1],dl
inc bx
add si,2
jmp short s

ok:
pop si
pop es
pop dx
pop cx
pop bx
pop ax
ret
;显示字符串函数^
quit:
mov ax,4c00h
int 21h
shanqu2 ends
end start

该程序的功能如下:
1、列出功能选项,让用户通过键盘进行选择,界面如下:
(1)reset pc ;重新启动计算机
(2)start system ;引导现有的操作系统
(3)clock ;进入时钟程序
(4)set clock ;设置时间
2、用户输入“1”后重新启动计算机
3、用户输入“2”后引导现有的操作系统
4、用户输入“3”后,执行动态显示当前日期、时间的程序。
当按下F1键后,改变显示颜色;按下Esc键后,返回到主菜单
5、用户输入“4”后可更改当前的日期、时间,更改后返回主菜单

问题1:这个程序中clock子程序中“变色”和“返回主菜单”功能是用更改9号中断程序实现的。问题是:当从clock项中返回主菜单后,再次进入clock项后F1和Esc按键都不管用且会阻止时间的刷新。这个是什么问题导致的?

问题2:重新写clock的子程序,“变色”和“返回主菜单”功能由调用16号中断的1号功能实现。问题是:当进入clock项中变色超过15次(按键15次)后会出问题:时间不再刷新,继续按键的话会出现功能紊乱等问题。这个是什么问题导致的?
程序代码在楼下:
...全文
574 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
fcqm8888 2015-06-27
  • 打赏
  • 举报
回复
调用问题解决了没有啊?
fcqm8888 2015-04-24
  • 打赏
  • 举报
回复
问题最后解决了没有?
qnapjiujiu 2015-01-22
  • 打赏
  • 举报
回复
改写clock子程序后的代码:
qnapjiujiu 2015-01-17
  • 打赏
  • 举报
回复
引用 20 楼 zara 的回复:
不可能啊,我修改了下恢复部分和主菜单处的读键部分,正常的;若是花屏的话,也是上面提及的没有先设置好 es 和 si 的缘故。 若确实总不能再进其它功能,还是int9 恢复错误,仔细看看自己的恢复代码,es 要先设置到 0000 因为显示部分改写到 0B800h 了吧。
谢谢zara老大,问题解决了,我感觉还是自己解决问题的思路比较欠缺,再次感谢您的多次帮助
zara 2015-01-16
  • 打赏
  • 举报
回复
还是说你上面的那个程序吧,按键的问题,我拿 7/8# 的代码,重写了按键处理部分,没有你所说的故障;乱码的问题,应该是没有设置好 es 和 si 就在 wan: 后面使用了,可能因此改写了 start1: 后面的部分内容导致错误代码造成的。
qnapjiujiu 2015-01-16
  • 打赏
  • 举报
回复
引用 11 楼 zara 的回复:
抱歉啊那是我胡说八道了,我最多也只是个爱好者罢了,很久以前有些兴趣和时间就自己看了点儿,终究也是没有进入这个行当,所以言论只是个人拙见,姑妄听之而已。
zara老大,您帮助了我很多,我把您当作老师一般,您就在指点一下吧
qnapjiujiu 2015-01-16
  • 打赏
  • 举报
回复
引用 20 楼 zara 的回复:
不可能啊,我修改了下恢复部分和主菜单处的读键部分,正常的;若是花屏的话,也是上面提及的没有先设置好 es 和 si 的缘故。 若确实总不能再进其它功能,还是int9 恢复错误,仔细看看自己的恢复代码,es 要先设置到 0000 因为显示部分改写到 0B800h 了吧。
好,我在研究一下,谢谢zara老大
zara 2015-01-16
  • 打赏
  • 举报
回复
不可能啊,我修改了下恢复部分和主菜单处的读键部分,正常的;若是花屏的话,也是上面提及的没有先设置好 es 和 si 的缘故。
若确实总不能再进其它功能,还是int9 恢复错误,仔细看看自己的恢复代码,es 要先设置到 0000 因为显示部分改写到 0B800h 了吧。
qnapjiujiu 2015-01-16
  • 打赏
  • 举报
回复
引用 18 楼 zara 的回复:
这个问题,#5 不是已经提过了的吗,int9 中断的恢复是错误的,“保存int9 在 0:200h,恢复时怎么是从 es:8000h?”
已经改了,还是同样的问题
zara 2015-01-16
  • 打赏
  • 举报
回复
这个问题,#5 不是已经提过了的吗,int9 中断的恢复是错误的,“保存int9 在 0:200h,恢复时怎么是从 es:8000h?”
qnapjiujiu 2015-01-16
  • 打赏
  • 举报
回复
引用 16 楼 zara 的回复:
应该还是方法不对吧。我看你的代码,实在有些晕,就清了重写的:
; 主菜单部分的
            call show_str             
qing1:
		mov ah,1
		int 16h			
pan1:
	jz	shuru
	mov	ah, 0
	int	16h
	jmp	qing1

shuru:    mov ah,0    ;选择菜单:
        int 16h   
	cmp	al, '1'
	jb	qing1
	cmp	al, '4'
	ja	qing1
	sub	al, '1'
	shl	al, 1
	mov	bh, 0
	mov	bl, al
	call word ptr table[bx]
	jmp	start1
; ......

; 显示时钟部分的
sys_showclock:;显示时钟
        call clean
        mov dl,2   
    ssc:
        mov ah,1
        int 16h   
	jz	wan
	mov	ah, 0
	int	16h
	cmp	ah, 1
	jne	isF1?
isEsc:
	ret

    fh db '// ::';用到的符号

isF1?:
	cmp ah,3bh
        jne ssc
        add dl,1
wan:
zara老大,您说的这个是调用int 16h实现返回的程序,这个已经解决了。我说的是1#的程序:程序中“变色”和“返回主菜单”功能是用更改9号中断程序实现的,当从clock项中返回主菜单后,再次进入clock项后F1和Esc按键都不管用且会阻止时间的刷新。您看看这是什么问题啊?辛苦您了
zara 2015-01-16
  • 打赏
  • 举报
回复
应该还是方法不对吧。我看你的代码,实在有些晕,就清了重写的:
; 主菜单部分的
call show_str
qing1:
mov ah,1
int 16h
pan1:
jz shuru
mov ah, 0
int 16h
jmp qing1

shuru: mov ah,0 ;选择菜单:
int 16h
cmp al, '1'
jb qing1
cmp al, '4'
ja qing1
sub al, '1'
shl al, 1
mov bh, 0
mov bl, al
call word ptr table[bx]
jmp start1
; ......

; 显示时钟部分的
sys_showclock:;显示时钟
call clean
mov dl,2
ssc:
mov ah,1
int 16h
jz wan
mov ah, 0
int 16h
cmp ah, 1
jne isF1?
isEsc:
ret

fh db '// ::';用到的符号

isF1?:
cmp ah,3bh
jne ssc
add dl,1
wan:
qnapjiujiu 2015-01-16
  • 打赏
  • 举报
回复
引用 14 楼 zara 的回复:
还是说你上面的那个程序吧,按键的问题,我拿 7/8# 的代码,重写了按键处理部分,没有你所说的故障;乱码的问题,应该是没有设置好 es 和 si 就在 wan: 后面使用了,可能因此改写了 start1: 后面的部分内容导致错误代码造成的。
谢谢zara老大,问题2解决了。1#的问题1应该不是按键缓冲区的问题,因为我把可能存在缓冲区问题的地方都加了清空缓存的代码,还是那个问题,第二次进入选项3时按什么键都不管用,还会阻止时间的刷新,您受累帮忙看一下吧
zara 2015-01-15
  • 打赏
  • 举报
回复
抱歉啊那是我胡说八道了,我最多也只是个爱好者罢了,很久以前有些兴趣和时间就自己看了点儿,终究也是没有进入这个行当,所以言论只是个人拙见,姑妄听之而已。
qnapjiujiu 2015-01-15
  • 打赏
  • 举报
回复
引用 9 楼 zara 的回复:
看了几行,就不想看下去了。 我觉得可能还是写些简单的、普通的程序更合适;如果是要实现这样的功能,也是以普通程序的形式为首选。 你这个代码,无论是实现的细节上(如条件判定标记位是使用)还是程序大的执行流程上(如时钟里Esc后用 call start1),都有不妥;大概是初入汇编或是自学的吧。所以,简单普通的程序来形成个比较好的基础和程序习惯还是比较重要的。 你这样的写入到软盘扇区的方式,完全违背了软盘文件系统的格式规范,如果是真写在软盘上的话,应该是不会被引导的(因为连可引导标记都没有),虚拟机上倒是生冷不忌,反倒形成了错误的印象。
我是利用下班时间自己看书学习的,学了大概两个月了,磕磕绊绊的学完了王爽汇编,这两个月感觉很充实,今天看了zara老大的评论备受打击啊,不过做程序员就要做打不死的小强,请zara老大指导一下以现在我的状态应该怎么做?学习那本书或者视频?我就是想通过汇编了解些底层的东西
zara 2015-01-15
  • 打赏
  • 举报
回复
看了几行,就不想看下去了。
我觉得可能还是写些简单的、普通的程序更合适;如果是要实现这样的功能,也是以普通程序的形式为首选。
你这个代码,无论是实现的细节上(如条件判定标记位是使用)还是程序大的执行流程上(如时钟里Esc后用 call start1),都有不妥;大概是初入汇编或是自学的吧。所以,简单普通的程序来形成个比较好的基础和程序习惯还是比较重要的。
你这样的写入到软盘扇区的方式,完全违背了软盘文件系统的格式规范,如果是真写在软盘上的话,应该是不会被引导的(因为连可引导标记都没有),虚拟机上倒是生冷不忌,反倒形成了错误的印象。
qnapjiujiu 2015-01-15
  • 打赏
  • 举报
回复
引用 11 楼 zara 的回复:
抱歉啊那是我胡说八道了,我最多也只是个爱好者罢了,很久以前有些兴趣和时间就自己看了点儿,终究也是没有进入这个行当,所以言论只是个人拙见,姑妄听之而已。
不用在意的,您帮助了我很多,应该感谢您的帮助,我是真心想请教一下,我现在应该学些什么东西?请zara老大不吝赐教
zara 2015-01-14
  • 打赏
  • 举报
回复
这不还就是没有清键盘缓冲区的缘故吗,前面那个帖子不也是你发的么?
用 int9 的那个,你的循环方式有些怪。保存int9 在 0:200h,恢复时怎么是从 es:8000h?这个方式,如果循环时按键有错误,首先试试在主循环读取按键前,先用 int16h 清空键盘缓冲区,即先用 01h 功能查是否有按键,有则用 00h 功能读取,一直到没有按键为止,然后等待功能选择的按键。
用 int16h 的,类似吧;看到有按键,就读取,是适当的功能选择就进行处理,不是也就丢弃了。
qnapjiujiu 2015-01-14
  • 打赏
  • 举报
回复
引用 3 楼 zara 的回复:
这两个问题以前个帖子好像有类似的?
大神,还能找出来吗?着两个问题困扰了一周了
zara 2015-01-14
  • 打赏
  • 举报
回复
这两个问题以前个帖子好像有类似的?
加载更多回复(5)

21,459

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧