lab 1

作者: ZoltanJin | 来源:发表于2018-03-13 20:38 被阅读0次
  • At what point does the processor start executing 32-bit code? What exactly causes the switch from 16- to 32-bit mode?

    当 CR0 中的 PE 位被置为 1 时进入 30-bit protected mode

  • What is the last instruction of the boot loader executed, and what is the first instruction of the kernel it just loaded?

    Last instruction of boot loader:

      ((void (*)(void)) (ELFHDR->e_entry))();
    

    First instruction of kernel:

      movl %cr4, %eax  
    
  • How does the boot loader decide how many sectors it must read in order to fetch the entire kernel from disk? Where does it find this information?

    boot/main.c 中,从 ELFHDR 中获得 sector 的数目并做相应循环。

  • Exercise 5

    Before boot loader:


    before.png

    After boot loader:


    after.png

    dump 出obj/kern/kernel 文件:


    objdump 结果

    可以发现 kernel 的 .text 段被加载到了 0x00100000 处。

Part 3: The kernel

  • kernel 被加载到 0xf0100000 的高地址(虚地址,kernel 认为自己被加载到),而实际上可能没有那么多物理地址,所以要做映射。事实上,kernel 的代码段被加载到 0x00100000(1MB)的地方。在本 lab 中,kern/entrypgdir.c 手动地将虚拟地址 0xf0000000~0xf04000000x00000000~0x004000000 都映射到物理地址 0x00000000~0x00400000
    在整个 JOS 的实现中,将实现物理地址的 0x00000000~0x0fffffff 到虚拟地址的 0xf0000000~0xffffffff (共 256M,JOS 只能使用物理地址地前 256M)。
  • Exercise 7.
  • Use QEMU and GDB to trace into the JOS kernel and find where the new virtual-to-physical mapping takes effect. Then examine the Global Descriptor Table (GDT) that the code uses to achieve this effect, and make sure you understand what's going on.
  • What is the first instruction after the new mapping is established that would fail to work properly if the old mapping were still in place? Comment out or otherwise intentionally break the segmentation setup code in kern/entry.S, trace into it, and see if you were right.

Formatted Printing to the console

  • Exercise 8

We have omitted a small fragment of code - the code necessary to print octal numbers using patterns of the form "%o". Find and fill in this code fragment. Remember the octal number should begin with '0'.

  case 'o':
        num = getuint(&ap, lflag);
        putch('0', putdat);
        base = 8;
        goto number;

其中 putch() 函数地功能是向终端输出一个 char 并将一个 counter 加一。模仿 case 'u' ,并依照要求提前输出一个 '0' 。

  • Exercise 9

You need also to add support for the "+" flag, which forces to precede the result with a plus or minus sign (+ or -) even for positive numbers.

// (signed) decimal
    case 'd':
        num = getint(&ap, lflag);
        if ((long long) num < 0) {
            putch('-', putdat);
            num = -(long long) num;
        }else if (plus){
            putch('+', putdat);
        }
        base = 10;              
        goto number;

主要修改了 case 'd' 代码段,因为只有 "%d" 涉及正负号。负的部分已经写好,plus 为一个记录正号出现的 flag,当 reswitch 的前一个循环读到了 '+' 符号,则把 plus 置为 1。

  • Explain the interface between printf.c and console.c. Specifically, what function does console.cexport? How is this function used by printf.c?
    printf.c calls function cputchar(int c) from console.c, and console.c calls function cprintf(const char *fmt, ...) defined by printf.c.

  • Explain the following from console.c:

      if (crt_pos >= CRT_SIZE) {
      int i;
      memmove(crt_buf, crt_buf + CRT_COLS, (CRT_SIZE - CRT_COLS) * sizeof(uint16_t));
      for (i = CRT_SIZE - CRT_COLS; i < CRT_SIZE; i++)
          crt_buf[i] = 0x0700 | ' ';
      crt_pos -= CRT_COLS;
      }
    

    如果屏幕满了则现有显示内容向上滚动一行。

  • Run the following code.

      unsigned int i = 0x00646c72;
      cprintf("H%x Wo%s", 57616, &i);
    

    What is the output?
    输出:He110 World

  • In the following code, what is going to be printed after 'y='? (note: the answer is not a specific value.) Why does this happen?
    答案不定,由于传参依靠的是 stack ,取当时 stack 上参数 3 再向上 4Byte 的值。

  • Exercise 10
    写一个辅助函数 printnumn ,这个函数做的事情大体和原来的 printnum 相同:递归地打印 num 的每一位,并在递归基处补足小数点后的 0(如果是小数的话)。但同时要记录一个 len 变量,表示打印了多少位。
    原来的 printnum 函数调用 printnumn 函数获得已打印的位数,在对比 width 参数补足后面的 padding。

  • Exercise 11
    Determine where the kernel initializes its stack, and exactly where in memory its stack is located. How does the kernel reserve space for its stack? And at which "end" of this reserved area is the stack pointer initialized to point to?
    浏览 /obj/kern/kernel.asm,发现 bootstacktop 的值为0x0f110000bc

  • Exercise 13\14
    首先在 monitor.c 中的 command list 中注册 backtrace 的指令。
    接着在 mon_backtrace 函数中写循环,循环的结束条件为 cur_ebp == 0,在每次循环中根据 cur_ebp 目前的值取得其他变量的值并格式化输出,每次循环结束时将 cur_ebp 做一次 dereference,并将新值赋给 cur_ebp 。
    通过阅读 kdebug.c 中的注释,补全缺的 eip_line 部分,然后在 mon_backtrace 函数中调用 debuginfo_eip 函数获取信息并格式化输出。

  • Exercise 15
    先在 monitor.h 中加上 mon_time 函数的声明,然后在 command list 中注册 time 的指令。
    接着定义 mon_time 函数,其中调用的辅助函数 read_cpu_cycle 使用嵌入汇编并加上 volatile 关键字执行 rdtsc 指令获取周期数。
    在两次调用 mon_time 函数中间执行命令行键入的指令,然后两个结果相减输出。

相关文章

网友评论

      本文标题:lab 1

      本文链接:https://www.haomeiwen.com/subject/jedtqftx.html