### 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");
}