lab1_练习4(bootmain.c载入os)

### boot/bootmain.c   bootmain
=> 0x7d10 <bootmain>:	push   %ebp
   0x7d11 <bootmain+1>:	mov    0x7df0,%eax	# eax = SECTSIZE
   0x7d16 <bootmain+6>:	xor    %ecx,%ecx	# ecx = 0 = offset
   0x7d18 <bootmain+8>:	lea    0x0(,%eax,8),%edx	# edx = SECTSIZE * 8  count
   0x7d1f <bootmain+15>:	mov    0x7dec,%eax	# eax = ELFHDR 
   0x7d24 <bootmain+20>:	mov    %esp,%ebp
   0x7d26 <bootmain+22>:	push   %esi
   0x7d27 <bootmain+23>:	push   %ebx
   0x7d28 <bootmain+24>:	call   0x7c72 <readseg>
   0x7d2d <bootmain+29>:	mov    0x7dec,%eax
   0x7d32 <bootmain+34>:	cmpl   $0x464c457f,(%eax)
   0x7d38 <bootmain+40>:	jne    0x7d73 <bootmain+99>
   0x7d3a <bootmain+42>:	mov    0x1c(%eax),%ebx	# ebx = ELFHDR->e_phoff
   0x7d3d <bootmain+45>:	movzwl 0x2c(%eax),%esi	# esi = e_phnum
   0x7d41 <bootmain+49>:	add    %eax,%ebx	# ebx = (uintptr_t)ELFHDR + ELFHDR->e_phoff = ph
   0x7d43 <bootmain+51>:	shl    $0x5,%esi	# esi = e_phnum * sizeof(proghdr)
   0x7d46 <bootmain+54>:	add    %ebx,%esi	# esi = ph + ELFHDR->e_phnum
   0x7d48 <bootmain+56>:	cmp    %esi,%ebx
   0x7d4a <bootmain+58>:	jae    0x7d64 <bootmain+84>
   0x7d4c <bootmain+60>:	mov    0x8(%ebx),%eax
   0x7d4f <bootmain+63>:	mov    0x4(%ebx),%ecx
   0x7d52 <bootmain+66>:	add    $0x20,%ebx
   0x7d55 <bootmain+69>:	mov    -0xc(%ebx),%edx
   0x7d58 <bootmain+72>:	and    $0xffffff,%eax
   0x7d5d <bootmain+77>:	call   0x7c72 <readseg>
   0x7d62 <bootmain+82>:	jmp    0x7d48 <bootmain+56>
   0x7d64 <bootmain+84>:	mov    0x7dec,%eax
   0x7d69 <bootmain+89>:	mov    0x18(%eax),%eax
   0x7d6c <bootmain+92>:	and    $0xffffff,%eax
   0x7d71 <bootmain+97>:	call   *%eax
   0x7d73 <bootmain+99>:	mov    $0xffff8a00,%edx
   0x7d78 <bootmain+104>:	mov    %edx,%eax
   0x7d7a <bootmain+106>:	out    %ax,(%dx)
   0x7d7c <bootmain+108>:	mov    $0xffff8e00,%eax
   0x7d81 <bootmain+113>:	out    %ax,(%dx)
   0x7d83 <bootmain+115>:	jmp    0x7d83 <bootmain+115>


### boot/bootmain.c   readseg

   0x7c72 <readseg>:	push   %ebp
   0x7c73 <readseg+1>:	mov    %esp,%ebp
=> 0x7c75 <readseg+3>:	push   %edi
   0x7c76 <readseg+4>:	push   %esi
   0x7c77 <readseg+5>:	push   %ebx
   0x7c78 <readseg+6>:	push   %ebx
   0x7c79 <readseg+7>:	mov    %eax,%ebx	# ebx = ELFHDR   va
   0x7c7b <readseg+9>:	mov    %ecx,%eax	# eax = ecx
   0x7c7d <readseg+11>:	lea    (%ebx,%edx,1),%edi	# edi = ebx + edx = va + count
   0x7c80 <readseg+14>:	xor    %edx,%edx	# edx = 0	# prepare for divl
   0x7c82 <readseg+16>:	mov    %edi,-0x10(%ebp)	# edi -> sp
   0x7c85 <readseg+19>:	divl   0x7df0		# eax = offset  ->  eax = offset / SECTSIZE
   0x7c8b <readseg+25>:	sub    %edx,%ebx	# ebx -= offset % SECTSIZE
   0x7c8d <readseg+27>:	lea    0x1(%eax),%esi	# esi = eax + 1 = secno
   0x7c90 <readseg+30>:	cmp    -0x10(%ebp),%ebx	# ebx = end_va
   0x7c93 <readseg+33>:	jae    0x7d0a <readseg+152>
   0x7c95 <readseg+35>:	mov    $0x1f7,%edx
   0x7c9a <readseg+40>:	in     (%dx),%al
   0x7c9b <readseg+41>:	and    $0xffffffc0,%eax



//一个扇区512字节
unsigned int    SECTSIZE  =      512 ;
//读取ELF header到虚拟地址0x10000    由于代码段数据段的base都为0 虚拟地址直接映射至线性地址
struct elfhdr * ELFHDR    =      ((struct elfhdr *)0x10000) ;     // scratch space


/* *
 * readseg - read @count bytes at @offset from kernel into virtual address @va,
 * might copy more than asked.
 * */
static void
readseg(uintptr_t va, uint32_t count, uint32_t offset) {
    uintptr_t end_va = va + count;

    // round down to sector boundary
    va -= offset % SECTSIZE;

    // translate from bytes to sectors; kernel starts at sector 1
    uint32_t secno = (offset / SECTSIZE) + 1;

    // If this is too slow, we could read lots of sectors at a time.
    // We'd write more to memory than asked, but it doesn't matter --
    // we load in increasing order.
    for (; va < end_va; va += SECTSIZE, secno ++) {
        readsect((void *)va, secno);
    }
}


void
bootmain(void) {
    // read the 1st page off disk
    //从ucore内核镜像 偏移为0处读入一页 至0x10000  读入ELF header和program header table
    readseg((uintptr_t)ELFHDR, SECTSIZE * 8, 0);

    // is this a valid ELF?
    if (ELFHDR->e_magic != ELF_MAGIC) {
        goto bad;
    }

    struct proghdr *ph, *eph;

    // load each program segment (ignores ph flags)
    //ph: 首个program header地址
    ph = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR->e_phoff);
    //phnum = 4 

    //eph:program header table 上界
    eph = ph + ELFHDR->e_phnum;

    //读入程序段
    for (; ph < eph; ph ++) {
        readseg(ph->p_va & 0xFFFFFF, ph->p_memsz, ph->p_offset);
    }

    // call the entry point from the ELF header
    // note: does not return
    ((void (*)(void))(ELFHDR->e_entry & 0xFFFFFF))();

bad:
    outw(0x8A00, 0x8A00);
    outw(0x8A00, 0x8E00);

    /* do nothing */
    while (1);
}


// libs/x86.h
//从给定端口读取指定数量的数据块 long为单位
static inline void
insl(uint32_t port, void *addr, int cnt) {
    asm volatile (
            "cld;"
            "repne; insl;"
            : "=D" (addr), "=c" (cnt)
            : "d" (port), "0" (addr), "1" (cnt)
            : "memory", "cc");
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值