まだ x86 NASM アセンブリ OS に取り組んでいます。
最後の質問へのフォローアップの質問 ( CLI と STI が機能していません):
CLI と STI 命令がすべての割り込みを正しくオフにしていることに気付いた後、すぐにシステム タイマーと RTC クロックが割り込み自体であることにも気付きました ( Wikipedia - IRQ : x86 IRQ : Master PICを参照)。これが、時計が機能しない理由でした。システム タイマーが更新されるまで、時計は永遠に待機し続けました。更新の割り込みがオフになっているため、これは明らかに発生しませんでした。
残念ながら、これを知っていてもアトミック性の問題は解決しません。割り込みをオンにしないと、システム クロックを読み取ることができません。ただし、割り込みをオンにしても原子性は保証されません。
一部の割り込みをマスクする方法があると聞きましたが、すべてではありません。0 と 8 以外のすべての割り込みをマスクする方法を知りたいです (ウィキペディアのリンクを参照)。Wait_Clk_Ticks
これを関数に実装したいと思います。
このコードにたどり着きました。このコードは、ブート デバイス (私の場合はフロッピー ディスク) にロードされると、「雨滴が落ちる」効果を表示します。赤い 2 ピクセルの長さのセクションが画面をゆっくりと下に移動し、上部から再開します。これは、それがすべきことです。
ただし、3 つの問題があり、そのすべてがクロックに関連しています (私は信じています)。
キーが押されると、コンピューターは不快なビープ音を鳴らし、雨滴がゆっくりと落ちていきます。キーを押すと割り込みが発生し、タイマー機能が遅れているためだと思います。
タイマーには原子性はありません。
しばらくすると、雨滴は完全に止みます (おそらく、これは問題を引き起こしている中断です)。
これらの問題を解決するにはどうすればよいですか?
編集: Set_IRQ_Mask 関数を追加しました。しかし、私のOSは起動時にハングします。
編集 2:修正、回答を参照してください。
[BITS 16] ; 16 bit code
[ORG 0x7C00] ; Start to load at 0x7c00
; OS to create 'falling raindrop' effect
jmp Code_Start
Set_IRQ_Mask: ; see http://wiki.osdev.org/8259_PIC and http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH17/CH17-3.html
in al, 21h ; Read existing bits.
or al, 00010000b ; Disable IRQ4 (serial port com1)
out 21h, al
mov al, 0x20 ; Send end of interrupt signal
out 0x20, al
ret
Wait_Clk_Ticks:
; MASK CERTAIN INTERRUPTS
push ax ; Store current values.
push bx
mov ax, 0 ; Reset 'ds' (destination pointer).
mov ds, ax
mov bx, [46Ch] ; Tick status is at 0:46Ch.
; Store into 'bx'.
_WCT_Get_Tick: ; Gets new tick.
mov ax, [46Ch] ; Update current time into 'ax'.
cmp ax, bx ; If 'current' == 'older' ticks,
je _WCT_Get_Tick
; Then clock tick isn't over: reset.
mov bx, ax ; If the clock tick is over,
; put 'current' into 'older'.
sub cx, 1 ; Decrement number of ticks till exit.
jnz _WCT_Get_Tick;
; If 'cx' (ticks till exit) is zero,
pop bx ; Restore current values.
pop ax
; UNMASK CERTAIN INTERRUPTS
ret ; Return.
Set_Video_Mode:
mov ax, 13h ; VGA mode (320x200) 256 color
int 10h ; sets vga mode SEE: http://www.wagemakers.be/english/doc/vga
ret
Write_Pixel:
push ax ; push variables used here onto the stack
push bx
push cx
mov cx, 320 ; puts 320 (how many rows there are) into a register
mul cx ; multiplies 320 by AX (# of rows) and stores into AX
add ax, bx ; adds rows and cols to make the location, puts into ax
mov si, ax ; move ax into si
mov bx, 0a000h ; this puts 0a000h (starting register) as the beginning
mov es, bx ; move bx into es
pop cx
mov word [es:si], cx ; move the color attribute (cx) into the memory location es+si
pop bx ; restore variables from stack
pop ax
ret
Code_Start:
mov bx, 40 ; work on COLUMN 40 solely
call Set_Video_Mode
call Set_IRQ_Mask
Reset:
mov ax, 0 ; Reset row to 0
Loop:
mov cx, 40 ; Write head in in RED (40)
call Write_Pixel
cmp ax, 0 ; Are we at row 1?
je Next_Zero ; Go to special conditions
cmp ax, 1 ; Are we at row 2?
je Next_One ; Go to special conditions
jmp Next_Norm ; Otherwise, no special conditions
Next_Zero: ; Make the cover spot 197 if the current dot is 0
push ax
mov ax, 197
jmp Cover_Black
Next_One: ; Make the cover spot 198 if the current dot is 1
push ax
mov ax, 198
jmp Cover_Black
Next_Norm: ; Otherwise, make the cover spot 'ax - 2'
push ax
sub ax, 2
Cover_Black: ; Set color to black
mov cx, 0
call Write_Pixel
pop ax ; Restore AX to the RED location.
mov cx, 1 ; Set to wait for a clock tick
call Wait_Clk_Ticks
inc ax ; Increment the row
cmp ax, 199 ; If pixel has reached the bottom of the screen, reset AX
je Reset
jmp Loop ; Otherwise, continue downwards.
End:
jmp $ ; Run this line over and over again- stops excecution.
times 510-($-$$) db 0 ; Fill the rest of the 512 byte sector with zeros
dw 0xAA55 ; Boot magic number