操作系统真象还原实验记录之实验十二:实现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;
}

总结:

  1. ASSERT(1==2); 调用ASSERT函数
  2. ASSERT函数,调用PANIC(#CONDITION)函数;
  3. PANIC(…) panic_spin (FILE, LINE, func, VA_ARGS)前三个参数固定,第四个参数由#CONDITION转化为字符串传入,__VA_ARGS__接收
  4. 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相关推荐

  1. 《操作系统真象还原》从零开始自制操作系统 全流程记录

    文章目录 前引 章节博客链接 实现源码链接 前引 这本<操作系统真象还原>里面一共有十五个章节 大约760页 这些系列博客也是我在做完哈工大操作系统Lab之后 觉得还是有些朦朦胧胧 毅然决 ...

  2. 操作系统真象还原实验记录之实验三十四:实现管道

    操作系统真象还原实验记录之实验三十四:实现管道 1.管道相关知识总结 先说我们操作系统的管道实现: 上述图中,管道缓冲区就是一页内存,这一页内存被我们当成了环形缓冲区结构, 当这页管道被创建出来后,全 ...

  3. 操作系统真象还原实验记录之实验十一:实现中断处理(二)

    操作系统真象还原实验记录之实验十一:实现中断处理(二) 书p335 7.6.2 改进中断处理程序,并调快时钟 1.实验代码第一次修改 对应 书p335 7.6.2 改进中断处理程序 这次是上一次实验的 ...

  4. 操作系统真象还原实验记录之实验七:加载内核

    操作系统真象还原实验记录之实验七:加载内核 对应书P207 1.相关基础知识总结 1.1 elf格式 1.1.1 c程序如何转化成elf格式 写好main.c的源程序 //main.c int mai ...

  5. 操作系统真象还原实验记录之实验六:内存分页

    操作系统真象还原实验记录之实验五:内存分页 对应书P199页 5.2 1.相关基础知识总结 页目录 页目录项 页表 页表项 物理页 虚拟地址 物理地址 概念略 页目录项及页表项 低12位都是属性.高2 ...

  6. 操作系统真象还原实验记录之实验一:第一次编写mbr

    操作系统真象还原之实验一:第一次编写mbr 对应书中第2.3节:让mbr飞一会 第58页 1.相关基础知识提炼总结 1.1电脑开机前与后 在电脑未开机前,BIOS就被事先写入到内存的F0000~FFF ...

  7. 操作系统真象还原实验记录之实验二十三:硬盘分区,并编写硬盘驱动程序

    操作系统真象还原实验记录之实验二十三:编写硬盘驱动程序 1.硬盘分区 1.1 创建Seven80.img硬盘 ./bximage -mode=create -imgmode=flat -hd=80 - ...

  8. 《操作系统真象还原》1-3章 学习记录

    文章目录 前言 一.开始实验前的一些基本问题解答? section的含义? vstart的含义? $ 和 $$区别? 实模式的特点? CPU如何和硬盘进行交互? CPU和IO设备交互方式? 程序载入内 ...

  9. 《操作系统真象还原》第十四章 ---- 实现文件系统 任务繁多 饭得一口口吃路得一步步走啊(上一)

    文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 部分缩写熟知 闲聊时刻 实现文件系统的原理 inode构建原理 目录构建原理 超级块构建思路 创建文件系统 编写完的super_block.h ...

最新文章

  1. win7 IIS7.5 HTTP 错误 404.17 - Not Found 请求的内容似乎是脚本,因而将无法由静态...
  2. redis -memcahe-mongo资料-windows定时重启计划
  3. Kaggle : Using a Convolutional Neural Network for classifying Cats vs Dogs
  4. fenby C语言 P30
  5. python 简单web音频_Python Twisted web服务器音频fi
  6. C++安全方向(二):2.4 openssl_BIO接口解析
  7. js学习(node.js环境)
  8. jQueryMobile新版中导航栏按钮消失的解决方法
  9. C#关键字operator
  10. 【数学模型】TOPSIS
  11. P-6002-10PK,P-6002-2PK脂质研究工具解析
  12. UnityShader 浮雕凹凸贴图BumpMap与法线贴图NormalMap的原理及其区别
  13. 风变编程python基础语法-第0关-千寻的名字
  14. 树状数组的理解以及简单应用
  15. 黑苹果鼠标不动_MacOS系统:解决黑果睡眠唤醒后假死问题(如键盘鼠标无反应等)...
  16. pyspider 文档介绍
  17. 禁止win10自动更新_一键禁止WIN10自动更新!
  18. 计算机的输入输出设备
  19. python问题:IndentationError:expected an indented blo
  20. 区块链在物联网中的应用

热门文章

  1. 你的团队需要一个会讲故事的人读书笔记
  2. 2020G1工业锅炉司炉操作证考试及G1工业锅炉司炉作业模拟考试
  3. 华为手机p40pro计算机不管,华为p40pro支持PC模式吗
  4. java中写定时任务
  5. ArcMap 镶嵌数据集基本使用方法
  6. 不知道什么时候开始,35 岁突然成了 IT 人职业生涯的终结年龄
  7. 如何减少页面加载时间(前端性能优化)
  8. SAP中通过生产版本有效期控制物料生产入库分析测试
  9. Python3 学习笔记
  10. 计算机的硬件组成(详)