0

まだ 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
4

4 に答える 4

1

まだマルチプロセッシングに対処しようとしていないと仮定すると、特定の IRQ をマスクするように8259 Programmable Interrupt Controllerをプログラムできます。

于 2013-06-30T03:52:20.887 に答える
-1
or al, 00010000b   ; Disable IRQ4 (serial port com1)

前の行はあなたのものほど正しくないか、シリアルポート com1 をマスクしません!!!

and al, 11101111b   
于 2016-10-14T05:48:05.257 に答える