MIT 6.828 Lecture 2的preparation要求阅读《xv6 book》的附录部分,附录包括“PC Hardware”和“The Boot loader”两部分,并且在附录最后还有3道练习题。下面先解答3道练习题,再摘录附录中的一些知识点。

Exercise

问题1:为什么这样调用readseg不会出错?

  1. Due to sector granularity, the call to readseg in the text is equivalent to readseg((uchar*)0x100000, 0xb500, 0x1000). In practice, this sloppy behavior turns out not to be a problem Why doesn’t the sloppy readsect cause problems?

回答:首先我们使用gdb确认一下内核的程序段的数目、起始地址、长度等信息。在执行地址0x7d77的指令时,程序段的数目会被保存到esi寄存器中,设置断点并打印esi寄存器的值,发现为2,因此一共有两个程序段。

=> 0x7d77:	movzwl 0x1002c,%esi

Thread 1 hit Breakpoint 3, 0x00007d77 in ?? ()
1: /x $esp = 0x7be0
2: /x $esi = 0x0
3: /x $edi = 0x0
4: /x $ebx = 0x10034
(gdb) si
=> 0x7d7e: shl $0x5,%esi
0x00007d7e in ?? ()
1: /x $esp = 0x7be0
2: /x $esi = 0x2
3: /x $edi = 0x0
4: /x $ebx = 0x10034

在for循环中每次调用readseg的地方设置断点,并观察此时栈顶向上3个元素的值,即为3个输入参数的值。第一次调用时的栈中数据如下,可见是调用了readseg(0x100000, 0xa516, 0x1000)

(gdb) si
=> 0x7da0: call 0x7cf8
0x00007da0 in ?? ()
1: /x $edi = 0x100000
2: /x $ebx = 0x10034
3: /x $esi = 0x10074
4: $esp = (void *) 0x7bd4
(gdb) x/4xw 0x7bd4
0x7bd4: 0x00100000 0x0000a516 0x00001000 0x00000000

第二次调用时的栈中数据如下,可见是调用了readseg(0, 0, 0),这样进入readseg不会执行循环就返回,实际上相当于啥也没干。

(gdb) c
Continuing.
=> 0x7da0: call 0x7cf8 Thread 1 hit Breakpoint 4, 0x00007da0 in ?? ()
1: /x $esp = 0x7bd4
2: /x $esi = 0x10074
3: /x $edi = 0x0
4: /x $ebx = 0x10054
(gdb) x/4xw 0x7bd4
0x7bd4: 0x00000000 0x00000000 0x00000000 0x00000000

因此,加载内核的操作是readseg(0x100000, 0xa516, 0x1000),但是这为什么与readseg(0x100000, 0xb500, 0x1000)等价?尚未理解,有待研究。

问题2:修改加载地址后哪里会出错?

  1. Suppose you wanted bootmain() to load the kernel at 0x200000 instead of 0x100000, and you did so by modifying bootmain() to add 0x100000 to the va of each ELF section. Something would go wrong. What?

回答:不会做。。后面掌握更多知识后再回头做。

问题3:为什么不通过malloc来获取所需内存?

  1. It seems potentially dangerous for the boot loader to copy the ELF header to memory at the arbitrary location 0x10000. Why doesn’t it call malloc to obtain the memory it needs?

回答:按我的理解,malloc是C语言的库函数,需要依赖操作系统来实现,现在连内核都没加载,根本还用不了malloc函数。

摘录

  1. A computer’s CPU (central processing unit, or processor) runs a conceptually simple loop:

    • it consults an address in a register called the program counter,
    • reads a machine instruction from that address in memory, advances the program counter past the instruction, and executes the instruction.
    • Repeat.
    • If the execution of the instructiondoes not modify the program counter, this loop will interpret the memory pointed at by the program counter as a sequence of machine instructions to run one after theother.
    • Instructions that do change the program counter include branches and function calls.
  2. x86 register:

    • The modern x86 provides eight general purpose 32-bit registers—%eax, %ebx, %ecx, %edx, %edi, %esi, %ebp, and %esp—and a program counter %eip (the instruction pointer). The common e prefix stands for extended, as these are 32-bit extensions of the 16-bit registers %ax, %bx, %cx, %dx, %di, %si, %bp, %sp, and %ip.
    • The two register sets are aliased so that, for example, %ax is the bottom half of %eax: writing to %ax changes the value stored in %eax and vice versa.
    • The first four registers also have names for the bottom two 8-bit bytes: %al and %ah denote the low and high 8 bits of %ax; %bl, %bh, %cl, %ch, %dl, and %dh continue the pattern.
    • In addition to these registers, the x86 has eight 80-bit floating-point registers as well as a handful of special purpose registers like the control registers %cr0, %cr2, %cr3, and %cr4;
    • the debug registers %dr0, %dr1, %dr2, and %dr3;
    • the segment registers %cs, %ds, %es, %fs, %gs, and %ss;
    • and the global and local descriptor table pseudo-registers %gdtr and %ldtr.
    • The control registers and segment registers are important to any operating system. The floating-point and debug registers are less interesting and not used by xv6.
  3. modern x86 architectures use this technique, called memory-mapped I/O, for most high-speed devices such as network, disk, and graphics controllers.

  4. When an x86 PC boots,

    • it starts executing a program called the BIOS (Basic Input/Output System), which is stored in non-volatile memory on the motherboard. The BIOS’s job is to prepare the hardware and then transfer control to the operating system. Specifically, it transfers control to code loaded from the boot sector, the first 512-byte sector of the boot disk.
    • The boot sector contains the boot loader: instructions that load the kernel into memory. The BIOS loads the boot sector at memory address 0x7c00 and then jumps (sets the processor’s %ip) to that address.
    • When the boot loader begins executing, the processor is simulating an Intel 8088, and the loader’s job is to put the processor in a more modern operating mode, to load the xv6 kernel from disk into memory, and then to transfer control to the kernel.
  5. More commonly, kernels are stored in ordinary file systems, where they may not be contiguous, or are loaded over a network. These complications require the boot loader to be able to drive a variety of disk and network controllers and understand various file systems and network protocols. In other words, the boot loader itself must be a small operating system.

  6. Since such complicated boot loaders certainly won’t fit in 512 bytes, most PC operating systems use a two-step boot process.

    • First, a simple boot loader like the one in this appendix loads a full-featured boot-loader from a known disk location, often relying on the less space-constrained BIOS for disk access rather than trying to drive the disk itself.
    • Then the full loader, relieved of the 512-byte limit, can implement the complexity needed to locate, load, and execute the desired kernel.
  7. Modern PCs avoid many of the above complexities, because they support the Unified Extensible Firmware Interface (UEFI), which allows the PC to read a larger boot loader from the disk (and start it in protected and 32-bit mode).

  8. In fact the BIOS does a huge amount of initialization in order to make the complex hardware of a modern computer look like a traditional standard PC. The BIOS is really a small operating system embedded in the hardware, which is present after the computer has booted.

《xv6 Appendices: PC Hardware and Boot loader》学习笔记的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  4. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  5. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  6. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  7. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记

    今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...

  10. ucos实时操作系统学习笔记——任务间通信(消息)

    ucos另一种任务间通信的机制是消息(mbox),个人感觉是它是queue中只有一个信息的特殊情况,从代码中可以很清楚的看到,因为之前有关于queue的学习笔记,所以一并讲一下mbox.为什么有了qu ...

随机推荐

  1. 关系型数据库与NoSQL的对比

    SQL(结构化的查询语言)数据库是过去四十年间存储数据的主要方式.20世纪90年代末随着Web应用和MySQL.PostgreSQL和SQLite等开源数据库的兴起,用户爆炸式的增长. NoSQL数据 ...

  2. 046_Shell 脚本的 fork 炸弹

    #!/bin/bash#快速消耗计算机资源,致使计算机死机#定义函数名为.(点), 函数中递归调用自己并放入后台执行.() {.|.& };.

  3. F. Make Them Similar ( 暴力折半枚举 + 小技巧 )

    传送门 题意: 给你 n 个数 a[ 1 ]  ~ a[ n ], n <= 100: 让你找一个 x , 使得 a[ 1 ] = a[ 1 ] ^ x ~ a[ n ] = a[ n ] ^ ...

  4. Codeforces 1220 E Tourism

    题面 可以发现一个边双必然是可以随意走的,所以我们就把原图求割边然后把边双缩成一个点,然后就是一个树上dp了. #include<bits/stdc++.h> #define ll lon ...

  5. LibreOJ #6000. 「网络流 24 题」搭配飞行员

    二次联通门 : LibreOJ #6000. 「网络流 24 题」搭配飞行员 /* LibreOJ #6000. 「网络流 24 题」搭配飞行员 二分图最大匹配 Dinic最大流 + 当前弧优化 */ ...

  6. 自制 yum 源仓库

    转自:https://www.cnblogs.com/marility/p/7278374.html 背景 客户服务器为内网机器,centos7系统,且无法与外网连接.需要部署对应的LANMP环境及其 ...

  7. 7.27T2

    不可做题 sol:首先有个很显然的性质就是答案一定是在叶子上最优,然后画画图发现就是从最底层看,如果一条链就看做一个点,向上的第一颗非链的节点,它的儿子数-1就会对答案贡献,所有这样的累加起来就是答案 ...

  8. Mybatis 返回值 返回Map的为空的值

    第一种.springMVC和boot通用配置:(Mybatis.xml) <?xml version="1.0" encoding="UTF-8"?> ...

  9. Jmeter Web 性能测试入门 (七):Performance 测试中踩过 Jmeter 的坑

    脚本运行的过程中,大量request抛error,但没有地方能够查看request是因为什么error的. 原因:Jmeter默认禁掉了运行过程中每个request的具体response信息收集,只保 ...

  10. SQL中instr和like的使用区别

    1.instr函数 instr函数是一个字符串处理函数,它在Oracle/PLSQL中是返回子字符串在源字符串中的位置,如果在源串中没有找到子串,则返回0. instr函数定义如下: /* * 返回子 ...