xv6/bootasm.S

 #include "asm.h"
#include "memlayout.h"
#include "mmu.h" # Start the first CPU: switch to -bit protected mode, jump into C.
# The BIOS loads this code from the first sector of the hard disk into
# memory at physical address 0x7c00 and starts executing in real mode
# with %cs= %ip=7c00. .code16 # Assemble for -bit mode
.globl start
start:
cli # BIOS enabled interrupts; disable # Zero data segment registers DS, ES, and SS.
xorw %ax,%ax # Set %ax to zero
movw %ax,%ds # -> Data Segment
movw %ax,%es # -> Extra Segment
movw %ax,%ss # -> Stack Segment # Physical address line A20 is tied to zero so that the first PCs
# with MB would run software that assumed MB. Undo that.
seta20.:
inb $0x64,%al # Wait for not busy
testb $0x2,%al
jnz seta20. movb $0xd1,%al # 0xd1 -> port 0x64
outb %al,$0x64 seta20.:
inb $0x64,%al # Wait for not busy
testb $0x2,%al
jnz seta20. movb $0xdf,%al # 0xdf -> port 0x60
outb %al,$0x60 # Switch from real to protected mode. Use a bootstrap GDT that makes
# virtual addresses map directly to physical addresses so that the
# effective memory map doesn’t change during the transition.
lgdt gdtdesc
movl %cr0, %eax
orl $CR0_PE, %eax
movl %eax, %cr0 # Complete transition to -bit protected mode by using long jmp
# to reload %cs and %eip. The segment descriptors are set up with no
# translation, so that the mapping is still the identity mapping.
ljmp $(SEG_KCODE<<), $start32 .code32 # Tell assembler to generate -bit code now.
start32:
# Set up the protected-mode data segment registers
movw $(SEG_KDATA<<), %ax # Our data segment selector
movw %ax, %ds # -> DS: Data Segment
movw %ax, %es # -> ES: Extra Segment
movw %ax, %ss # -> SS: Stack Segment
movw $, %ax # Zero segments not ready for use
movw %ax, %fs # -> FS
movw %ax, %gs # -> GS # Set up the stack pointer and call into C.
movl $start, %esp
call bootmain # If bootmain returns (it shouldn’t), trigger a Bochs
# breakpoint if running under Bochs, then loop.
movw $0x8a00, %ax # 0x8a00 -> port 0x8a00
movw %ax, %dx
outw %ax, %dx
movw $0x8ae0, %ax # 0x8ae0 -> port 0x8a00
outw %ax, %dx
spin:
jmp spin # Bootstrap GDT
.p2align # force byte alignment
gdt:
SEG_NULLASM # null seg
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg
SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg gdtdesc:
.word (gdtdesc - gdt - ) # sizeof(gdt) -
.long gdt # address gdt

xv6/bootmain.c

 // Boot loader.
//
// Part of the boot sector, along with bootasm.S, which calls bootmain().
// bootasm.S has put the processor into protected 32-bit mode.
// bootmain() loads an ELF kernel image from the disk starting at
// sector 1 and then jumps to the kernel entry routine. #include "types.h"
#include "elf.h"
#include "x86.h"
#include "memlayout.h" #define SECTSIZE 512 void readseg(uchar*, uint, uint); void
bootmain(void)
{
struct elfhdr *elf;
struct proghdr *ph, *eph;
void (*entry)(void);
uchar* pa; elf = (struct elfhdr*)0x10000; // scratch space // Read 1st page off disk
readseg((uchar*)elf, , ); // Is this an ELF executable?
if(elf->magic != ELF_MAGIC)
return; // let bootasm.S handle error // Load each program segment (ignores ph flags).
ph = (struct proghdr*)((uchar*)elf + elf->phoff);
eph = ph + elf->phnum;
for(; ph < eph; ph++){
pa = (uchar*)ph->paddr;
readseg(pa, ph->filesz, ph->off);
if(ph->memsz > ph->filesz)
stosb(pa + ph->filesz, , ph->memsz - ph->filesz);
} // Call the entry point from the ELF header.
// Does not return!
entry = (void(*)(void))(elf->entry);
entry();
} void
waitdisk(void)
{
// Wait for disk ready.
while((inb(0x1F7) & 0xC0) != 0x40)
;
} // Read a single sector at offset into dst.
void
readsect(void *dst, uint offset)
{
// Issue command.
waitdisk();
outb(0x1F2, ); // count = 1
outb(0x1F3, offset);
outb(0x1F4, offset >> );
outb(0x1F5, offset >> );
outb(0x1F6, (offset >> ) | 0xE0);
outb(0x1F7, 0x20); // cmd 0x20 - read sectors // Read data.
waitdisk();
insl(0x1F0, dst, SECTSIZE/);
} // Read ’count’ bytes at ’offset’ from kernel into physical address ’pa’.
// Might copy more than asked.
void
readseg(uchar* pa, uint count, uint offset)
{
uchar* epa; epa = pa + count; // Round down to sector boundary.
pa -= offset % SECTSIZE; // Translate from bytes to sectors; kernel starts at sector 1.
offset = (offset / SECTSIZE) + ; // 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(; pa < epa; pa += SECTSIZE, offset++)
readsect(pa, offset);
}

xv6/bootasm.S + xv6/bootmain.c的更多相关文章

  1. XV6源代码阅读-中断与系统调用

    Exercise1 源代码阅读 1.启动部分: bootasm.S bootmain.c 和xv6初始化模块:main.c bootasm.S 由16位和32位汇编混合编写成的XV6引导加载器.boo ...

  2. xv6 makefile

    1. xv6.img的构建 在makefile中 bootblock: bootasm.S bootmain.c $(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. - ...

  3. xv6的作业翻译——作业1 - shell和系统调用

    Xv6的lecture LEC 1 Operating systems   L1: O/S overview L1:O/S概述   * 6.828 goals 6.828的目标   Understan ...

  4. ubuntu编译运行xv6

    最近想找个简单的类Unix系统学习下, xv6不错的, 所有代码加起来不到一万行,首先把代码跑起来还是很重要的. # 下载xv6源码并编译 git clone git://pdos.csail.mit ...

  5. xv6 + Qemu 在Ubuntu下编译运行教程【转】

    转自:https://blog.csdn.net/yinglang19941010/article/details/49310111 如果想要离线看教程,可以下载该 文档 一.使用工具说明 1.    ...

  6. XV6操作系统代码阅读心得(三):锁

    锁是操作系统中实现进程同步的重要机制. 基本概念 临界区(Critical Section)是指对共享数据进行访问与操作的代码区域.所谓共享数据,就是可能有多个代码执行流并发地执行,并在执行中可能会同 ...

  7. XV6学习(2)Lab syscall

    实验的代码放在了Github上. 第二个实验是Lab: system calls. 这个实验主要就是自己实现几个简单的系统调用并添加到XV6中. XV6系统调用 添加系统调用主要有以下几步: 在use ...

  8. XV6学习(1) Lab util

    正在学习MIT的6.S081,把做的实验写一写吧. 实验的代码放在了Github上. 第一个实验是Lab util,算是一个热身的实验,没有涉及到系统的底层,就是使用系统调用来完成几个用户模式的小程序 ...

  9. lab 1实验报告

    练习1:理解通过make生成执行文件的过程. 1.操作系统镜像文件ucore.img是如何一步一步生成的? 生成 bin/kern 部分 生成 init.o 生成 readline.o 生成 stdi ...

随机推荐

  1. 【计算机网络】NAT:网络地址转换

    NAT(Network Address Translation,网络地址转换)是1994年提出的.当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但现在又想和因 ...

  2. npm 安装 不快的解决办法

    npm config list  查看配置 npm config set prefix “c:\dev\nvm\npm”(配置用npm下载包时全局安装的包路径) npm install npm -g ...

  3. FZU2128_最长子串

    题目说给你一个长串,要你选一个最长子串,不包括任何一个给定串为子串. 建立一个自动机,每个点保存的信息为当前这个状态为结尾最长可以有多长? 然后....就可以了... #include <ios ...

  4. BZOJ 1924 所驼门王的宝藏(强连通分量缩点+DAG最长链)

    思路不是很难,因为宝藏只会在给出的n个点内有,于是只需要在这n个点里面连边,一个点如果能到达另一个点则连一条有向边, 这样用强连通分量缩点后答案就是DAG的最长链. 问题在于暴力建图是O(n^2)的, ...

  5. Docker学习笔记五:Docker生成jenkins容器,支持Java Web项目持续集成、持续部署

    一.创建jenkins容器: 1.拉取jeknin镜像 sudo docker pull jenkins 2.创建一个jenkins目录 sudo mkdir /jenkins 3.在jenkins目 ...

  6. 【BZOJ3244】【NOI2013】树的计数(神仙题)

    [BZOJ3244][NOI2013]树的计数(神仙题) 题面 BZOJ 这题有点假,\(bzoj\)上如果要交的话请输出\(ans-0.001,ans,ans+0.001\) 题解 数的形态和编号没 ...

  7. POJ.3894 迷宫问题 (BFS+记录路径)

    POJ.3894 迷宫问题 (BFS+记录路径) 题意分析 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, ...

  8. bzoj5055: 膜法师(BIT)

    大水题WA了两发T T 记录一下a[i]的前缀和,a[i]*a[j]就是sigma(a[j]*sumi[j-1]) 记录一下a[i]*a[j]的前缀和,a[i]*a[j]*a[k]就是sigma(a[ ...

  9. Notes of fwt

    昨天考试由于不会fwt而爆炸,所以今天搞了一下fwt……话说这玩意的普及程度已经很高了.fwt,快速沃尔什变换,可以用于位运算卷积的优化,是一种线性变换,所以就会有许多好的性质(eg:可以直接模,可以 ...

  10. 学习 opencv---(12)OpenCV 图像金字塔:高斯金字塔,拉普拉斯金字塔与图片尺寸缩放

    在这篇文章里,我们一起学习下 图像金字塔 的一些基本概念,如何使用OpenCV函数pyrUp和pyrDown 对图像进行向上和向下采样,以及了解专门用于缩放图像尺寸的resize函数的用法.此博文一共 ...