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. 获取http和ftp地址的图片

    根据http和ftp图片地址获取对应图片的缩略图和原图 public class GetBitmapImageClass { public BitmapSource GetImageHttp(stri ...

  2. [AT2363] [agc012_c] Tautonym Puzzle

    题目链接 AtCoder:https://agc012.contest.atcoder.jp/tasks/agc012_c 洛谷:https://www.luogu.org/problemnew/sh ...

  3. 从块级元素和行内元素的分析到bfc的布局理解

    接口和属性介绍 播放器提供了progressMakers属性,是一个数组类型,每一条记录包含offset时间和text打点的内容,还可以包含其他属性,此属性用于告诉播放器进度条打点记录,记录内容属性说 ...

  4. MySQL中文全文检索demoSQL

    一.概述      MySQL全文检索是利用查询关键字和查询列内容之间的相关度进行检索,可以利用全文索引来提高匹配的速度. 二.语法      MATCH (col1,col2,...) AGAINS ...

  5. python基础(4)

    条件判断和循环 条件判断 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现: age = 20 if ag ...

  6. bzoj2296: 【POJ Challenge】随机种子(思维题/水题)

    有点类似CF某场div2T1... 前面接上1234567890000000,后面加上x+(1234567890000000%x)就可以保证是x的倍数了 #include<iostream> ...

  7. 【CF113D】Museum

    Portal --> cf113D Solution 额题意的话大概就是给一个无向图然后两个人给两个出发点,每个点每分钟有\(p[i]\)的概率停留,问这两个人在每个点相遇的概率是多少 如果说我 ...

  8. git 列出两个 commit 之间变更的文件列表

    git diff <commit1> <commit2> --stat 如: git diff 74ecf17dc 1ee25ed3c --stat src/assets 上面 ...

  9. chrome插件控制台

    在manifest.json中添加下面的几行 "background": { "scripts": ["background.js"] }, ...

  10. web系统中上下移动功能的实现

    其实上移下移的思想分几步: 核心思想:交换两个记录的位置字段的值. 问题:如何根据当前记录,找到前一个或者后一个的记录的位置. 第一:在java类属性定义一个position位置字段,不同的位置pos ...