GRUB2 BOOT

1 啟動程式

GRUB2 的 I386-PC 啟動程式位於目錄 grub2\grub-core\boot\i386\pc 的 boot.S、diskboot.S、cdboot.S、lnxboot.S、pxeboot.S。 這幾個檔案分別用來處理四種不同的啟動程序,包括軟硬碟啟動、光碟啟動、網路啟動、LILO啟動。

啟動程式 pxeboot.S 本身並不做事,只是提供一個跳板,執行 GRUB核心。主要是由 BIOS 從網路載入 GRUB 映像,這部分必須有主機板的網路開機才能支援。

啟動程式 lnxboot.S 會和 GRUB 核心映像放在一起,讓 LILO 可以辨識,並載入記憶體執行。 有點像是騙 LILO 說我是 LINUX,請把我載入記憶體執行。只要 lnxboot 執行起來,就會繼續執行 GRUB 核心,而不需要做磁碟讀取的動作。

這裡筆者要說明的是軟硬體啟動程式,並在下一章中說明光碟啟動程式,略過網路啟動程式和偽 LINUX 啟動程式。


2 軟硬碟啟動程式

啟動程式 boot.S 會測試啟動磁碟的類型和讀取規格,再繼續載入第二個磁區,磁碟啟動程式 diskboot.S,到 0x8000 的位址上。 之後,啟動程式就會跳到 0x8000 執行磁碟啟動程式,啟動程式 boot.S 的工作到此告一段落。 磁碟啟動程式會將 GRUB 映像載入 0x8200,在跳到 0x8200 的位址上執行 GRUB 核心。


2.1 啟動程式開頭

,。

00 .file "boot.S"
00 .text
00 .code16
00 .globl _start, start;
00 _start:
00 start:
00 jmp	LOCAL(after_BPB)
00 nop
00 . = _start + GRUB_BOOT_MACHINE_BPB_START
00 . = _start + 4
00 mode:	         .byte 0
00 disk_address_packet:
00 sectors:         .long 0
00 heads:           .long 0
00 cylinders:       .word 0
00 sector_start:    .byte 0
00 head_start:      .byte 0
00 cylinder_start:	 .word 0
00 . = _start + GRUB_BOOT_MACHINE_BPB_END
00 kernel_address:	 .word GRUB_BOOT_MACHINE_KERNEL_ADDR
00 . = _start + GRUB_BOOT_MACHINE_KERNEL_SECTOR
00 kernel_sector:   .long 1, 0
00 . = _start + GRUB_BOOT_MACHINE_BOOT_DRIVE
00 boot_drive: .byte 0xff	


2.2 磁碟模式初檢

當剛從 BIOS 過來的時候,BIOS 應該會預先把啟動磁碟的參數放在 dl 暫存器。 所以先從 dl 暫存器值判讀啟動磁碟。

00 LOCAL(after_BPB):
00  cli
00  . = _start + GRUB_BOOT_MACHINE_DRIVE_CHECK
00 boot_drive_check:
00  jmp   3f
00  testb $0x80, %dl
00  jz    2f
00 3:
00  testb $0x70, %dl
00  jz    1f
00 2:
00  movb  $0x80, %dl
00 1:
00  ljmp  $0, $real_start


2.3 判斷磁碟模式

這段程式碼的動作分二段,初始化節區戰存器、測試啟動磁碟。 初始化節區戰存器的動作是設定資料節區暫存器為0,並設定堆疊指標為 0:2000。 測試啟動磁碟的部分是以 int 0x13,ah=0x41 的指令,探知磁碟是否支援延伸屬性,即 LBA 模式。
如果指令回應結果是 cf=1,表示不支援 LBA,程序跳往 CHS 處理程序。
如果指令回應結果是 bx 不等於 0xaa55,表示不支援 LBA,程序跳往 CHS 處理程序。
如果指令回應結果是 cx 的位元 0 不等於 1,表示不支援 LBA 命令結構,程序跳往 CHS 處理程序。 通過以上三個條件的測試後,啟動磁碟應該支援 LBA 模式。 這裡說"應該"表示不完全確定,如果LBA模式讀取出錯的話,再嘗試 CHS 模式。

00 real_start:
00 xorw %ax, %ax
00 movw %ax, %ds
00 movw %ax, %ss
00 movw $GRUB_BOOT_MACHINE_STACK_SEG, %sp
00 sti
00 movb boot_drive, %al
00 cmpb $0xff, %al
00 je   1f
00 movb %al,%dl
00 1:
00 pushw %dx
00 MSG(notification_string)
00 movw $disk_address_packet, %si
00 movb $0x41, %ah
00 movw $0x55aa, %bx
00 int  $0x13
00 popw %dx
00 pushw %dx
00 jc   LOCAL(chs_mode)
00 cmpw $0xaa55, %bx
00 jne  LOCAL(chs_mode)
00 andw $1, %cx
00 jz   LOCAL(chs_mode)


2.4 LBA 模式讀取磁碟

使用 LBA 模式讀取啟動磁碟之前,已經先判斷磁碟的 CHS/LBA 模式。 當啟動磁碟為 LBA 模式時,啟動磁碟一定是硬碟。 當LBA讀取失敗後,就表示磁碟的讀取格式應該是 CHS 模式,再到 CHS 模式執行磁碟讀取程序。

00 lba_mode:
00 xorw	%ax, %ax
00 movw	%ax, 4(%si)
00 incw	%ax
00 movb	%al, -1(%si)
00 movw	%ax, 2(%si)
00 movw	$0x0010, (%si)
00 movl	kernel_sector, %ebx
00 movl	%ebx, 8(%si)
00 movl	kernel_sector + 4, %ebx
00 movl	%ebx, 12(%si)
00 movw	$GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si)
00 movb	$0x42, %ah
00 int	$0x13
00 jc	LOCAL(chs_mode)
00 movw	$GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
00 jmp	LOCAL(copy_buffer)


2.5 CHS 模式讀取磁碟

以下說明 CHS 模式的存取步驟。


2.5.1 檢驗磁碟

當啟動磁碟為 CHS 模式時,啟動磁碟有可能是硬碟或軟碟,先測試啟動磁碟為硬碟或軟碟。

00 LOCAL(chs_mode):
00 movb	$8, %ah
00 int	$0x13
00 jnc	LOCAL(final_init)
00 testb	$GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl
00 jz	LOCAL(floppy_probe)
00 ERR(hd_probe_error_string)
00 


2.5.2 計算磁碟參數

計算磁碟 CHS 模式的各參數值,包括磁柱值、磁頭值、磁軌值。 這些值會填入 BPB 表格,做為計算磁區讀取位置的參考。

00 LOCAL(final_init):
00 movzbl	%dh, %eax
00 movb	%ah, -1(%si)
00 incw	%ax
00 movl	%eax, 4(%si)
00 movzbw	%cl, %dx
00 shlw	$2, %dx
00 movb	%ch, %al
00 movb	%dh, %ah
00 incw	%ax
00 movw	%ax, 8(%si)
00 movzbw	%dl, %ax
00 shrb	$2, %al
00 movl	%eax, (%si)
00 


2.5.3 計算磁碟讀取參數

計算所要讀取磁區的 CHS 模式磁碟參數,包括該磁區所在的磁柱值、磁頭值、磁軌值。

00 setup_sectors:
00 movl	kernel_sector + 4, %eax
00 orl	%eax, %eax
00 jnz	LOCAL(geometry_error)
00 movl	kernel_sector, %eax
00 xorl	%edx, %edx
00 divl	(%si)
00 movb	%dl, %cl
00 xorw	%dx, %dx
00 divl	4(%si)
00 cmpw	8(%si), %ax
00 jge	LOCAL(geometry_error)
00 incb	%cl
00 movb	%al, %ch
00 xorb	%al, %al
00 shrw	$2, %ax
00 orb	%al, %cl
00 movb	%dl, %al
00 popw	%dx
00 movb	%al, %dh
00 movw	$GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
00 movw	%bx, %es
00 xorw	%bx, %bx
00 movw	$0x0201, %ax
00 int	$0x13
00 jc	LOCAL(read_error)
00 movw	%es, %bx


2.6 軟碟讀取程序

磁碟啟動程式位於第二個磁區,會先被存入到 0x7000,再複製到 0x8000。 因為不知道軟碟機的格式,所以會從一個磁軌有36個磁區的軟碟格式開始讀取。 讀取失敗再嘗試一個磁軌有 18 個磁區,接著再嘗試 18、15、9 磁區的格式,嘗試到 0 的時候,等於是宣告軟碟讀取失敗。

00 probe_values: .byte 36, 18, 15, 9, 0
00 LOCAL(copy_buffer):
00  pusha
00  pushw %ds
00  movw $0x100, %cx
00  movw %bx, %ds
00  xorw %si, %si
00  movw $GRUB_BOOT_MACHINE_KERNEL_ADDR, %di
00  movw %si, %es
00  cld
00  rep
00  movsw
00  popw %ds
00  popa
00  jmp *(kernel_address)


2.7 軟碟讀取程序

00 LOCAL(floppy_probe):
00  movw $probe_values - 1, %si
00 LOCAL(probe_loop):
00  xorw %ax, %ax
00  int  $0x13
00  incw %si
00  movb (%si), %cl
00  cmpb $0, %cl
00  jne  1f
00  MSG(fd_probe_error_string)
00  jmp  LOCAL(general_error)
00 fd_probe_error_string:	.asciz "Floppy"
00 1:
00  movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
00  movw %bx, %es
00  xorw %bx, %bx
00  movw $0x201, %ax
00  movb $0, %ch
00  movb $0, %dh
00  int $0x13
00  jc LOCAL(probe_loop)
00  movb $1, %dh
00  movb $79, %ch
00  jmp LOCAL(final_init)


2.9 讀取軟碟機

磁碟啟動程式位於第二個磁區,會先被存入到 0x7000,再複製到 0x8000。

00 1:
00  movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
00  movw %bx, %es
00  xorw %bx, %bx
00  movw $0x201, %ax
00  movb $0, %ch
00  movb $0, %dh
00  int  $0x13
00  jc   LOCAL(probe_loop)
00  movb $1, %dh
00  movb $79, %ch
00  jmp  LOCAL(final_init)


2.10 啟動程式結尾

啟動程式的結尾是一個結尾特徵值 0x55aa,0xaa 在第 511 位元組,0x55 在第 512 位元組。

00 . = _start + GRUB_BOOT_MACHINE_PART_END
00 .word	GRUB_BOOT_MACHINE_SIGNATURE


3 磁碟啟動程式

磁碟啟動程式負責從啟動磁碟將 GRUB 映像載入記憶體。 以 I386-PC 架構來說,就是載入到 0000:8200 的位址上。 GRUB2 的映像資訊是由 grub2/grub-mkimage 在製作映像時才填入,所以在這個檔案中其值均為 0。


3.1 程式開頭

1.宣告檔案名稱。 2.宣告以下為程式碼區段。 3.設定編譯格式為16位元。 4.將符號 start和_start 引出,只是應該沒有其他程式會用到這個符號,引出了也沒有意義。 5.將磁碟參數存在堆疊中 6.顯示 GRUB2 的啟動資訊,為了保存 si 暫存器的值,需要再事前存入堆疊,事後再取出堆疊。 7.計算 GRUB 映像的參數位址值,並存入 di 暫存器。此位址也是檔案最後面第 12 位元組的地方,內容包含磁區起始位址(八位元組)、磁區數(二位元組)、要載入的記憶體節區位址(二位元組)。 8.將 GRUB 映像的參數位址值存入 ebp 暫存器。

diskboot.S
01 .file "diskboot.S"
02 .text
03 .code16
04 .globl	start, _start
05 start:
06 _start:
07  pushw	%dx
08  pushw	%si
09  MSG(notification_string)
10  popw	%si
11  movw	$(firstlist - GRUB_BOOT_MACHINE_LIST_SIZE), %di 
12  movl	(%di), %ebp

行號說明
01宣告檔案名稱。
02宣告以下為程式碼區段。
03設定編譯格式為16位元。
04將符號 start和_start 引出,只是應該沒有其他程式會用到這個符號,引出了也沒有意義。
07將磁碟參數存在堆疊。
09顯示 GRUB2 的啟動資訊,為了保存暫存器 si 的值,需要再事前存入堆疊,事後再取出堆疊。暫存器 si 存有 boot.S 的 PBP 位址值。
11計算 GRUB 映像的參數位址值,並存入 di 暫存器。此位址也是檔案最後面第 12 位元組的地方,內容包含磁區起始位址(八位元組)、磁區數(二位元組)、要載入的記憶體節區位址(二位元組)。,。
12將 GRUB 映像的參數位址值存入 ebp 暫存器。

3.2 檢查磁區數目

檢查磁區數目,為 0 時,表示 GRUB 映像已經讀完,可以啟動 GRUB 核心了 (bootit=boot grub kernel)。 啟動前先顯示啟動訊息,再將程式開頭時堆入堆疊的磁碟參數取出,放入 dx,但這個步驟在筆者看來是多餘的,因為 GRUB 的起始程式用不到這個參數。 跳進 GRUB 映像就是跳到 0000:8200,執行 startup.S 進行 GRUB2 核心的起始程序。

diskboot.S
00 LOCAL(bootloop):
00  cmpw	$0, 8(%di)
00  je	LOCAL(bootit)
00 
00 LOCAL(setup_sectors):
00  ...
00  
00 LOCAL(bootit):
00  MSG(notification_done)
00  popw	%dx
00  ljmp	$0, $(GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)

行號說明
01當磁區數目等於 0,跳到 GRUB 映像啟動程序處。
01顯示GRUB讀取完成訊息。
01將磁碟代號從堆疊中復原到 dl 暫存器,外面看起來是 dx,事實上只有 dl 的值有用。
01跳躍到 0000:8200,開始執行 GRUB2 映像。

3.3 LBA 模式

lba 模式 GRUB 核心映像讀取程序。
暫存器 si 指向啟動程式的 disk_address_packet(BLOCK PARAMETER BLOCK),也因此 %si-1 就是 mode 符號的位址,其值指示啟動磁碟的 chs(0)/lba(1) 模式。 當 mode 值為 0,表示啟動磁碟的操作模式為 chs,跳到 chs 模式讀取 GRUB 核心映像。 當 mode 值不為 0,表示啟動磁碟的操作模式為 lba,執行 lba 模式讀取 GRUB 核心映像。

diskboot.S
01 LOCAL(setup_sectors):
02  cmpb	$0, -1(%si)
03  je	LOCAL(chs_mode)
04  movl	(%di), %ebx
05  movl	4(%di), %ecx
06  xorl	%eax, %eax
07  movb	$0x7f, %al
08  cmpw	%ax, 8(%di)
09  jg	1f
10  movw	8(%di), %ax
11 1:
12  subw	%ax, 8(%di)
13  addl	%eax, (%di)
14  adcl	$0, 4(%di)
15  movw	$0x0010, (%si)
16  movw	%ax, 2(%si)
17  movl	%ebx, 8(%si)
18  movl	%ecx, 12(%si)
19  movw	$GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si)
20  pushw	%ax
21  movw	$0, 4(%si)
22  movb	$0x42, %ah
23  int	$0x13
24  jc	LOCAL(read_error)
25  movw	$GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
26  jmp	LOCAL(copy_buffer)

行號說明
02判斷 mode 為 chs 或 lba,0 時為 chs 模式。
03變數 mode 為 0,跳躍到 chs 模式磁碟讀取程序處。
04取得磁區位址值的低四位元組,存入 ebx。
05取得磁區位址值的高四位元組,存入 ecx。
06清除 eax 為 0。
07設定 al 為 0x7f,所以 ax 也為 0x7f。
08~10比較磁區數目與ax,如果磁區數目小於或等於 0x7f,將磁區數目值移入 ax。
12從磁區數目扣除此次要讀取的磁區數。
13~14接下來會讀取啟動磁碟,這裡預先計算讀取後的磁區位置。因為磁區位置為 8 位元組,有進位時,高四位元組加一。
15將 PBP 的 DAP 欄位設定為 0x10。暫存器 si 指向 boot.S 的 PBP 起始位址。
PBP在 chs 模式時,各欄位分別是 sectors(4)、headers(4)、cylinders(2)、sector start(1)、head start(1)、cylinder(2)。
BPB在 lba 模式時,各欄位分別是 DAP(1)、unused(1)、sector count(2)、offset(2)、segment(2)、sector(8)。
16設定 lba 模式下,PBP 的 sector count 欄位,ax 是磁區數目。
17~18設定 lba 模式下,PBP 的 sector 欄位,ebx 是低四位元組,ecx 是高四位元組。
19設定 lba 模式下,PBP 的 segment 欄位,此值的起始值是 0x7000,表示讀取的磁碟資料都會放在 7000:0000 的位址。
20將此次讀取的磁區數目存放在堆疊中,讀完磁碟後還會用到。
21設定 lba 模式下,PBP 的 offset 欄位,設定此值為 0,表示讀取的磁碟資料都會放在 7000:0000 的位址。
22設定 ah 為 0x42,表示要執行 lba 磁碟讀取命令。
23呼叫 bios 中斷服務 int 0x13,執行磁碟讀取。
24有錯誤發生,跳至讀取錯誤處理程序。
25沒有錯誤發生,設定 bx=0x7000,準備複製到執行 GRUB2 映像的記憶體位址。
26跳至記憶體複製程序處,執行計憶體的複製。

3.4 CHS 模式

chs 模式 GRUB 核心映像讀取程序。

diskboot.S
01 LOCAL(chs_mode):
02  movl	4(%di), %eax
03  orl	%eax, %eax
04  jnz	LOCAL(geometry_error)
05  movl	(%di), %eax
06  xorl	%edx, %edx
07  divl	(%si)
08  movb	%dl, 10(%si)
09  xorl	%edx, %edx
10  divl	4(%si)
11  movb	%dl, 11(%si)
12  movw	%ax, 12(%si)
13  cmpw	8(%si), %ax
14  jge	LOCAL(geometry_error)
15  movw	(%si), %ax
16  subb	10(%si), %al
17  cmpw	%ax, 8(%di)
18  jg	2f
19  movw	8(%di), %ax
20 2:
21  subw	%ax, 8(%di)
22  addl	%eax, (%di)
23  adcl	$0, 4(%di)
24  movb	13(%si), %dl
25  shlb	$6, %dl
26  movb	10(%si), %cl
27  incb	%cl
28  orb	%dl, %cl
29  movb	12(%si), %ch
30  popw	%dx
31  pushw	%dx
32  movb	11(%si), %dh
33  pushw	%ax
34  movw	$GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
35  movw	%bx, %es	
36  xorw	%bx, %bx
37  movb	$0x2, %ah
38  int	$0x13
39  jc	LOCAL(read_error)
40  movw	%es, %bx

行號說明
02~12計算 chs 模式的讀取位置,包括 sector start、head start、cylinder start。
02~04取得磁區位置的高四位元組,不為0時,即為磁碟幾何錯誤。
05取得磁區位置的低四位元組。
06清除 edx 為 0。
07eax 除以 si,取得磁軌數目 eax 和磁區位置值 edx。
08將磁區值 dl 設定給 chs 模式 PBP 的 sector start 欄位。
09清除 edx 為 0。
010eax 除以 si,取得磁柱數目 eax 和磁頭位置值 edx。
11將磁頭值 dl 設定給 chs 模式 PBP 的 header start 欄位。
12將磁柱數目 eax 設定給 chs 模式 PBP 的 cylinder start 欄位。
13~14當 cylinder start 大於或等於 cylinders,表示磁碟太小,產生磁碟幾何錯誤。
15取得磁軌的最大磁區數。
16最大磁區數減去sector start,得到該磁軌內可讀的磁區數。
17~19當可讀取的磁區數大於需要的磁區數目,重新設定要讀的磁區數目為需要的磁區數目。
21計算此次讀取後剩下的磁區數目值,目前磁區數目減去要讀取的磁區數目。
22計算此次讀取後的磁區位置值,目前磁區位置加上要讀取的磁區數目。如果有進位,把進位值加到磁區位置的高四位元組。
23~28因為 chs 模式下,cyliner high 會併到 sector start 位元組的高位元處,即 ch[1]ch[0]+s[5]s[4]s[3]s[2]s[1]s[0]。 將 cylinder high 向左旋六位元,再將 sector start 值加一,再將二者加在一起,即得到此組合值,存入 cl。
29取得 cylinder low,存入 ch。
30~31取得磁碟號碼,再存回堆疊,因為還會用到。
32取得 header start,存入 dh。
30~31將要讀取的磁區數目 ax,存入堆疊。
34~35取得緩衝區的節區號碼,存入 es,準備用來存入讀取的磁碟資料。
36清除 bx。
37設定 ah 為 0x02,表示要執行 chs 磁碟讀取命令。
38呼叫 bios 中斷服務 0x13,執行磁碟讀取命令。
39當 cpu 的 cf 旗號為1,表示讀取錯誤。
40將 es 中的 0x7000 存入 bx。

3.5 複製緩衝區

將讀取的磁碟資料複製到核心映像記憶體,。

diskboot.S
01 LOCAL(copy_buffer):
02  movw	10(%di), %es
03  popw	%ax
04  shlw	$5, %ax
05  addw	%ax, 10(%di)
06  pusha
07  pushw	%ds
08  shlw	$3, %ax
09  movw	%ax, %cx
10  xorw	%di, %di
11  xorw	%si, %si
12  movw	%bx, %ds
13  cld
14  rep
15  movsw
16  popw	%ds
17  MSG(notification_step)
18  popa
19  cmpw	$0, 8(%di)
20  jne	LOCAL(setup_sectors)
21  subw	$GRUB_BOOT_MACHINE_LIST_SIZE, %di
22  jmp	LOCAL(bootloop)

行號說明
02取得複製資料的目的節區 es。
03取得要讀取的磁區數目 ax。
04計算要讀取的磁區所跨越的節區範圍,即磁區數目*32。
05~06計算此次複製資料後的節區值,即目前節區值加上資料節區範圍,並存入堆疊。
07將資料節區暫存器存入堆疊,因為後面的複製動作會破壞此暫存器。
08計算要讀取磁區字組數,即磁區數目*32*8。注意,一個字組等於二位元組。
09將要讀取磁區字組數存入cx,做為複製資料的計數器。
10~11清除目標索引暫存器 di 和來源索引暫存器 si。
12設定資料節區 ds 為 0x7000,即磁碟資料緩衝區。
13設定複製方向為位址遞增。
14啟動複製功能。
15執行複製,一次一個字組。
16資料複製完成,從堆疊回復 ds 暫存器值。
17顯示載入訊息 "."。
18從堆疊回復 acc 暫存器值。
19~20當磁區數目不為0,表示還有磁區資料要讀取,繼續執行磁碟讀取迴圈。
21這行指令的目的比較奇怪,因為暫存器 di 指向 blocklist_default_start,減去 12 的意義是什麼? 原來是 LOCAL(bootloop) 有一行指令 cmpw $0, 8(%di)。為了讓 %di+8 指向一個 0,以滿足離開條件,作者在 blocklist_default_start 之前埋入 .word 0,0。 意思是 di 先指向 blocklist_default_start-12,再透過 8(%di) 指向 .word 0,0,好滿足 cmpw $0, 8(%di),並離開磁碟啟動程式。
15,。

3.6 錯誤處理程序

兩個錯誤處理程序,當磁區位置太大時,表示為磁碟幾何錯誤,顯示幾何錯誤訊息,再顯示一般錯誤訊息。 當讀取磁碟發生錯誤時,表示為磁碟讀取錯誤,顯示讀取錯誤訊息,再顯示一般錯誤訊息。 顯示錯誤訊息後,執行因錯誤而停止的無窮迴圈。

diskboot.S
00 LOCAL(geometry_error):
00  MSG(geometry_error_string)
00  jmp LOCAL(general_error)
00 
00 LOCAL(read_error):
00  MSG(read_error_string)
00 
00 LOCAL(general_error):
00  MSG(general_error_string)
00 
00 LOCAL(stop): jmp LOCAL(stop)

行號說明
01,。

3.7 訊息顯示程序

訊息顯示程序。

diskboot.S
01 1:
02  movw	$0x0001, %bx
03  movb	$0xe, %ah
04  int	$0x10
05  incw	%si
06 LOCAL(message):
07  movb	(%si), %al
08  cmpb	$0, %al
09  jne	1b
10  ret

行號說明
02~04顯示一個字的程序,使用 bios 0x10 呼叫。
05遞增一個字的位址。
07取得一個字的值。
08~10當字的值為 0,遇到字串結尾,離開字串顯示迴圈。當字的值不為 0,繼續執行字串顯示迴圈。

3.8 磁碟映像變數

GRUB 核心映像變數,包括磁區位置、磁區數目、核心映像記憶體節區。

diskboot.S
01  . = _start + 0x200 - GRUB_BOOT_MACHINE_LIST_SIZE
02 blocklist_default_start:
03  .long 2, 0
04 blocklist_default_len:
05  .word 0
06 blocklist_default_seg:
07  .word (GRUB_BOOT_MACHINE_KERNEL_SEG + 0x20)
08 firstlist:

行號說明
01設定程式碼位置在 512-12 的位址。
01磁區位置變數,八位元組。
01磁區數目變數,二位元組。
01核心映像記憶體節區變數,二位元組。