ucore lab1

ucore lab1

练习1:理解通过make生成执行文件的过程。(要求在报告中写出对下述问题的回答)

1 .操作系统镜像文件ucore.img是如何一步一步生成的?(需要比较详细地解释Makefile中每一条相关命令和命令参数的含义,以及说明命令导致的结果)
首先查看ucore.img生成规则,发现ucore.img生成依赖于kernel和bootblock
# create ucore.img
UCOREIMG	:= $(call totarget,ucore.img)$(UCOREIMG): $(kernel) $(bootblock)$(V)dd if=/dev/zero of=$@ count=10000$(V)dd if=$(bootblock) of=$@ conv=notrunc$(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc$(call create_target,ucore.img)

dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。$@是输出文件名

第一行dd:就是开辟一块存储区域大小为10000 * 512字节然后将/dev/zero (0)输入进去【初始化一块区域】

第二行dd:读取bootblock(512字节)内容然后输出到$@ 转换格式为 notrunc(不截短输出文件)

第三行dd:读取kernel内容然后输出到$@ 转换格式同上。 注意有偏移seek=1 偏移 1 * 512 位置

有关dd命令可以查看linux下的dd命令使用详解 - 知乎 (zhihu.com)

说白了就是弄一块磁盘区域来把kernel和bootblock按照头512字节是bootblock然后其次是kernel放进去,在模拟的时候这个文件要放到指定磁盘位置,然后BLOS启动时会读取磁盘上该文件的内容,bootblock作为bootloader引导代码然后加载kernel了

其次查看kernel生成规则
# create kernel target
kernel = $(call totarget,kernel)$(kernel): tools/kernel.ld$(kernel): $(KOBJS)@echo + ld $@$(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)@$(OBJDUMP) -S $@ > $(call asmfile,kernel)@$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)$(call create_target,kernel)

kernel赋值为"bin/kernel"

执行toos/kernel.ld链接脚本

编译kernel\下的所有.s和.c文件

然后看一下bootblock
# create bootblock
bootfiles = $(call listf_cc,boot)
$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))
#编译boot\下的所有C文件bootblock = $(call totarget,bootblock)$(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)@echo + ld $@$(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock)@$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)@$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)@$(call totarget,sign) $(call outfile,bootblock) $(bootblock)$(call create_target,bootblock)
#编译boot\下所有文件,并链接bootblock文件
# create 'sign' tools
$(call add_files_host,tools/sign.c,sign,sign)
$(call create_target_host,sign,sign)
#前面需要sign这个,这里就是编译,tools/sign.c并调用

发现前面都用到了$(call totarget,…) totarget定义在tools/function.mk

totarget = $(addprefix $(BINDIR)$(SLASH),$(1))
#BINDIR在别处定义为"bin",slash定义为斜线"/",$(1)指代输入参数
#所以totarget作用为给输入参数添加前缀"bin/"
2 一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?

阅读sign.c可知,大小小于512字节且以0X55AA结尾

练习3:分析bootloader进入保护模式的过程。

1 关闭中断,初始化寄存器为0
    cli                                             # Disable interruptscld                                             # String operations increment# Set up the important data segment registers (DS, ES, SS).xorw %ax, %ax                                   # Segment number zeromovw %ax, %ds                                   # -> Data Segmentmovw %ax, %es                                   # -> Extra Segmentmovw %ax, %ss                                   # -> Stack Segment
2 开启A20:

​ 为了兼容早期版本初始化时物理地址只能寻址20位也就是1M,所以要开启A20这样物理寻址就能达到32位也就是4G

3 同时载入全局描述表
    lgdt gdtdesc
4 进入保护模式,将cr0寄存器PE置1,开启保护模式
    movl %cr0, %eaxorl $CR0_PE_ON, %eaxmovl %eax, %cr0
5 通过长跳转更新cs的基地址
	ljmp $PROT_MODE_CSEG, $protcseg
6 设置段寄存器,建立堆栈
7 转到保护模式完成,call进入bootmain
	call bootmain

练习4:分析bootloader加载ELF格式的OS的过程。

先从磁盘开始处读取了1页(8个扇区,每个512byte)的数据到内存64K处,再校验头部标识符是否合法.
接着从磁盘中读取每个程序段,并放到虚拟内存对应位置.
最后执行ELF入口程序,将控制权交给kernel

练习5:实现函数调用堆栈跟踪函数 (需要编程)

考察的是对EBP寄存器的运用.几乎所有本地编译器都会在每个函数体之前插入类似如下的汇编指令:

pushl %ebp
movl %esp,%ebp

这两条汇编指令的含义是:首先将ebp寄存器入栈,然后将栈顶指针esp赋值给ebp。“mov ebp esp”这条指令表面上看是用esp覆盖ebp原来的值,其实不然。因为给ebp赋值之前,原ebp值已经被压栈(位于栈顶),而新的ebp又恰恰指向栈顶。此时ebp寄存器就已经处于一个非常重要的地位,该寄存器中存储着栈中的一个地址(原ebp入栈后的栈顶),从该地址为基准,向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取函数局部变量值,而该地址处又存储着上一层函数调用时的ebp值。

一般而言,ss:[ebp+4]处为返回地址,ss:[ebp+8]处为第一个参数值(最后一个入栈的参数值,此处假设其占用4字节内存),ss:[ebp-4]处为第一个局部变量,ss:[ebp]处为上一层ebp值。由于ebp中的地址处总是“上一层函数调用时的ebp值”,而在每一层函数调用中,都能通过当时的ebp值“向上(栈底方向)”能获取返回地址、参数值,“向下(栈顶方向)”能获取函数局部变量值。如此形成递归,直至到达栈底。这就是函数调用栈。

由文档给出的不难理解,双层循环内层循环复则打印,外层循环复则查看堆栈调用,关键代码如下:

        eip = ((uint32_t *)ebp)[1];ebp = ((uint32_t *)ebp)[0];

练习6:完善中断初始化和处理

1 中断描述符表(也可简称为保护模式下的中断向量表)中一个表项占多少字节?其中哪几位代表中断处理代码的入口?
/* Gate descriptors for interrupts and traps */
struct gatedesc {unsigned gd_off_15_0 : 16;        // low 16 bits of offset in segmentunsigned gd_ss : 16;            // segment selectorunsigned gd_args : 5;            // # args, 0 for interrupt/trap gatesunsigned gd_rsv1 : 3;            // reserved(should be zero I guess)unsigned gd_type : 4;            // type(STS_{TG,IG32,TG32})unsigned gd_s : 1;                // must be 0 (system)unsigned gd_dpl : 2;            // descriptor(meaning new) privilege levelunsigned gd_p : 1;                // Presentunsigned gd_off_31_16 : 16;        // high bits of offset in segment
};

可以看出一个表项为8字节(64位)其中0 ~ 15位和48 ~ 63位分别为偏移量的低16位和高16位,两者拼接为偏移量,16~31位为段选择器。通过段选择子去GDT中找到对应的基地址,然后基地址加上偏移量就是中断处理程序的地址。

2 请编程完善kern/trap/trap.c中对中断向量表进行初始化的函数idt_init。在idt_init函数中,依次对所有中断入口进行初始化。使用mmu.h中的SETGATE宏,填充idt数组内容。每个中断的入口由tools/vectors.c生成,使用trap.c中声明的vectors数组即可
    extern uintptr_t __vectors[];int i ;for( i = 0; i < sizeof(idt) / sizeof(struct gatedesc); i++ ){SETGATE(idt[i] , 0 , GD_KTEXT , __vectors[i]  ,  DPL_KERNEL );}/*** 【注意】除了系统调用中断(T_SYSCALL)使用陷阱门描述符且权限为用户态权限以外* ,其它中断均使用特权级(DPL)为0的中断门描述符,权限为内核态权限;而ucore的* 应用程序处于特权级3,需要采用`int 0x80`指令操作(这种方式称为软中断,软件* 中断,Tra中断,在lab5会碰到)来发出系统调用请求,并要能实现从特权级3到特权* 级0的转换,所以系统调用中断(T_SYSCALL)所对应的中断门描述符中的特权级(DPL)* 需要设置为3。*/SETGATE(idt[T_SYSCALL] , 1 , GD_KTEXT , __vectors[T_SYSCALL] , DPL_USER);// this is different than  answerlidt(&idt_pd);

就是找一些宏去填就行了,找宏很麻烦,其他还好

3 请编程完善trap.c中的中断处理函数trap,在对时钟中断进行处理的部分填写trap函数中处理时钟中断的部分,使操作系统每遇到100次时钟中断后,调用print_ticks子程序,向屏幕上打印一行文字”100 ticks”。

Too Simple? Yes, I think so!

      /* LAB1 YOUR CODE : STEP 3 *//* handle the timer interrupt *//* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c* (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().* (3) Too Simple? Yes, I think so!*/ticks++;if(ticks % TICK_NUM  == 0){print_ticks();}break;
整体流程完成后就可以看到大约一秒会打印一个ticks,还能获取到键盘响应

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/3494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

left join 和except方法区别和联系

目录 相同点&#xff1a; left join except 不同点 假设有两个表&#xff1a;A客户表 和 B客户表&#xff0c;客户uid是唯一主键 相同点&#xff1a; 查询在A中的客户 但不在B中&#xff0c;也就是图中的阴影部分&#xff0c;left join 和except方法都可以实现 left join …

使用IDEA社区版创建SpringBoot项目

文章目录 1.关于IDEA社区版的版本2.下载Spring Boot Helper3.创建项目4.配置Maven国内源4.1找不到settings.xml的情况4.2找得到settings.xml的情况 4.3删除repository目录下的所有文件和目录5.加载项目6.解决org.springframework.boot:spring-boot-starter-parent:pom:2.7.13.R…

laravel 的SQL使用正则匹配

案例场景 精准正则匹配 查询结果 代码如下 $regexp ^ . $new_str . [^0-9];$info Test::query()->where(is_del, 0)->whereRaw("name REGEXP $regexp")->pluck(name, id)->toArray();字符 “^” 匹配以特定字符或者字符串开头的文本 name 字段值包含…

记一次搞崩ubuntu系统的经历

本来想在ubuntu系统上安装一个windows系统&#xff0c;没想成在对磁盘进行分区的时候出错了&#xff0c;导致进入了grub模型&#xff0c;一直出不来&#xff0c; 过程中一些很好的链接放上来哈 市面上很少有的基于linux系统安装另外一个系统的&#xff08;感觉是非常靠谱的&…

php做网页版剪刀石头布的功能

实例讲述了php实现的网页版剪刀石头布攻略在玩游网上的设计。分享给大家供大家参考&#xff0c;具体如下&#xff1a; <?php /* * Created on 2016-11-25 * */ if (isset($_POST[sub])) { $what $_POST[what]; //需要输入的数组 $my_array array("剪刀","…

数据可视化揭示人口趋势:从数字到图像的转变

人口是一个关乎我们生活的重要话题&#xff0c;而数据可视化技术为我们提供了一种全新的方式来理解和解读人口变化的趋势。通过将大量的人口数据转化为直观的图表和图像&#xff0c;数据可视化帮助我们更好地观察、分析和解释人类发展的重要特征。 数据可视化揭示人口趋势的第一…

Spring @RequestMapping 工作原理

Spring RequestMapping 工作原理 配置基础启动类及Controller类 SpringBootApplication public class DemoServiceApplication {public static void main(String[] args) {SpringApplication.run(DemoServiceApplication.class, args);} }RestController public class HelloC…

SQLite指令

一、创建数据库 方式一&#xff1a; 1. sqlite3 进入数据库 2. .open test.db 3. .quit 数据库退出后在命令当前路径创建数据库 test.db 方式二&#xff1a; sqlite3 test.db // 在命令运行当前窗口创建数据库 test.db 在数据库命令下 .databases // 列出…

【YOLO】自定义训练数据(roboflow版)

YOLOv5自定义训练数据(roboflow版) 上一章 yolov5部署与推理 文章目录 YOLOv5自定义训练数据(roboflow版)前言一、Roboflow1. 数据标注2. 创建训练模型3. 划分数据集4.数据预处理5. 生成最终预训练数据集6.开始训练7. 选择预训练模型8. 可视化9. 推理10. 如何加载其他预训…

自动驾驶商用驶入“快车道”,汽车软件厂商如何“抢市”?

L3级及以上自动驾驶的商业化进程正在驶入“快车道”。 一方面&#xff0c;高阶自动驾驶的相关法规及标准不断出台&#xff0c;为自动驾驶行业的发展注入了“强心剂”。 比如工业和信息化部副部长辛国斌就曾表示&#xff0c;将启动智能网联汽车准入和上路通行试点&#xff0c;…

SQL实践语句:筛选表中异常数据!关键词:EXISTS

语句示例 SELECT COUNT(1) FROM(SELECT T.CUSTOMERCODE,T.CUSTOMERNAME,T.RECSTS,T.INDATTRODE,T.COUNTRYCODE,T.SAFECODE,T.REGIONCODE,T.ECONTYPECODEFROM WHJH.TBL_CODECUSTOMER_NEW T WHERET.BATCHNO>(SELECT BATCHNO FROM WHJH.TBL DATAFILE_MAKE_BATCHNO) -6 ) A WHE…

【云原生】k8s之包管理器Helm

前言 每个成功的软件平台都有一个优秀的打包系统&#xff0c;比如Debian、Ubuntu 的 apt&#xff0c;RedHat、CentOS 的 yum。Helm 则是 Kubernetes上 的包管理器&#xff0c;方便我们更好的管理应用。 1.Helm的相关知识 1.1 Helm的简介与了解 Helm本质就是让K8s的应用管理&…

PostgreSQL 的就业前景如何?

PostgreSQL的就业前景非常广阔&#xff0c;它是一种功能强大、可靠且开源的关系型数据库管理系统。以下是说明PostgreSQL就业前景的几个关键点&#xff1a; 1.高需求&#xff1a;随着企业和组织对数据存储和管理的需求不断增长&#xff0c;对数据库专业人员的需求也在持续上升…

Python 算法基础篇之数组和列表:创建、访问、添加和删除元素

Python 算法基础篇之数组和列表&#xff1a;创建、访问、添加和删除元素 引用 1. 数组的概念和创建2. 列表的概念和创建3. 访问数组和列表中的元素4. 添加和删除元素 a ) 添加元素 b ) 删除元素 总结 引用 在算法和数据结构中&#xff0c;数组和列表是常见的数据结构&#xff…

使用matlab给信号添加某一信噪比的噪声

在MATLAB中&#xff0c;你可以使用awgn函数给信号添加高斯白噪声来实现给矩阵信号添加特定信噪比的噪声&#xff0c;并使用plot函数可视化添加噪声前后的信号。以下是示例代码&#xff1a; % 创建原始信号 Fs 1000; % 采样率 t 0:1/Fs:1-1/Fs; % 时间轴 signal sin(2*pi*…

Tomcat工作原理

一、Tomcat架构 ### 说明&#xff1a; Server&#xff1a;表示整个 Tomcat Catalina servlet 容器&#xff0c;Server 中可以有多个 Service。&#xff08;可以通过telenet 8005后连接后输入“SHUTDOWN” 注意这里是大写&#xff0c;来关闭服务&#xff09;Service&#xff1…

Microsoft Update Assistant导致 MAC 电脑内存占用过高解决方案

目录 问题: 排查原因: 解决方案: 问题: 一直很苦恼,每次开机隔会发下电脑内存就 100%了,这次找了下原因,也记录下. 排查原因: 通过 mac 自带的活动监视器,发现居然是Microsoft Update Assistant它导致的 解决方案: 那这样就简单了,这个应该是 word,execl 的一个自动更新程序…

Spring 事务控制

1. 编程式事务控制相关对象 1.1 平台事务管理器 1.2 事务定义对象 1.3 事务状态对象 关系&#xff1a; PlatformTransactionManager TransactionManager TransactionStatus 2. 基于XML的声明式事务控制 切点&#xff1a;&#xff08;目标对象&#xff09;业务方法&#xff…

微派前端一面

1.挑一个你在项目中遇到比较有挑战的问题&#xff0c;如何去解决的 2.开发小程序的过程&#xff0c;有没有遇到一些性能问题或技术问题 3.最近关注哪些技术社区的动态&#xff0c;哪些技术的发展 这边我自己回答了tsvue3&#xff0c;小程序的taro 4.vue3相对于vue2升级了哪些…

OpenCv之Canny

目录 一、自适应阈值 二、边缘检测Canny 一、自适应阈值 引入前提:在前面的部分我们使用是全局闻值&#xff0c;整幅图像采用同一个数作为闻值。当时这种方法并不适应与所有情况&#xff0c;尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应闻…