Bootloader加载图像文件

时间:2014-03-04 05:34:36

标签: assembly bootloader

我需要一些帮助来理解使用BrokenThorn的bootloader加载内核的逻辑。

代码:

LOAD_IMAGE:

          mov     ax, WORD [cluster]                  ; cluster to read
          pop     bx                                  ; buffer to read into
          call    ClusterLBA                          ; convert cluster to LBA
          ;xor     cx, cx
          ;mov     cl, BYTE [bpbSectorsPerCluster]     ; sectors to read (commenting out has same result?
          call    ReadSectors                          ;(ES:BX from above)
          push    bx

     ; compute next cluster

          mov     ax, WORD [cluster]                  ; identify current cluster
          mov     cx, ax                              ; copy current cluster
          mov     dx, ax                              ; copy current cluster
          shr     dx, 0x0001                          ; divide by two
          add     cx, dx                              ; sum for (3/2)
          mov     bx, 0x0200                          ; location of FAT in memory
          add     bx, cx                              ; index into FAT
          mov     dx, WORD [bx]                       ; read two bytes from FAT
          test    ax, 0x0001
          jnz     .ODD_CLUSTER

     .EVEN_CLUSTER:

          and     dx, 0000111111111111b               ; take low twelve bits
         jmp     .DONE

     .ODD_CLUSTER:

          shr     dx, 0x0004                          ; take high twelve bits

     .DONE:

          mov     WORD [cluster], dx                  ; store new cluster
          cmp     dx, 0x0FF0                          ; test for end of file
          jb     LOAD_IMAGE

     DONE:

          mov     si, msgCRLF
          call    Print
          push    WORD 0x0050
          push    WORD 0x0000
          retf

为什么我需要将CHS转换为LBA?在该函数中,似乎LBA存储在AX寄存器中。但它没有在ReadSectors中使用?然后,将当前群集复制到AX中。

ClusterLBA:
          sub     ax, 0x0002                          ; zero base cluster number
          xor     cx, cx
          mov     cl, BYTE [bpbSectorsPerCluster]     ; convert byte to word
          mul     cx
          add     ax, WORD [datasector]               ; base data sector

          ret

此外,引导加载程序将内核加载到内存位置0x0050:0x0000

为什么我不能jmp 0x0050:0x0000并开始执行代码?什么

push WORD 0x0050 push WORD 0x0000

做什么?这在教程中没有解释。

2 个答案:

答案 0 :(得分:2)

ClusterLBA将群集#(在AX中)转换为扇区#(在AX中),以便能够通过int 13h读取这些扇区。
ReadSectors似乎将AX,ES:BX作为参数 推,推,retf相当于jmp远。两种变体都是5个字节长。没有区别。

答案 1 :(得分:1)

为什么我需要将CHS转换为LBA?

你没有,代码在我能看到的任何地方都没有这样做。我假设代码所做的是将(FAT)“簇号”转换为LBA号。请注意,FAT文件系统使用群集(可能是512字节,1024字节......),其中群集编号相对于分区的开头(而不是磁盘的开头)。

在该函数中,好像LBA存储在AX寄存器中。但它没有在ReadSectors中使用?

您没有发布ReadSectors的代码,也没有提供该代码可能位于何处的链接。我只能假设你错了,并且ReadSectors确实在AX中使用了LBA(例如在使用int0x13加载扇区之前立即进行快速LBA到CHS转换。)

为什么我不能jmp 0x0050:0x0000并开始执行代码?

你可以。

遗憾的是,很多编写汇编语言代码的人都不是汇编语言程序员(例如他们可能是熟悉汇编语言的C程序员)。更可悲的是,一些陈旧的装配工并不是很好,让人们很难弄清楚如何做得很远。基本上,“推;推; retf”就在那里,因为无论谁编写它都没有或无法弄清楚如何正确地做到这一点。