2016-12-06 1 views
3

내 부트 로더의 두 번째 단계에서 가상 플로피 디스크의 일부 섹터를 bochs의 메모리에로드하려고 시도하지만 int 0x13을 호출하면 루틴이 돌아 오지 않는다. 플로피 읽기 (AH = 0x2, int 0x13)가 완료되지 않습니다

나는 나의 두 번째 단계에서 관련 코드가 생각 : 모든 코드 내 Github repository에서 찾을 수 있습니다

bootsys_start: 
    mov %cs, %ax 
    mov %ax, %ds 

    /* 
    * Remap IRQs. Interrupts have been disabled in the 
    * bootloader already. 
    */ 

    mov i8259A_ICW1($i8259A_IC4), %al 
    out %al, i8259A_ICW1_ADDR($i8259A_MASTER) 
    out %al, i8259A_ICW1_ADDR($i8259A_SLAVE) 

    mov i8259A_ICW2($USER_INT_START), %al 
    out %al, i8259A_ICW2_ADDR($i8259A_MASTER) 
    mov i8259A_ICW2($USER_INT_START + 8), %al 
    out %al, i8259A_ICW2_ADDR($i8259A_SLAVE) 

    mov i8259A_ICW3($0x4), %al 
    out %al, i8259A_ICW3_ADDR($i8259A_MASTER) 
    mov i8259A_ICW3($0x2), %al 
    out %al, i8259A_ICW3_ADDR($i8259A_SLAVE) 

    mov i8259A_ICW4($i8259A_uPM & i8259A_x86), %al 
    out %al, i8259A_ICW4_ADDR($i8259A_MASTER) 
    out %al, i8259A_ICW4_ADDR($i8259A_SLAVE) 

    call mm_detect 

    /* Load the kernel now. */ 

    xor %bp, %bp 
1: 
    mov $KERNEL_ORG >> 0x4, %ax 
    mov %ax, %es 
    mov $KERNEL_ORG & 0xf, %bx 
    mov $0x200 | KERNEL_SECTORS, %ax 
    mov $(KERNEL_C << 0x8) | KERNEL_S, %cx 
    mov $(KERNEL_H << 0x8) | FLOPPY_DRV, %dx 
    int $0x13 /* <--- This int 0x13 doesn't seem to return */ 
    jnc 1f 
    cmp $0x2, %bp 
    je floppy_err 
    inc %bp 
    xor %ah, %ah 
    int $0x13 
    jmp 1b 

. 단지 make all를 사용하여 구축하고 다음 명령을 내가 정말 모든 매개 변수를 잘 가지고 확인 된 한 bochs


우선을 사용 Bochs와으로 실행합니다. Bochs와 '쉘 수율 r (. 섹터 번호 및 실린더의 높은 두 개의 비트 아니오)

CPU0: 
rax: 00000000_534d0201 rcx: 00000000_00000005 
rdx: 00000000_534d0000 rbx: 00000000_00000000 
rsp: 00000000_00007700 rbp: 00000000_00000000 
rsi: 00000000_000e0005 rdi: 00000000_00000316 
r8 : 00000000_00000000 r9 : 00000000_00000000 
r10: 00000000_00000000 r11: 00000000_00000000 
r12: 00000000_00000000 r13: 00000000_00000000 
r14: 00000000_00000000 r15: 00000000_00000000 
rip: 00000000_00000036 
eflags 0x00007046: id vip vif ac vm rf NT IOPL=3 of df if tf sf ZF af PF cf 

ah = 0x2 (루틴 ID) al = 0x1 (섹터 수) ch = 0x0, cl = 0x5 (실린더 번호의 하위 바이트) dh = 0x0 (헤드 번호), dl = 0x0 (드라이브 번호). es에 대한

sreg 지문 :

es:0x0000 

bx = 0x0,이 분야는 내가 의도 한대로 0x0:0x0에로드되도록.

  1. 로드 나는 어쩌면 IVT를 무시하거나 BDA는 BIOS의 실행 중에 좋은 생각되지 않을 수도 있습니다 인터럽트 루틴 생각 0x600

    물리적 주소 :


    나는 몇 가지 시도 그래서 섹터를 0x600 (es = 0x60, bx = 0x0)으로로드하려고 시도했습니다. BDA의 크기는 256 바이트뿐입니다. 같은 결과.

  2. 로드 아마 다섯 번째 부문을 읽는 디스크

    의 첫 번째 부문은 경계 또는 무엇이든에서 어떻게 든? int 0x13을 사용하여 두 번째 단계를 읽는 코드가 예상대로 작동합니다. 내 두 번째 단계의 int 0x13도 비슷하므로 제대로 작동 할 것으로 예상됩니다. 테스트로서, 나는 두 번째 단계에서 섹터 1을 읽도록 변경했으나 여전히 작동하지 않았습니다. 내가 생각 eax

    의 상단 부분을 비우기

  3. 어쩌면 실제로 BIOS 루틴의 버그가 어떻게 든 eaxax을 사용하지 않습니다. eax의 상위 16 비트 부분을 제로로 해봤습니다 ... 아무 소용이 없습니다.

앞서 말한 것처럼 이미 디스크의 일부 섹터를 메모리에로드했습니다.합니다 (Bochs와 쉘에 r을 사용하여 얻은) 다음과 같이 int 0x13 전에 GPRS는 "콘텐트 권한은 :

CPU0: 
rax: 00000000_00000203 rcx: 00000000_00090002 
rdx: 00000000_00000000 rbx: 00000000_00000000 
rsp: 00000000_00007700 rbp: 00000000_00000000 
rsi: 00000000_000e7cdd rdi: 00000000_000000e2 
r8 : 00000000_00000000 r9 : 00000000_00000000 
r10: 00000000_00000000 r11: 00000000_00000000 
r12: 00000000_00000000 r13: 00000000_00000000 
r14: 00000000_00000000 r15: 00000000_00000000 
rip: 00000000_00007c59 
eflags 0x00007046: id vip vif ac vm rf NT IOPL=3 of df if tf sf ZF af PF cf 

sreg

EBDA 바로 전에 계산 동적 주소 es:0x8f60를 산출한다.

두 가지를 모두 비교해 보면 인터럽트 루틴의 기능에 영향을 줄 수있는 중요한 차이가 나타나지 않으므로 문제는 레지스터를 통해 전달 된 매개 변수가 될 수 없습니다.

누구에게 무엇을해야하는지에 대한 다른 제안이 있습니까? 나는 종류의 당신의 Int 13h/AH=02h 플로피 디스크를 읽는 코드 ... 여기

+1

[mcve]로 문제를 격리 해 보았습니까? 특히 IP가 첫 번째 경우에는 36h이고 두 번째 경우에는 7c59h 인 것을 고려하여 세그먼트 레지스터를 설정하는 방법. –

+0

"섹터가 0x0 : 0x0에로드됩니다."- 그래서 err이 인터럽트 벡터 테이블을 덮어 쓰시겠습니까? – davmac

+0

@MargaretBloom'cs'는 전자의 경우 '0x8f60'이고 후자의 경우 '0x0'입니다. BIOS는 부트 로더를 실제 주소 0x7c00으로로드하고, 부트 로더는 EBDA 바로 아래에있는 2 단계 부트 로더를로드하며, 그 시작 값은 동적으로 얻어지며, 2 단계 부트 로더는 커널을 물리적 주소 0x0로로드합니다. ** no ** 시도가 성공했다면로드 섹터가 작동하는지 확인하기 위해 MCVE를 할 것입니다. 그러나 보조 부트 로더를로드하는 것은 정상적으로 작동합니다. – Downvoter

답변

6

문제의 몇 가지를 잃었어요 :

  1. 이미 귀하의 질문에 식별이 하나. 리얼 모드에서 실행하면 0x0000 : 0x0000 상단의 섹터를 읽는 것이 좋습니다. 그러면 인터럽트 벡터 테이블 (IVT)이 손상됩니다. 0x0000 : 0x0000에서 0x0040 : 0x0000까지의 영역이 IVT입니다. 영역 0x0040 : 0x0000 ~ 0x0060 : 0x0000은 BIOS Data Area (BDA)입니다. BDA는 실제 모드 BIOS 루틴이 사용할 수있는 스크래치 영역으로 간주되어야합니다.

    0x0060 : 0x0000 (실제 주소 0x00600)과 같이 어딘가에 안전하게로드하도록 수정하려면.

    보호 모드에 들어가면 0x00000000과 0x00000600 사이의 영역을 다른 용도로 사용할 수 있습니다. 참고 : System Management Mode (SMM) 및 Advanced Configuration and Power Interface (ACPI)이 쓸 수 있기 때문에 Extended BIOS Data Area (EBDA) 메모리 영역을 범용 메모리로 사용하지 마십시오.

  2. 코드가 8259A를 다시 매핑하여 보호 모드를 준비합니다. 이렇게하면 IRQ는 IVT의 다른 부분으로 다시 매핑됩니다. Int 13h 루틴은 인터럽트 및 BIOS 인터럽트 루틴을 사용하여 플로피 디스크 읽기에 필요한 작업을 수행 할 수 있습니다. IRQ0 (시스템 타이머) 및 IRQ6 (플로피 컨트롤러)가 가능합니다. 8259A의베이스를 다른 곳에서 다시 매핑하면 BIOS가 설치 한 인터럽트 루틴이 실행되지 않습니다. 이 경우 예기치 않은 동작 (예 : Int 13h)이 반환되지 않을 수 있습니다.

    문제를 해결하려면 보호 모드에있는 후 8259A PIC의 기본을 다시 매핑하는 것이 좋습니다. 그때까지는 BIOS 인터럽트가 발생할 가능성이 높으므로 문제가되지 않아야합니다.

관련 문제