王爽--アセンブリ言語課程設計2いくつかの問題記録
全体プログラムは、19番割り込みルーチンを書き換えることによって実現される.19番割り込みルーチンで異なるサブルーチンを呼び出し、異なる機能を実現する.
1.時間を動的に表示するサブルーチン
cmos中の時間情報をループ読み出して動的表示時間を実現する.また、表示中には、F 1キーとescキーの動作も実現される.ただし,16 h番割り込みで対応するキーを取得し,対応する動作を行うことはできない.時間を動的に表示するには、cmosの時間をループして読み込む必要があります.ループに読み取りキーボード入力を入れた16 h割り込みは、キーボード入力バッファが空の場合、16 h割り込みはブロックされ、ダイナミック表示の効果は得られません.したがって,9番割り込み応答キーボード割り込みによりキーボード入力を処理する.9番割り込み処理プログラムを書き換え、F 1とESCキーを押したときの動作を定義します.
このサブルーチンでは、9番割り込みを書き換えるには、ハードウェアに関連する問題を呼び出す必要があるため、元の9番割り込みのエントリアドレスを保存することに注意します.上記表示時間の部分には、予め設定されたbhを用いて表示の色属性値、blを用いて文字のASCIIコードを格納し、bh値を変更すれば時間表示の色を変更することができる.そこで9番割り込みでF 1キーを押したと判断したらbhを直接修正します.9番割り込みがcmosサイクル読み出し時間に戻って表示されるプログラムセグメントに戻ると、bh値が新しくなり、表示の色も変わりました.escキーでは,まずescを押下した後に無限ループ読み出しを飛び出して時間を表示するプログラムセグメントを実現する.どうやって飛び出しますか?9番割り込み中なので、最後にIRETを使って引き返します.返されるアドレスは、割り込み処理がスタックに格納されているCS:IPが指すアドレスである.したがって、スタック内でCS:IPを変更することによって、IRETが所望のアドレスに戻ることを実現することができる.私たちが望むアドレスは,ループ表示時間のプログラムセグメントの下のアドレスshowover(表示終了)である.CS部分はIPを修正するだけで修正する必要はありません.したがって,このサブルーチンにはescジャンプの宛先IPも予め保存しておく.ESCの処理には、元の処理プログラムアドレスを9番で中断する復元も含まれる.サブルーチンの準備が完了します.
2つのバグ:
(1)時間をループ表示する場合,表示する文字と画面上に表示する位置をsiとdiでそれぞれ位置決めする.ループが始まる前に2つの値を初期化しました.loopループでは、この2つの値が変更されます.したがって、次回のリフレッシュ時間には、2つの値を再初期化する必要があります.これにより、同じ位置に表示され、表示内容が正しいことが保証されます.以前はsiとdiの値を表示するたびにスタックを使用して保存し、一度の表示が終了した後、popでsiとdiの初期値を復元し、次回のループ表示を実行していました.ここでの問題は,escキーボードの割り込みが発生した場合,スタックのpushとpop操作がペアで発生することを保証できず,エラーを招くことである.たとえば、表示時間のプログラムセグメントが表示月まで実行されたばかりで、スタックにはsiとdiを初期化するための値が保存されています.ESCを押すと、キーボード割り込みが発生し、フラグレジスタ、CS、IPが保存され、9番キーボード割り込みに入ります.我々が定義したESCキーボード割り込み処理は,割り込みが返されたアドレスを直接修正し,元の保存したアドレスには戻らない.showoverに戻ったとき、問題が発生しました.showoverは主にいくつかのレジスタの復元とサブプログラムの戻りをします.しかし、以前に押し込まれたsiとdiはスタックにあり、必然的にエラーを引き起こす.この問題は、BH値を変更しただけで、割り込み時のアドレスで表示時間を継続するプログラムセグメントを返すため、F 1キーボード割り込みには存在しない.
この中には実はウィンドウの問題があります.ESC割り込みについては,最後のpopが終了して次のループ表示の準備が完了した場合にもプログラムにエラーは発生しない.しかし、この確率はかなり小さく、エラーを起こさないウィンドウは小さすぎます.
(2)新たな9番割り込みは,元の19 H割り込みで発生して処理される.最初に発生した19 h割込みはIFを0にし、すなわち19 h割込み中に他のシールド可能割込みの発生を許さない.ほとんどの割り込みは遮断可能な割り込みであり、9番の割り込みはそのうちの1つである.したがって,9番割り込みを機能させるには,このサイクル表示時間のサブプログラムでIFを1にし,ESCを押した後にshowoverにジャンプしてサブプログラム準備を終了する必要がある.このときIFを0にリセットする.
19 h割り込みハンドラインストールコード:
メインプログラム:
1.時間を動的に表示するサブルーチン
cmos中の時間情報をループ読み出して動的表示時間を実現する.また、表示中には、F 1キーとescキーの動作も実現される.ただし,16 h番割り込みで対応するキーを取得し,対応する動作を行うことはできない.時間を動的に表示するには、cmosの時間をループして読み込む必要があります.ループに読み取りキーボード入力を入れた16 h割り込みは、キーボード入力バッファが空の場合、16 h割り込みはブロックされ、ダイナミック表示の効果は得られません.したがって,9番割り込み応答キーボード割り込みによりキーボード入力を処理する.9番割り込み処理プログラムを書き換え、F 1とESCキーを押したときの動作を定義します.
このサブルーチンでは、9番割り込みを書き換えるには、ハードウェアに関連する問題を呼び出す必要があるため、元の9番割り込みのエントリアドレスを保存することに注意します.上記表示時間の部分には、予め設定されたbhを用いて表示の色属性値、blを用いて文字のASCIIコードを格納し、bh値を変更すれば時間表示の色を変更することができる.そこで9番割り込みでF 1キーを押したと判断したらbhを直接修正します.9番割り込みがcmosサイクル読み出し時間に戻って表示されるプログラムセグメントに戻ると、bh値が新しくなり、表示の色も変わりました.escキーでは,まずescを押下した後に無限ループ読み出しを飛び出して時間を表示するプログラムセグメントを実現する.どうやって飛び出しますか?9番割り込み中なので、最後にIRETを使って引き返します.返されるアドレスは、割り込み処理がスタックに格納されているCS:IPが指すアドレスである.したがって、スタック内でCS:IPを変更することによって、IRETが所望のアドレスに戻ることを実現することができる.私たちが望むアドレスは,ループ表示時間のプログラムセグメントの下のアドレスshowover(表示終了)である.CS部分はIPを修正するだけで修正する必要はありません.したがって,このサブルーチンにはescジャンプの宛先IPも予め保存しておく.ESCの処理には、元の処理プログラムアドレスを9番で中断する復元も含まれる.サブルーチンの準備が完了します.
2つのバグ:
(1)時間をループ表示する場合,表示する文字と画面上に表示する位置をsiとdiでそれぞれ位置決めする.ループが始まる前に2つの値を初期化しました.loopループでは、この2つの値が変更されます.したがって、次回のリフレッシュ時間には、2つの値を再初期化する必要があります.これにより、同じ位置に表示され、表示内容が正しいことが保証されます.以前はsiとdiの値を表示するたびにスタックを使用して保存し、一度の表示が終了した後、popでsiとdiの初期値を復元し、次回のループ表示を実行していました.ここでの問題は,escキーボードの割り込みが発生した場合,スタックのpushとpop操作がペアで発生することを保証できず,エラーを招くことである.たとえば、表示時間のプログラムセグメントが表示月まで実行されたばかりで、スタックにはsiとdiを初期化するための値が保存されています.ESCを押すと、キーボード割り込みが発生し、フラグレジスタ、CS、IPが保存され、9番キーボード割り込みに入ります.我々が定義したESCキーボード割り込み処理は,割り込みが返されたアドレスを直接修正し,元の保存したアドレスには戻らない.showoverに戻ったとき、問題が発生しました.showoverは主にいくつかのレジスタの復元とサブプログラムの戻りをします.しかし、以前に押し込まれたsiとdiはスタックにあり、必然的にエラーを引き起こす.この問題は、BH値を変更しただけで、割り込み時のアドレスで表示時間を継続するプログラムセグメントを返すため、F 1キーボード割り込みには存在しない.
この中には実はウィンドウの問題があります.ESC割り込みについては,最後のpopが終了して次のループ表示の準備が完了した場合にもプログラムにエラーは発生しない.しかし、この確率はかなり小さく、エラーを起こさないウィンドウは小さすぎます.
(2)新たな9番割り込みは,元の19 H割り込みで発生して処理される.最初に発生した19 h割込みはIFを0にし、すなわち19 h割込み中に他のシールド可能割込みの発生を許さない.ほとんどの割り込みは遮断可能な割り込みであり、9番の割り込みはそのうちの1つである.したがって,9番割り込みを機能させるには,このサイクル表示時間のサブプログラムでIFを1にし,ESCを押した後にshowoverにジャンプしてサブプログラム準備を終了する必要がある.このときIFを0にリセットする.
19 h割り込みハンドラインストールコード:
assume cs:code
code segment
start:mov ax,0
mov es,ax
mov di,200h
mov ax,cs
mov ds,ax
mov si,offset int19
mov cx,offset int19_e - offset int19
mov ax,offset rst - offset int19
add ax,200h
mov [si+2],ax
mov ax,offset stt - offset int19
add ax,200h
mov [si+4],ax
mov ax,offset showt - offset int19
add ax,200h
mov [si+6],ax
mov ax,offset sett - offset int19
add ax,200h
mov [si+8],ax
cld
rep movsb
cli
mov word ptr es:[19h*4],200h
mov word ptr es:[19h*4+2],0
sti
mov ax,4c00h
int 21h
int19:jmp short s
dw 0,0,0,0 ;
dw 0,0ffffh ;
dw 7c00h,0 ;
s:push bx
push ds
mov bl,ah
mov bh,0
add bx,bx
mov ax,cs
mov ds,ax
call word ptr [bx+202h]
pop ds
pop bx
iret
rst:jmp dword ptr ds:[20ah]
ret
stt:mov ax,0
mov es,ax
mov bx,7c00h
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,80h
mov ah,2
int 13h
jmp dword ptr ds:[20eh]
ret
showt:jmp short showst
db 9,8,7,4,2,0
db '// ::',0
dw 0,0 ; 9
dw 0 ;esc ,
showst:push ax ; F1 esc ,
push bx ; 9 。
push cx
push si
push di
push ds
push es
mov ax,cs ;cs=0
mov ds,ax ;ds=0
mov ax,0b800h
mov es,ax
mov bh,42h
mov di,720h
mov si,offset showt- offset int19
add si,202h
mov ax,si
add ax,12
mov bp,ax ;bp 9
push ds:[36] ; 9
pop ds:[bp]
push ds:[38]
pop ds:[bp+2]
push cs ; 9
pop ds:[38]
mov ax,offset int9 - offset int19
add ax,200h
mov ds:[36],ax
mov ax,offset showover - offset int19
add ax,200h
mov ds:[bp+4],ax ; esc
pushf ; IF , 19h ,if=0,
pop ax
or ax,0200h
push ax
popf
refresht:mov si,bp ; , F1 , , 。
sub si,12
mov di,720h ; esc 。 iret IP
mov cx,6 ; , push si push di
lpt:mov al,[si] ; esc , showover 。 si di
out 70h,al ; , 。 , int19
in al,71h ; , push pop 。 : si di。
push ax
push cx
mov cl,4
shr al,cl
pop cx
add al,30h
mov bl,al
mov es:[di],bx
pop ax
and al,0fh
add al,30h
mov bl,al
mov es:[di+2],bx
mov bl,[si+6]
mov es:[di+4],bx
inc si
add di,6
loop lpt
jmp short refresht
showover:pushf ; , IF
pop ax
and ax,0fdffh
push ax
popf
pop es
pop ds
pop di
pop si
pop cx
pop bx
pop ax
ret
int9:push ax
push bp
in al,60h
pushf
call dword ptr ds:[bp]
cmp al,3bh ;F1
je sf1
cmp al,1 ;esc
je sesc
jmp short int9ok
sf1:inc bh
jmp short int9ok
sesc:push ds:[bp]
push ds:[bp+2]
pop ds:[38]
pop ds:[36]
mov ax,ds:[bp+4]
mov bp,sp
mov [bp+4],ax
int9ok:pop bp
pop ax
iret
sett:ret
int19_e:nop
code ends
end start
メインプログラム:
assume cs:code,ds:data,ss:stack
data segment
table dw hint,reset,boot,clock,set_c
hint db 'pls select the program you want to run','$'
reset db 'reset pc ------- 0','$'
boot db 'start system ----1','$'
clock db 'clock -----------2','$'
set_c db 'set clock -------3','$'
data ends
stack segment
dw 64 dup (0)
stack ends
code segment
start:mov ax,stack
mov ss,ax
mov sp,128
mov ax,data
mov ds,ax
mov ax,0b800h
mov es,ax
mov bh,0
mov dh,6
mov dl,16
mov cx,5
mov bp,0
s:push dx
mov ah,2 ;
int 10h
mov dx,table[bp] ;
mov ah,9
int 21h
pop dx
inc dh
add bp,2
loop s
mov ah,2
int 10h ; ,
push dx ; dx, ,
mov al,160
mul dh
mov dh,0
add dx,dx
add ax,dx
mov di,ax
pop dx
getch:mov ah,0
int 16h
cmp ah,0bh
je rst
cmp ah,2
je stt
cmp ah,3
je showt
cmp ah,4
je sett
jmp short getch
rst:mov ah,0
jmp short ok
stt:mov ah,1
jmp short ok
showt:mov ah,2
jmp short ok
sett:mov ah,3
ok:push ax
mov ah,42h
mov es:[di],ax
e_b:mov ah,0
int 16h
cmp ah,1ch ;
je int19
cmp ah,0eh ;
jne short e_b
mov ah,2
int 10h
mov al,0
mov ah,01110111b
mov es:[di],ax
pop ax
jmp short getch
int19:pop ax
int 19h
mov ax,4c00h
int 21h
code ends
end start