Search code examples
assemblyoperating-systemnasmx86-16bios

Why does my assembly program gets stuck when it's excuting 'int 13h'?


I'm trying to make an operating system and I've written two programs: boot.asm and loader.asm, the compilation process was very success, but when I'm using bochs to debug my program, it gets stuck at the command 'int 13h'.Did anyone has a solution to this problem?

Here's my code:

boot.asm:

org 07c00h

...
BPB_SecPerTrk dw 18
BS_DrvNum db 0
...

ReadOneSector:
    push bp
    mov sp, sp
    sub esp, 2
    mov byte [bp-2], cl
    push bx
    mov bl, [BPB_SecPerTrk]
    div bl
    inc ah
    mov cl, ah
    mov dh, al
    shr al, 1
    mov ch, al
    and dh, 1
    pop bx
    mov dl, [BS_DrvNum]
Label_Go_Reading:
    mov ah, 2
    mov al, byte [bp-2]
    int 13h ; the program gets stuck when running this line
    jc Label_Go_Reading
    add esp, 2
    pop bp
    ret
...

times 510-($-$$) db 0
dw 0xaa55

Here's the debugger's output:

<bochs:45> n
Next at t=14041939
(0) [0x000000007ca1] 0000:7ca1 (unk. ctxt): mov al, byte ptr ss:[bp-2] ; 8a46fe
<bochs:46> n
Next at t=14041940
(0) [0x000000007ca4] 0000:7ca4 (unk. ctxt): int 0x13                  ; cd13
<bochs:47> n ;the program gets stuck when executing this line

Can anyone tell me why does the program gets stuck and how to solve this problem(I think maybe the code before can't let 'int 13h' run)


Solution

  • ReadOneSector:
        push bp
        mov sp, sp     <<<<<<<<<<<<<<<<<<<<<<<<<<<<
        sub esp, 2
        mov byte [bp-2], cl
    

    There's a typo in the third line. You want to load the BP register, not just nop on SP!

    Next solution avoids putting a local variable on the stack:

    ; IN (ax,es:bx,cl)
    ReadOneSector:
        push  bp
        mov   ch, 2     ; CH Function number
        mov   bp, cx    ; CL Sector count
        push  bx
        mov   bl, [BPB_SecPerTrk]
        div   bl
        inc   ah
        mov   cl, ah
        mov   dh, al
        shr   al, 1
        mov   ch, al
        and   dh, 1
        pop   bx
        mov   dl, [BS_DrvNum]
    Label_Go_Reading:
        mov   ax, bp    ; -> AH function number, AL sector count
        int   13h
        jc    Label_Go_Reading
        pop   bp
        ret
    

    If this routine is named "Read One Sector", then why is there even a parameter (in CL) for the number of sectors?
    Anyway, for reading/writing several sectors it's probably best to read/write a single sector and repeat that in a loop (look up multitrack problem):

    ; IN (ax,es:bx,cl)
    ReadMultipleSectors:
        pusha
        movzx bp, cl    ; CL Sector count 1+
    NextSector:
        push  ax        ; (1)
        push  bx        ; (2)
        mov   bl, [BPB_SecPerTrk]
        div   bl
        inc   ah
        mov   cl, ah
        mov   dh, al
        shr   al, 1
        mov   ch, al
        and   dh, 1
        pop   bx        ; (2)
        mov   dl, [BS_DrvNum]
    Label_Go_Reading:
        mov  ax, 0201h
        int  13h
        jc   Label_Go_Reading
        pop  ax         ; (1)
        inc  ax         ; Next sector number
        add  bx, 512    ; Next sector buffer
        dec  bp
        jnz  NextSector
        popa
        ret