2013-06-29 2 views
0

x86 NASM 어셈블리 OS에서 계속 작업 중입니다.특정 IRQ를 마스크/차단하는 방법

내 마지막 ( CLI and STI are not working)에

후속 조사 질문 : 시스템 타이머 & RTC 시계 자신을 중단한다는 CLI 및 STI 지침이 제대로 오프 인터럽트의 모든 선회했다, 나는 또한 곧 이후에 실현 것을 깨달았다 후

(Wikipedia - IRQ : x86 IRQs : Master PIC 참조). 이것이 시계가 작동하지 않는 이유입니다. 시스템 타이머가 업데이트 될 때까지 기다렸다가 영원히 기다릴 것입니다. 이것은 업데이트에 대한 인터럽트가 해제 되었기 때문에 분명히 발생하지 않았습니다!

불행히도 이것을 알면 내 원 자성 문제가 해결되지 않습니다. 시스템 시계는 인터럽트없이 읽을 수 없습니다. 그러나 인터럽트가 켜져 있으면 원 자성이 보장되지 않습니다.

일부 인터럽트를 마스크하는 방법이 있지만 전부는 아닙니다. 0과 8 외의 모든 인터럽트를 숨기는 방법을 알고 싶습니다. (위키피디아 링크 참조). 이 기능을 Wait_Clk_Ticks 함수에서 구현하고 싶습니다. 이 날을 제공


는 "떨어지는 빗방울"효과가 표시됩니다 부팅 장치 (내 경우에는 플로피 디스크)에로드 코드를 코드 -. 빨간색 2 픽셀 길이의 섹션이 화면 아래로 천천히 이동 한 다음 상단에서 다시 시작합니다. 그것은 그것이하기로되어있는 것입니다.

그러나 (내가 믿는) 시계에 관련된 모두 3 문제가 있습니다 :

키를 누를
  • , 컴퓨터가 불쾌 음이 나고 빗방울 천천히 이동합니다. 나는 pressign 키가 인터럽트를 일으키고 타이머 기능을 지연시키기 때문이라고 생각한다.

  • 타이머에는 원 자성이 없습니다.

  • 잠시 후, 빗방울이 완전히 중지됩니다

가 어떻게 이러한 문제를 해결할 수 있습니다 (아마도이 ​​문제를 일으키는 인터럽트이다)?


편집 : 나는 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 
+2

대체 어디서 플로피 드라이브를 작동 시켰습니까? –

+1

PIC에는 인터럽트 제어 및 마스킹에 사용되는 레지스터가 있어야합니다. 레지스터의 각 비트는 링크를 지정한 Wiki 페이지에 나열된 인터럽트 중 하나에 해당합니다. 인터럽트를 마스크하려면 해당 비트에 '또는'을 입력하십시오. 나는 이것을 위해 PC에서 어떤 레지스터 주소가 사용되는지 조사하지 않았으므로 그러한 세부 사항은 없지만 귀하의 조사에 도움이 될 것입니다. – lurker

+0

@David Jashi ... 플로피 드라이브, 예. 일? 어, 일종의. '플로피 드라이브에 넣을 자리가 있었으니까요. –

답변

1

은 ... 음, 수정은 그 한 줄에 대한 디버깅 5 시간이었다

... 도움을 :) 감사하지만 ... Set_IRQ_Mask 기능 후에 ret을 추가했다 보인다!

-1
or al, 00010000b ; Disable IRQ4 (serial port com1) 

이전 줄이 너만큼 정확하지 않거나 직렬 포트 com1을 마스크하지 않을 것이다 !!!

and al, 11101111b 
0

수행중인 작업에 대해 인터럽트를 전혀 사용하지 않아도됩니다. 당신이 원자 일 필요가 있다고 생각하는 것이 확실하지 않지만 원자 적으로 수행되어야하는 유일한 작업은 메모리의 틱 카운터의 16 비트 읽기입니다. 정렬 된 16 비트 읽기는 원자 단위로 보장되므로 틱 계수기가 적절하게 정렬되므로 인터럽트를 비활성화 할 필요가 없습니다. 보장되지 않는 경우 (예 : 카운터가 홀수 번지에있는 경우) 읽기를 수행하는 명령어에 대한 인터럽트를 비활성화해야합니다. 여기

내가 당신 Wait_Clk_Ticks 기능을 구현하는 것이 방법 : 타이머 카운터가 적절하게 정렬되지 않은 경우 CLI/STI 지침 갈 것 어디 보여준

Wait_Clk_Tics: 
    push ds 
    push ax 
    push bx 

    xor ax, ax 
    mov ds, ax 
    ; cli 
    mov ax, [0x46c] 
    ; sti 
.loop: 
    hlt 
    ; cli 
    mov bx, [0x46c] 
    ; sti 
    sub bx, ax 
    cmp bx, cx 
    jb .loop 

    pop bx 
    pop ax 
    pop ds 
    ret 

. 또한 코드를 단순화하여 카운터 변경 사항을 계산하지 않고 원래 값에서 카운터의 현재 값을 뺍니다. 마지막으로 HLT 명령어를 삽입했습니다. 이렇게하면 CPU가 인터럽트를 기다립니다. 상대적으로 현대적인 CPU에서는 프로세서가 저전력 상태가되기 때문에 CPU 팬에서 발생하는 전력 소비 및 잡음이 눈에 띄게 나타납니다.

관련 문제