教学文库网 - 权威文档分享云平台
您的当前位置:首页 > 精品文档 > 高等教育 >

ucore - LAB1实验报告(2)

来源:网络收集 时间:2026-09-10
导读: seta20.1: inb $0x64, %al # Wait for not busy testb $0x2, %al jnz seta20.1 movb $0xd1, %al # 0xd1 -> port 0x64 outb %al, $0x64 seta20.2: inb $0x64, %al # Wait for not busy testb $0x2, %al jnz seta20.2

seta20.1: inb $0x64, %al # Wait for not busy testb $0x2, %al jnz seta20.1 movb $0xd1, %al # 0xd1 -> port 0x64 outb %al, $0x64

seta20.2: inb $0x64, %al # Wait for not busy testb $0x2, %al jnz seta20.2 movb $0xdf, %al # 0xdf -> port 0x60 outb %al, $0x60 (4) lgdt gdtdesc //重新加载GDT表 movl %cr0, êx orl $CR0_PE_ON, êx //设置CR0寄存器PE位,PE位(第0位)是启用保护(Protection Enable)标志位。该位为0时为实地址模式,设置为1时开启保护模式,开启分页机制 movl êx, %cr0 ljmp $PROT_MODE_CSEG, $protcseg

(5)//进入32位模式,$PROT_MODE_CSEG表示段选择子,被加载到CS寄存器中,$protcseg被加载到IP寄存器中。CS、IP寄存器会重新加载,后面的代码都在32位保护模式下执行。

.code32 # Assemble for 32-bitmode protcseg:

//设置保护模式下的段寄存器

movw $PROT_MODE_DSEG, %ax # Our data segment lector movw %ax, %ds # -> DS: Data Segment movw %ax, %es # -> ES: Extra Segment movw %ax, %fs # -> FS movw %ax, %gs # -> GS

movw %ax, %ss # -> SS: Stack Segment //设置栈指针,程序跳转到0x7c00 movl $0x0, ?p movl $start, %esp

call bootmain

练习4:分析bootloader加载ELF格式的OS 1. bootloader如何读取硬盘扇区的?

答:读一个扇区的流程可参看bootmain.c 中的 readsect 函数实现。大致如下:

1. 读 I/O 地址 0x1f7,等待磁盘准备好;

2. 写 I/O 地址 0x1f2~0x1f5,0x1f7,发出读取第 offseet 个扇区处的磁盘数据的命令; 3. 读 I/O 地址 0x1f7,等待磁盘准备好;

4. 连续读 I/O 地址 0x1f0,把磁盘扇区数据读到指定内存。 /* readsect - read a single sector at @secno into @dst */ static void

readsect(void *dst, uint32_t secno) { // 第1步:等待硬盘准备好 waitdisk();

// 第2步:发出读取扇区的命令 outb(0x1F2, 1); // 读取一个扇区 outb(0x1F3, secno & 0xFF); // LBA参数的0~7位 outb(0x1F4, (secno >> 8) & 0xFF); // LBA参数的8~15位 outb(0x1F5, (secno >> 16) & 0xFF); // LBA参数的16~23位 outb(0x1F6, ((secno >> 24) & 0xF) | 0xE0); // LBA参数的24~27位 outb(0x1F7, 0x20); // 状态和命令寄存器。命令 0x20 - 读取扇区 // 第3步:等待硬盘准备好 waitdisk();

// 第4步:把磁盘扇区数据读取到指定内存 insl(0x1F0, dst, SECTSIZE / 4); }

2. bootloader是如何加载ELF格式的OS?

答:bootmain函数中完成加载ELF格式os的操作:

1: 读取ELF的头部

2: 判断ELF文件是否是合法 3: 将描述表的头地址存在ph

4: 按照描述表将ELF文件中数据载入内存

5: 根据ELF头部储存的入口信息,找到内核的入口(不再返回) 具体在bootmain.c的函数main()中实现: // 读取硬盘的第一页(载入kernel的文件头) readseg((uintptr_t)ELFHDR, SECTSIZE * 8, 0); // 判断是否为有效的ELF if (ELFHDR->e_magic != ELF_MAGIC) { goto bad; } struct proghdr *ph, *eph; // 从硬盘载入程序片段到内存(忽略ph标志) ph = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR->e_phoff); eph = ph + ELFHDR->e_phnum;

for (; ph < eph; ph ++) { readseg(ph->p_va & 0xFFFFFF, ph->p_memsz, ph->p_offset); }

// 从elf->entry为入口进入程序 // 注意:不返回

((void (*)(void))(ELFHDR->e_entry & 0xFFFFFF))();

练习5:实现函数调用堆栈跟踪函数 答:void print_stackframe(void{

uint32_t ebp = read_ebp(), eip = read_eip(); int i, j;

for (i = 0; ebp != 0 && i < STACKFRAME_DEPTH; i ++) { cprintf(\ uint32_t *args = (uint32_t *)ebp + 2; for (j = 0; j < 4; j ++) {

cprintf(\ }

cprintf(\

print_debuginfo(eip - 1); eip = ((uint32_t *)ebp)[1]; ebp = ((uint32_t *)ebp)[0]; …… 此处隐藏:475字,全部文档内容请下载后查看。喜欢就下载吧 ……

ucore - LAB1实验报告(2).doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.jiaowen.net/wendang/604851.html(转载请注明文章来源)
Copyright © 2020-2025 教文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:78024566 邮箱:78024566@qq.com
苏ICP备19068818号-2
Top
× 游客快捷下载通道(下载后可以自由复制和排版)
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能出现无法下载或内容有问题,请联系客服协助您处理。
× 常见问题(客服时间:周一到周五 9:30-18:00)