操作系统真象还原实验记录之实验十二:实现ASSERT
操作系统真象还原实验记录之实验十二:实现ASSERT,通过makefile完成编译
对应书P367 第8.2节
1.相关基础知识
见书
2.实验代码
完成了开关中断函数。实现assert断言函数用于调式程序,编写makefile简化编译
2.1 interrupt.c
增加的代码
#define EFLAGS_IF 0x00000200 // eflags寄存器中的if位为1
#define GET_EFLAGS(EFLAG_VAR) asm volatile("pushfl; popl %0" : "=g" (EFLAG_VAR))/* 开中断并返回开中断前的状态*/
enum intr_status intr_enable() {enum intr_status old_status;if (INTR_ON == intr_get_status()) {old_status = INTR_ON;return old_status;} else {old_status = INTR_OFF;asm volatile("sti"); // 开中断,sti指令将IF位置1return old_status;}
}/* 关中断,并且返回关中断前的状态 */
enum intr_status intr_disable() { enum intr_status old_status;if (INTR_ON == intr_get_status()) {old_status = INTR_ON;asm volatile("cli" : : : "memory"); // 关中断,cli指令将IF位置0return old_status;} else {old_status = INTR_OFF;return old_status;}
}/* 将中断状态设置为status */
enum intr_status intr_set_status(enum intr_status status) {return status & INTR_ON ? intr_enable() : intr_disable();
}/* 获取当前中断状态 */
enum intr_status intr_get_status() {uint32_t eflags = 0; GET_EFLAGS(eflags);return (EFLAGS_IF & eflags) ? INTR_ON : INTR_OFF;
}
intr_enable() 用于开中断
2.2 interrupt.h
#ifndef __KERNEL_INTERRUPT_H
#define __KERNEL_INTERRUPT_H
#include "stdint.h"
typedef void* intr_handler;
void idt_init(void);/* 定义中断的两种状态:* INTR_OFF值为0,表示关中断,* INTR_ON值为1,表示开中断 */
enum intr_status { // 中断状态INTR_OFF, // 中断关闭INTR_ON // 中断打开
};enum intr_status intr_get_status(void);
enum intr_status intr_set_status (enum intr_status);
enum intr_status intr_enable (void);
enum intr_status intr_disable (void);
void register_handler(uint8_t vector_no, intr_handler function);
#endif
2.3 debug.h
#ifndef __KERNEL_DEBUG_H
#define __KERNEL_DEBUG_H
void panic_spin(char* filename, int line, const char* func, const char* condition);/*************************** __VA_ARGS__ ******************************** __VA_ARGS__ 是预处理器所支持的专用标识符。* 代表所有与省略号相对应的参数. * "..."表示定义的宏其参数可变.*/
#define PANIC(...) panic_spin (__FILE__, __LINE__, __func__, __VA_ARGS__)/***********************************************************************/#ifdef NDEBUG#define ASSERT(CONDITION) ((void)0)
#else#define ASSERT(CONDITION) \if (CONDITION) {} else { \/* 符号#让编译器将宏的参数转化为字符串字面量 */ \PANIC(#CONDITION); \}
#endif /*__NDEBUG */#endif /*__KERNEL_DEBUG_H*/
PANIC(…)表示函数panic_spin参数可变,__VA_ARGS__代表所有可变参数
宏毕竟是一段代码,调用宏越多的地方,程序体积就越大,为了方便调试,这个宏ASSERT将会频繁出现在我们操作系统的各个角落。
当我们不再需要调试的时候,就应该可以手动取消这些宏;
预处理指令#ifdef,他的意思是,如果定义了宏NDEBUG,就使ASSERT等于0空值。
也就是说,定义宏NDEBUG是一个开关,掌握着ASSERT宏是否有效。
gcc -D NDEBUG就可以定义这个宏,但是一般-D NDEBUG写在makefile中
2.4 debug.c
#include "debug.h"
#include "print.h"
#include "interrupt.h"/* 打印文件名,行号,函数名,条件并使程序悬停 */
void panic_spin(char* filename, \int line, \const char* func, \const char* condition) \
{intr_disable(); // 因为有时候会单独调用panic_spin,所以在此处关中断。put_str("\n\n\n!!!!! error !!!!!\n");put_str("filename:");put_str(filename);put_str("\n");put_str("line:0x");put_int(line);put_str("\n");put_str("function:");put_str((char*)func);put_str("\n");put_str("condition:");put_str((char*)condition);put_str("\n");while(1);
}
2.5 main.c
#include "print.h"
#include "init.h"
#include "debug.h"int main(void) {put_str("I am kernel\n");init_all();
// asm volatile("sti"); //临时开中断ASSERT(1==2);while(1);return 0;
}
总结:
- ASSERT(1==2); 调用ASSERT函数
- ASSERT函数,调用PANIC(#CONDITION)函数;
- PANIC(…) panic_spin (FILE, LINE, func, VA_ARGS)前三个参数固定,第四个参数由#CONDITION转化为字符串传入,__VA_ARGS__接收
- panic_spin函数实行关中断并且打印错误“1==2”。
2.6 makefile
BUILD_DIR = ./build
ENTRY_POINT = 0xc0001500
AS = nasm
CC = gcc
LD = ld
LIB = -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/
ASFLAGS = -f elf
CFLAGS = -Wall -m32 -fno-stack-protector $(LIB) -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes
LDFLAGS = -m elf_i386 -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_DIR)/kernel.map
OBJS = $(BUILD_DIR)/main.o $(BUILD_DIR)/init.o $(BUILD_DIR)/interrupt.o \$(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/print.o \$(BUILD_DIR)/debug.o
############## c代码编译 ###############
$(BUILD_DIR)/main.o: kernel/main.c lib/kernel/print.h \lib/stdint.h kernel/init.h$(CC) $(CFLAGS) $< -o $@$(BUILD_DIR)/init.o: kernel/init.c kernel/init.h lib/kernel/print.h \lib/stdint.h kernel/interrupt.h device/timer.h$(CC) $(CFLAGS) $< -o $@$(BUILD_DIR)/interrupt.o: kernel/interrupt.c kernel/interrupt.h \lib/stdint.h kernel/global.h lib/kernel/io.h lib/kernel/print.h$(CC) $(CFLAGS) $< -o $@$(BUILD_DIR)/timer.o: device/timer.c device/timer.h lib/stdint.h\lib/kernel/io.h lib/kernel/print.h$(CC) $(CFLAGS) $< -o $@$(BUILD_DIR)/debug.o: kernel/debug.c kernel/debug.h \lib/kernel/print.h lib/stdint.h kernel/interrupt.h$(CC) $(CFLAGS) $< -o $@############## 汇编代码编译 ###############
$(BUILD_DIR)/kernel.o: kernel/kernel.S$(AS) $(ASFLAGS) $< -o $@$(BUILD_DIR)/print.o: lib/kernel/print.S$(AS) $(ASFLAGS) $< -o $@############## 链接所有目标文件 #############
$(BUILD_DIR)/kernel.bin: $(OBJS)$(LD) $(LDFLAGS) $^ -o $@.PHONY : mk_dir hd clean allmk_dir:if [ ! -d $(BUILD_DIR) ]; then mkdir $(BUILD_DIR); fihd:dd if=$(BUILD_DIR)/kernel.bin \of=hd60M.img \bs=512 count=200 seek=9 conv=notruncclean:cd $(BUILD_DIR) && rm -f ./*build: $(BUILD_DIR)/kernel.binall: mk_dir build hd
makefile相当于一种脚本语言文件,必须遵循make定义的语法
而make相当于脚本解析器
make和makefile的本质是,make通过解析makefile文件,找出哪些文件有变化,根据依赖关系找出受变化影响的文件,然后将找出所有的文件执行事先在makefile定义好的命令规则。
格式:
目标文件:依赖文件
[TAB]命令
命令的行首必须以TAB开头。
$(BUILD_DIR)/main.o: kernel/main.c lib/kernel/print.h
lib/stdint.h kernel/init.h
$(CC) $(CFLAGS) $< -o $@
上述命令:
目标文件main.o依赖于main.c、print.h、stdint.h、int.h
依赖文件中main.c的mtime比main.o的mtime更新(或目标文件main.o不存在)
所以执行下列命令
$< :表示依赖文件中的第一个文件 也就是main.c
$@:表示所有目标文件的集合
$^:该规则中所有依赖文件集合
这个命令规则表示会重新编译生成目标文件main.o
运行make all 会递归执行所有命令
再举一个例子
若发现依赖文件有但是不存在,则递归找以该不存在依赖文件为目标文件的规则解析。
若发现依赖文件没有,则直接执行命令。
伪目标
上述概念和伪目标不同
clean后面没有依赖文件,则直接执行命令。上述是依赖文件不存在,则递归解析其他。有区别
3.效果图
3.1一句make all 完成编译到刻入磁盘
make all
3.2运行bochs
./bochs -f bochsrc.disk
操作系统真象还原实验记录之实验十二:实现ASSERT相关推荐
- 《操作系统真象还原》从零开始自制操作系统 全流程记录
文章目录 前引 章节博客链接 实现源码链接 前引 这本<操作系统真象还原>里面一共有十五个章节 大约760页 这些系列博客也是我在做完哈工大操作系统Lab之后 觉得还是有些朦朦胧胧 毅然决 ...
- 操作系统真象还原实验记录之实验三十四:实现管道
操作系统真象还原实验记录之实验三十四:实现管道 1.管道相关知识总结 先说我们操作系统的管道实现: 上述图中,管道缓冲区就是一页内存,这一页内存被我们当成了环形缓冲区结构, 当这页管道被创建出来后,全 ...
- 操作系统真象还原实验记录之实验十一:实现中断处理(二)
操作系统真象还原实验记录之实验十一:实现中断处理(二) 书p335 7.6.2 改进中断处理程序,并调快时钟 1.实验代码第一次修改 对应 书p335 7.6.2 改进中断处理程序 这次是上一次实验的 ...
- 操作系统真象还原实验记录之实验七:加载内核
操作系统真象还原实验记录之实验七:加载内核 对应书P207 1.相关基础知识总结 1.1 elf格式 1.1.1 c程序如何转化成elf格式 写好main.c的源程序 //main.c int mai ...
- 操作系统真象还原实验记录之实验六:内存分页
操作系统真象还原实验记录之实验五:内存分页 对应书P199页 5.2 1.相关基础知识总结 页目录 页目录项 页表 页表项 物理页 虚拟地址 物理地址 概念略 页目录项及页表项 低12位都是属性.高2 ...
- 操作系统真象还原实验记录之实验一:第一次编写mbr
操作系统真象还原之实验一:第一次编写mbr 对应书中第2.3节:让mbr飞一会 第58页 1.相关基础知识提炼总结 1.1电脑开机前与后 在电脑未开机前,BIOS就被事先写入到内存的F0000~FFF ...
- 操作系统真象还原实验记录之实验二十三:硬盘分区,并编写硬盘驱动程序
操作系统真象还原实验记录之实验二十三:编写硬盘驱动程序 1.硬盘分区 1.1 创建Seven80.img硬盘 ./bximage -mode=create -imgmode=flat -hd=80 - ...
- 《操作系统真象还原》1-3章 学习记录
文章目录 前言 一.开始实验前的一些基本问题解答? section的含义? vstart的含义? $ 和 $$区别? 实模式的特点? CPU如何和硬盘进行交互? CPU和IO设备交互方式? 程序载入内 ...
- 《操作系统真象还原》第十四章 ---- 实现文件系统 任务繁多 饭得一口口吃路得一步步走啊(上一)
文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 部分缩写熟知 闲聊时刻 实现文件系统的原理 inode构建原理 目录构建原理 超级块构建思路 创建文件系统 编写完的super_block.h ...
最新文章
- win7 IIS7.5 HTTP 错误 404.17 - Not Found 请求的内容似乎是脚本,因而将无法由静态...
- redis -memcahe-mongo资料-windows定时重启计划
- Kaggle : Using a Convolutional Neural Network for classifying Cats vs Dogs
- fenby C语言 P30
- python 简单web音频_Python Twisted web服务器音频fi
- C++安全方向(二):2.4 openssl_BIO接口解析
- js学习(node.js环境)
- jQueryMobile新版中导航栏按钮消失的解决方法
- C#关键字operator
- 【数学模型】TOPSIS
- P-6002-10PK,P-6002-2PK脂质研究工具解析
- UnityShader 浮雕凹凸贴图BumpMap与法线贴图NormalMap的原理及其区别
- 风变编程python基础语法-第0关-千寻的名字
- 树状数组的理解以及简单应用
- 黑苹果鼠标不动_MacOS系统:解决黑果睡眠唤醒后假死问题(如键盘鼠标无反应等)...
- pyspider 文档介绍
- 禁止win10自动更新_一键禁止WIN10自动更新!
- 计算机的输入输出设备
- python问题:IndentationError:expected an indented blo
- 区块链在物联网中的应用