zoukankan      html  css  js  c++  java
  • Lab_1:练习2——使用qemu执行并调试lab1中的软件

     

    一、实验内容

    为了熟悉使用qemu和gdb进行的调试工作,我们进行如下的小练习:

    (一)从CPU加电后执行的第一条指令开始,单步跟踪BIOS的执行。

    (二)在初始化位置0x7c00设置实地址断点,测试断点正常。

    (三)从0x7c00开始跟踪代码运行,将单步跟踪反汇编得到的代码与bootasm.S和 bootblock.asm进行比较。

    (四)自己找一个bootloader或内核中的代码位置,设置断点并进行测试。

    二、实验步骤 

    补充材料:

    我们主要通过硬件模拟器qemu来进行各种实验。在实验的过程中我们可能会遇上各种各样的问题,调试是必要的。qemu支持使用gdb进行的强大而方便的调试。所以用好qemu和gdb是完成各种实验的基本要素

    默认的gdb需要进行一些额外的配置才进行qemu的调试任务。qemu和gdb之间使用网络端口1234进行通讯。在打开qemu进行模拟之后,执行gdb并输

    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或内核中的代码位置,设置断点并进行测试

     

      

  • 相关阅读:
    CAN总线学习资料
    VMware虚拟机 硬盘空间不足 磁盘大小调整方案
    郭天祥-S3C2440开发板Linux2.6.31移植教程
    MFC串口编程——使用标准SerialCom类
    Luogu P2602 [ZJOI2010]数字计数 //数位DP
    luogu P1896 [SCOI2005] 互不侵犯 //状压DP
    中北大学ACM 5/12 T6 CSY的幸福
    P2473 || SCOI2008 奖励关 //状压&&期望DP
    请让蝴蝶爬满全身
    【图论】二分图 // 未完成 =、=
  • 原文地址:https://www.cnblogs.com/cyx-b/p/11762551.html
Copyright © 2011-2022 走看看