Lab_1:練習2——使用qemu執行並調試lab1中的軟件

 

1、實驗內容bootstrap

爲了熟悉使用qemu和gdb進行的調試工做,咱們進行以下的小練習:vim

(一)從CPU加電後執行的第一條指令開始,單步跟蹤BIOS的執行。sass

(二)在初始化位置0x7c00設置實地址斷點,測試斷點正常。網絡

(三)從0x7c00開始跟蹤代碼運行,將單步跟蹤反彙編獲得的代碼與bootasm.S和 bootblock.asm進行比較。ide

(四)本身找一個bootloader或內核中的代碼位置,設置斷點並進行測試。oop

2、實驗步驟 測試

補充材料:ui

咱們主要經過硬件模擬器qemu來進行各類實驗。在實驗的過程當中咱們可能會趕上各類各樣的問題,調試是必要的。qemu支持使用gdb進行的強大而方便的調試。因此用好qemu和gdb是完成各類實驗的基本要素this

默認的gdb須要進行一些額外的配置才進行qemu的調試任務。qemu和gdb之間使用網絡端口1234進行通信。在打開qemu進行模擬以後,執行gdb並輸spa

target remote :1234

便可鏈接qemu,此時qemu會進入中止狀態,遵從gdb的命令

另外,咱們可能須要qemu在一開始便進入等待模式,則咱們再也不使用make qemu開始系統的運行,而使用make debug來完成這項工做。這樣qemu便不會在gdb還沒有鏈接的時候擅自運行了。

gdb的地址斷點

在gdb命令行中,使用b *[地址]即可以在指定內存地址設置斷點,當qemu中的cpu執行到指定地址時,便會將控制權交給gdb。

 

(一)從CPU加電後執行的第一條指令開始,單步跟蹤BIOS的執行

1.修改gdbinit文件

首先,在 /moocos/ucore_lab/labcodes_answer/lab1_result/tools  目錄下,修改gdbinit文件

進入目錄:

cd ./moocos/ucore_lab/labcodes_answer/lab1_result/tools

修改方法爲:

輸入vim gdbinit

用D刪除gdbinit中原有的內容(D爲刪除整行,x或X爲刪除單個字符)

 

將如下內容粘貼入gdbinit中

 

set architecture i8086
target remote :1234 

 

 

2.make debug

輸入cd ..,退回到./moocos/ucore_lab/labcodes_answer/lab1_result

輸入make debug

隨後執行make debug,將彈出gdb窗口,如圖所示:

在gdb窗口中使用si命令便可單步追蹤

(注意:你沒必要每次輸入si,輸入一次si後,只要按回車便可執行上次的指令)

在gdb界面下,可經過以下命令來看BIOS的代碼

x /2i $pc(顯示當前eip處的彙編指令)

 

 (二)在初始化位置0x7c00設置實地址斷點,測試斷點正常。

1.修改gdbinit文件

進入目錄:

cd ./moocos/ucore_lab/labcodes_answer/lab1_result/tools

修改方法與(一)相同,

修改的內容以下:

target remote :1234     //鏈接qemu,此時qemu會進入中止狀態,遵從gdb的命令
set architecture i8086  //設置當前調試的CPU是8086
b *0x7c00   //在0x7c00處設置斷點。此地址是bootloader入口點地址,可看boot/bootasm.S的start地址處
c     //continue簡稱,表示繼續執行
x/10i $pc    //顯示當前eip處的彙編指令

 

 

2.make debug 

輸入cd ..,退回到./moocos/ucore_lab/labcodes_answer/lab1_result

輸入make debug

 

(三)從0x7c00開始跟蹤代碼運行,將單步跟蹤反彙編獲得的代碼與bootasm.S和 bootblock.asm進行比較

 bootasm.S的完整代碼爲:

 1 #include <asm.h>
 2 
 3 # Start the CPU: switch to 32-bit protected mode, jump into C.  4 # The BIOS loads this code from the first sector of the hard disk into  5 # memory at physical address 0x7c00 and starts executing in real mode  6 # with %cs=0 %ip=7c00.  7 
 8 .set PROT_MODE_CSEG,        0x8 # kernel code segment selector  9 .set PROT_MODE_DSEG,        0x10 # kernel data segment selector 10 .set CR0_PE_ON,             0x1                     # protected mode enable flag 11 
12 # start address should be 0:7c00, in real mode, the beginning address of the running bootloader 13 .globl start 14 start: 15 .code16                                             # Assemble for 16-bit mode 16  cli # Disable interrupts 17  cld # String operations increment 18 
19  # Set up the important data segment registers (DS, ES, SS). 20     xorw %ax, %ax # Segment number zero 21     movw %ax, %ds                                   # -> Data Segment 22     movw %ax, %es                                   # -> Extra Segment 23     movw %ax, %ss                                   # -> Stack Segment 24 
25  # Enable A20: 26  # For backwards compatibility with the earliest PCs, physical 27     #  address line 20 is tied low, so that addresses higher than 28     #  1MB wrap around to zero by default. This code undoes this. 29 seta20.1: 30     inb $0x64, %al                                  # Wait for not busy(8042 input buffer empty). 31     testb $0x2, %al 32     jnz seta20.1
33 
34     movb $0xd1, %al                                 # 0xd1 -> port 0x64
35     outb %al, $0x64                                 # 0xd1 means: write data to 8042's P2 port
36 
37 seta20.2: 38     inb $0x64, %al                                  # Wait for not busy(8042 input buffer empty). 39     testb $0x2, %al 40     jnz seta20.2
41 
42     movb $0xdf, %al                                 # 0xdf -> port 0x60
43     outb %al, $0x60                                 # 0xdf = 11011111, means set P2's A20 bit(the 1 bit) to 1
44 
45     # Switch from real to protected mode, using a bootstrap GDT 46     # and segment translation that makes virtual addresses 47  # identical to physical addresses, so that the 48     # effective memory map does not change during the switch. 49  lgdt gdtdesc 50     movl %cr0, %eax 51     orl $CR0_PE_ON, %eax 52     movl %eax, %cr0 53 
54     # Jump to next instruction, but in 32-bit code segment. 55     # Switches processor into 32-bit mode. 56  ljmp $PROT_MODE_CSEG, $protcseg 57 
58 .code32                                             # Assemble for 32-bit mode 59 protcseg: 60     # Set up the protected-mode data segment registers 61     movw $PROT_MODE_DSEG, %ax # Our data segment selector 62     movw %ax, %ds                                   # -> DS: Data Segment 63     movw %ax, %es                                   # -> ES: Extra Segment 64     movw %ax, %fs                                   # -> FS 65     movw %ax, %gs                                   # -> GS 66     movw %ax, %ss                                   # -> SS: Stack Segment 67 
68     # Set up the stack pointer and call into C. The stack region is from 0--start(0x7c00) 69     movl $0x0, %ebp 70     movl $start, %esp 71  call bootmain 72 
73     # If bootmain returns (it shouldn't), loop.
74 spin: 75  jmp spin 76 
77 # Bootstrap GDT 78 .p2align 2                                          # force 4 byte alignment 79 gdt: 80     SEG_NULLASM                                     # null seg 81     SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)           # code seg for bootloader and kernel 82     SEG_ASM(STA_W, 0x0, 0xffffffff)                 # data seg for bootloader and kernel 83 
84 gdtdesc: 85     .word 0x17                                      # sizeof(gdt) - 1
86     .long gdt                                       # address gdt
bootasm.S

 

 bootblock.asm的完整代碼爲:

 1 obj/bootblock.o:     file format elf32-i386  2 
 3 
 4 Disassembly of section .text:  5 
 6 00007c00 <start>:  7 
 8 # start address should be 0:7c00, in real mode, the beginning address of the running bootloader  9 .globl start  10 start:  11 .code16                                             # Assemble for 16-bit mode  12  cli # Disable interrupts  13  7c00: fa cli  14  cld # String operations increment  15  7c01: fc cld  16 
 17  # Set up the important data segment registers (DS, ES, SS).  18     xorw %ax, %ax # Segment number zero  19     7c02:    31 c0                    xor    %eax,%eax  20     movw %ax, %ds                                   # -> Data Segment  21     7c04:    8e d8                    mov    %eax,%ds  22     movw %ax, %es                                   # -> Extra Segment  23     7c06:    8e c0                    mov    %eax,%es  24     movw %ax, %ss                                   # -> Stack Segment  25     7c08:    8e d0                    mov    %eax,%ss  26 
 27 00007c0a <seta20.1>:  28  # Enable A20:  29  # For backwards compatibility with the earliest PCs, physical  30     #  address line 20 is tied low, so that addresses higher than  31     #  1MB wrap around to zero by default. This code undoes this.  32 seta20.1:  33     inb $0x64, %al                                  # Wait for not busy(8042 input buffer empty).  34     7c0a:    e4 64                    in     $0x64,%al  35     testb $0x2, %al  36     7c0c:    a8 02                    test   $0x2,%al  37     jnz seta20.1
 38     7c0e:    75 fa                    jne    7c0a <seta20.1>
 39 
 40     movb $0xd1, %al                                 # 0xd1 -> port 0x64
 41     7c10:    b0 d1                    mov    $0xd1,%al  42     outb %al, $0x64                                 # 0xd1 means: write data to 8042's P2 port
 43     7c12:    e6 64                    out    %al,$0x64
 44 
 45 00007c14 <seta20.2>:  46 
 47 seta20.2:  48     inb $0x64, %al                                  # Wait for not busy(8042 input buffer empty).  49     7c14:    e4 64                    in     $0x64,%al  50     testb $0x2, %al  51     7c16:    a8 02                    test   $0x2,%al  52     jnz seta20.2
 53     7c18:    75 fa                    jne    7c14 <seta20.2>
 54 
 55     movb $0xdf, %al                                 # 0xdf -> port 0x60
 56     7c1a:    b0 df                    mov    $0xdf,%al  57     outb %al, $0x60                                 # 0xdf = 11011111, means set P2's A20 bit(the 1 bit) to 1
 58     7c1c:    e6 60                    out    %al,$0x60
 59 
 60     # Switch from real to protected mode, using a bootstrap GDT  61     # and segment translation that makes virtual addresses  62  # identical to physical addresses, so that the  63     # effective memory map does not change during the switch.  64  lgdt gdtdesc  65     7c1e:    0f 01 16                 lgdtl  (%esi)  66     7c21:    6c                       insb   (%dx),%es:(%edi)  67     7c22:    7c 0f                    jl     7c33 <protcseg+0x1>
 68     movl %cr0, %eax  69     7c24:    20 c0                    and    %al,%al  70     orl $CR0_PE_ON, %eax  71     7c26:    66 83 c8 01              or     $0x1,%ax  72     movl %eax, %cr0  73     7c2a:    0f 22 c0                 mov    %eax,%cr0  74 
 75     # Jump to next instruction, but in 32-bit code segment.  76     # Switches processor into 32-bit mode.  77  ljmp $PROT_MODE_CSEG, $protcseg  78     7c2d:    ea 32 7c 08 00 66 b8     ljmp   $0xb866,$0x87c32
 79 
 80 00007c32 <protcseg>:  81 
 82 .code32                                             # Assemble for 32-bit mode  83 protcseg:  84     # Set up the protected-mode data segment registers  85     movw $PROT_MODE_DSEG, %ax # Our data segment selector  86     7c32:    66 b8 10 00              mov    $0x10,%ax  87     movw %ax, %ds                                   # -> DS: Data Segment  88     7c36:    8e d8                    mov    %eax,%ds  89     movw %ax, %es                                   # -> ES: Extra Segment  90     7c38:    8e c0                    mov    %eax,%es  91     movw %ax, %fs                                   # -> FS  92     7c3a:    8e e0                    mov    %eax,%fs  93     movw %ax, %gs                                   # -> GS  94     7c3c:    8e e8                    mov    %eax,%gs  95     movw %ax, %ss                                   # -> SS: Stack Segment  96     7c3e:    8e d0                    mov    %eax,%ss  97 
 98     # Set up the stack pointer and call into C. The stack region is from 0--start(0x7c00)  99     movl $0x0, %ebp 100     7c40:    bd 00 00 00 00           mov    $0x0,%ebp 101     movl $start, %esp 102     7c45:    bc 00 7c 00 00           mov    $0x7c00,%esp 103  call bootmain 104     7c4a:    e8 b1 00 00 00           call   7d00 <bootmain>
105 
106 00007c4f <spin>: 107 
108     # If bootmain returns (it shouldn't), loop.
109 spin: 110  jmp spin 111     7c4f:    eb fe                    jmp    7c4f <spin>
112     7c51:    8d 76 00                 lea    0x0(%esi),%esi 113 
114 00007c54 <gdt>: 115  ... 116  7c5c: ff (bad) 117     7c5d:    ff 00                    incl   (%eax) 118     7c5f:    00 00                    add    %al,(%eax) 119     7c61:    9a cf 00 ff ff 00 00     lcall  $0x0,$0xffff00cf
120     7c68:    00 92 cf 00 17 00        add    %dl,0x1700cf(%edx) 121 
122 00007c6c <gdtdesc>: 123     7c6c:    17                       pop    %ss 124     7c6d:    00 54 7c 00              add    %dl,0x0(%esp,%edi,2) 125  ... 126 
127 00007c72 <readseg>: 128 /* * 129  * readseg - read @count bytes at @offset from kernel into virtual address @va, 130  * might copy more than asked. 131  * */
132 static void
133 readseg(uintptr_t va, uint32_t count, uint32_t offset) { 134     7c72:    55                       push   %ebp 135     7c73:    89 e5                    mov    %esp,%ebp 136     7c75:    57                       push   %edi 137     7c76:    56                       push   %esi 138     7c77:    89 c6                    mov    %eax,%esi 139     7c79:    53                       push   %ebx 140     uintptr_t end_va = va + count; 141     7c7a:    8d 04 10                 lea    (%eax,%edx,1),%eax 142 
143     // round down to sector boundary
144     va -= offset % SECTSIZE; 145     7c7d:    31 d2                    xor    %edx,%edx 146 /* * 147  * readseg - read @count bytes at @offset from kernel into virtual address @va, 148  * might copy more than asked. 149  * */
150 static void
151 readseg(uintptr_t va, uint32_t count, uint32_t offset) { 152     7c7f:    53                       push   %ebx 153     uintptr_t end_va = va + count; 154     7c80:    89 45 f0                 mov    %eax,-0x10(%ebp) 155 
156     // round down to sector boundary
157     va -= offset % SECTSIZE; 158     7c83:    89 c8                    mov    %ecx,%eax 159     7c85:    f7 35 e4 7d 00 00        divl   0x7de4
160     7c8b:    29 d6                    sub    %edx,%esi 161 
162     // translate from bytes to sectors; kernel starts at sector 1
163     uint32_t secno = (offset / SECTSIZE) + 1; 164     7c8d:    8d 58 01                 lea    0x1(%eax),%ebx 165 
166     // If this is too slow, we could read lots of sectors at a time. 167     // We'd write more to memory than asked, but it doesn't matter -- 168     // we load in increasing order.
169     for (; va < end_va; va += SECTSIZE, secno ++) { 170     7c90:    3b 75 f0                 cmp    -0x10(%ebp),%esi 171     7c93:    73 65                    jae    7cfa <readseg+0x88>
172 static inline void ltr(uint16_t sel) __attribute__((always_inline)); 173 
174 static inline uint8_t 175 inb(uint16_t port) { 176  uint8_t data; 177     asm volatile ("inb %1, %0" : "=a" (data) : "d" (port)); 178     7c95:    ba f7 01 00 00           mov    $0x1f7,%edx 179     7c9a:    ec                       in     (%dx),%al 180 struct elfhdr * ELFHDR    =      ((struct elfhdr *)0x10000) ;     // scratch space
181 
182 /* waitdisk - wait for disk ready */
183 static void
184 waitdisk(void) { 185     while ((inb(0x1F7) & 0xC0) != 0x40) 186     7c9b:    83 e0 c0                 and    $0xffffffc0,%eax 187     7c9e:    3c 40                    cmp    $0x40,%al 188     7ca0:    75 f3                    jne    7c95 <readseg+0x23>
189             : "memory", "cc"); 190 } 191 
192 static inline void
193 outb(uint16_t port, uint8_t data) { 194     asm volatile ("outb %0, %1" :: "a" (data), "d" (port)); 195     7ca2:    b2 f2                    mov    $0xf2,%dl 196     7ca4:    b0 01                    mov    $0x1,%al 197     7ca6:    ee                       out    %al,(%dx) 198     7ca7:    0f b6 c3                 movzbl %bl,%eax 199     7caa:    b2 f3                    mov    $0xf3,%dl 200     7cac:    ee                       out    %al,(%dx) 201     7cad:    0f b6 c7                 movzbl %bh,%eax 202     7cb0:    b2 f4                    mov    $0xf4,%dl 203     7cb2:    ee                       out    %al,(%dx) 204  waitdisk(); 205 
206     outb(0x1F2, 1);                         // count = 1
207     outb(0x1F3, secno & 0xFF); 208     outb(0x1F4, (secno >> 8) & 0xFF); 209     outb(0x1F5, (secno >> 16) & 0xFF); 210     7cb3:    89 d8                    mov    %ebx,%eax 211     7cb5:    b2 f5                    mov    $0xf5,%dl 212     7cb7:    c1 e8 10                 shr    $0x10,%eax 213     7cba:    0f b6 c0                 movzbl %al,%eax 214     7cbd:    ee                       out    %al,(%dx) 215     outb(0x1F6, ((secno >> 24) & 0xF) | 0xE0); 216     7cbe:    89 d8                    mov    %ebx,%eax 217     7cc0:    b2 f6                    mov    $0xf6,%dl 218     7cc2:    c1 e8 18                 shr    $0x18,%eax 219     7cc5:    83 e0 0f                 and    $0xf,%eax 220     7cc8:    83 c8 e0                 or     $0xffffffe0,%eax 221     7ccb:    ee                       out    %al,(%dx) 222     7ccc:    b0 20                    mov    $0x20,%al 223     7cce:    b2 f7                    mov    $0xf7,%dl 224     7cd0:    ee                       out    %al,(%dx) 225 static inline void ltr(uint16_t sel) __attribute__((always_inline)); 226 
227 static inline uint8_t 228 inb(uint16_t port) { 229  uint8_t data; 230     asm volatile ("inb %1, %0" : "=a" (data) : "d" (port)); 231     7cd1:    ba f7 01 00 00           mov    $0x1f7,%edx 232     7cd6:    ec                       in     (%dx),%al 233 struct elfhdr * ELFHDR    =      ((struct elfhdr *)0x10000) ;     // scratch space
234 
235 /* waitdisk - wait for disk ready */
236 static void
237 waitdisk(void) { 238     while ((inb(0x1F7) & 0xC0) != 0x40) 239     7cd7:    83 e0 c0                 and    $0xffffffc0,%eax 240     7cda:    3c 40                    cmp    $0x40,%al 241     7cdc:    75 f3                    jne    7cd1 <readseg+0x5f>
242 
243     // wait for disk to be ready
244  waitdisk(); 245 
246     // read a sector
247     insl(0x1F0, dst, SECTSIZE / 4); 248     7cde:    8b 0d e4 7d 00 00        mov    0x7de4,%ecx 249     return data; 250 } 251 
252 static inline void
253 insl(uint32_t port, void *addr, int cnt) { 254     asm volatile ( 255     7ce4:    89 f7                    mov    %esi,%edi 256     7ce6:    ba f0 01 00 00           mov    $0x1f0,%edx 257     7ceb:    c1 e9 02                 shr    $0x2,%ecx 258  7cee: fc cld 259     7cef:    f2 6d                    repnz insl (%dx),%es:(%edi) 260     uint32_t secno = (offset / SECTSIZE) + 1; 261 
262     // If this is too slow, we could read lots of sectors at a time. 263     // We'd write more to memory than asked, but it doesn't matter -- 264     // we load in increasing order.
265     for (; va < end_va; va += SECTSIZE, secno ++) { 266     7cf1:    03 35 e4 7d 00 00        add    0x7de4,%esi 267     7cf7:    43                       inc    %ebx 268     7cf8:    eb 96                    jmp    7c90 <readseg+0x1e>
269         readsect((void *)va, secno); 270  } 271 } 272     7cfa:    58                       pop    %eax 273     7cfb:    5b                       pop    %ebx 274     7cfc:    5e                       pop    %esi 275     7cfd:    5f                       pop    %edi 276     7cfe:    5d                       pop    %ebp 277  7cff: c3 ret 278 
279 00007d00 <bootmain>: 280 
281 /* bootmain - the entry of bootloader */
282 void
283 bootmain(void) { 284     // read the 1st page off disk
285     readseg((uintptr_t)ELFHDR, SECTSIZE * 8, 0); 286     7d00:    a1 e4 7d 00 00           mov    0x7de4,%eax 287     7d05:    31 c9                    xor    %ecx,%ecx 288  } 289 } 290 
291 /* bootmain - the entry of bootloader */
292 void
293 bootmain(void) { 294     7d07:    55                       push   %ebp 295     7d08:    89 e5                    mov    %esp,%ebp 296     7d0a:    56                       push   %esi 297     // read the 1st page off disk
298     readseg((uintptr_t)ELFHDR, SECTSIZE * 8, 0); 299     7d0b:    8d 14 c5 00 00 00 00     lea    0x0(,%eax,8),%edx 300     7d12:    a1 e0 7d 00 00           mov    0x7de0,%eax 301  } 302 } 303 
304 /* bootmain - the entry of bootloader */
305 void
306 bootmain(void) { 307     7d17:    53                       push   %ebx 308     // read the 1st page off disk
309     readseg((uintptr_t)ELFHDR, SECTSIZE * 8, 0); 310     7d18:    e8 55 ff ff ff           call   7c72 <readseg>
311 
312     // is this a valid ELF?
313     if (ELFHDR->e_magic != ELF_MAGIC) { 314     7d1d:    a1 e0 7d 00 00           mov    0x7de0,%eax 315     7d22:    81 38 7f 45 4c 46        cmpl   $0x464c457f,(%eax) 316     7d28:    75 3a                    jne    7d64 <bootmain+0x64>
317  } 318 
319     struct proghdr *ph, *eph; 320 
321     // load each program segment (ignores ph flags)
322     ph = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR->e_phoff); 323     7d2a:    8b 58 1c                 mov    0x1c(%eax),%ebx 324     7d2d:    01 c3                    add    %eax,%ebx 325     eph = ph + ELFHDR->e_phnum; 326     7d2f:    0f b7 40 2c              movzwl 0x2c(%eax),%eax 327     7d33:    c1 e0 05                 shl    $0x5,%eax 328     7d36:    8d 34 03                 lea    (%ebx,%eax,1),%esi 329     for (; ph < eph; ph ++) { 330     7d39:    39 f3                    cmp    %esi,%ebx 331     7d3b:    73 18                    jae    7d55 <bootmain+0x55>
332         readseg(ph->p_va & 0xFFFFFF, ph->p_memsz, ph->p_offset); 333     7d3d:    8b 43 08                 mov    0x8(%ebx),%eax 334     struct proghdr *ph, *eph; 335 
336     // load each program segment (ignores ph flags)
337     ph = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR->e_phoff); 338     eph = ph + ELFHDR->e_phnum; 339     for (; ph < eph; ph ++) { 340     7d40:    83 c3 20                 add    $0x20,%ebx 341         readseg(ph->p_va & 0xFFFFFF, ph->p_memsz, ph->p_offset); 342     7d43:    8b 4b e4                 mov    -0x1c(%ebx),%ecx 343     7d46:    8b 53 f4                 mov    -0xc(%ebx),%edx 344     7d49:    25 ff ff ff 00           and    $0xffffff,%eax 345     7d4e:    e8 1f ff ff ff           call   7c72 <readseg>
346     7d53:    eb e4                    jmp    7d39 <bootmain+0x39>
347  } 348 
349     // call the entry point from the ELF header 350     // note: does not return
351     ((void (*)(void))(ELFHDR->e_entry & 0xFFFFFF))(); 352     7d55:    a1 e0 7d 00 00           mov    0x7de0,%eax 353     7d5a:    8b 40 18                 mov    0x18(%eax),%eax 354     7d5d:    25 ff ff ff 00           and    $0xffffff,%eax 355     7d62:    ff d0                    call   *%eax 356     asm volatile ("outb %0, %1" :: "a" (data), "d" (port)); 357 } 358 
359 static inline void
360 outw(uint16_t port, uint16_t data) { 361     asm volatile ("outw %0, %1" :: "a" (data), "d" (port)); 362     7d64:    b8 00 8a ff ff           mov    $0xffff8a00,%eax 363     7d69:    89 c2                    mov    %eax,%edx 364     7d6b:    66 ef                    out    %ax,(%dx) 365     7d6d:    b8 00 8e ff ff           mov    $0xffff8e00,%eax 366     7d72:    66 ef                    out    %ax,(%dx) 367     7d74:    eb fe                    jmp    7d74 <bootmain+0x74>
bootblock.asm

 反彙編獲得的代碼是:

 

下圖是bootasm.S中14到28行的代碼:

下面是bootblock.asm中10到25行的代碼

 

比較可知,三者基本一致。

 

(四)本身找一個bootloader或內核中的代碼位置,設置斷點並進行測試

相關文章
相關標籤/搜索