操作系统真相还原--第七章中断实验BUG--找不到中断向量表

本文主要是介绍操作系统真相还原--第七章中断实验BUG--找不到中断向量表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 一、问题描述
  • 二、解决思路
    • 2.1 尝试从编译命令层面解决
    • 2.2 反汇编kernel.bin分析原因
    • 2.3 制作test文件验证链接是否存在问题
    • 2.4 修改loader.S解决问题
  • 三、结尾

一、问题描述

在进行第七章中断实验时,出现一个问题。当使用lidt加载中断向量表命令后,使用bochs的调试命令Info idt,发现中断号对应的中断函数地址有问题:
在这里插入图片描述
从图中可以看到,DPL正确,选择子正确,但是基址有问题,全为0

二、解决思路

先说结论:问题出现在lodaer.S中,在加载elf文件的program段时,只运行了一次加载过程,导致只加载了.text段,也就是代码段,没加载.data段。

2.1 尝试从编译命令层面解决

完成该实验时ubuntu的gcc版本为7.5,根据有的博主描述,需要降版本到4.4,于是进行降版本,参考文章:

《操作系统真象还原》第五章 ---- 轻取物理内存容量 启用分页畅游虚拟空间 力斧直斩内核先劈一角 闲庭信步摸谈特权级

并深入学习了nasm编译和ld链接的原理,以为是链接出现了问题,于是修改编译命令,最终使用的编译命令如下:

#var for boot#Var for GCC
# 此处可能需要加stck_protect那个编译选项
CFLAGS += -fno-builtin 
INCLUDE := \-Ikernel/ \-Iinclude/ \-Ilib/ \-Ilib/kernel/ \-Ilib/kernel/include
GCC32 += -m32
GCC_MARCH += -march=i386#Var for ld
BUILD_SRC := build/main.o \build/init.o \build/interrupt.o \build/print.o \build/kernel.o
BUILD_DES := build/kernel.bin
LD_ENTRY_ADDR := -Ttext 0xc0001500
LD_ENTRY_FUNC := main#Var for gene
CURRENT_PATH := $(shell pwd)
_all:all: _all@echo "==========================start building...===================================="@echo "=============================#1 start compile=============================="gcc ${GCC32} ${INCLUDE} -c ${CFLAGS} -o build/main.o kernel/main.cnasm -f elf -o build/print.o lib/kernel/print.Snasm -f elf -o build/kernel.o kernel/kernel.Sgcc ${GCC32} ${INCLUDE} -c ${CFLAGS} -o build/interrupt.o drivers/interrupt/interrupt.cgcc ${GCC32} ${INCLUDE} -c ${CFLAGS} -o build/init.o init/init.c@echo "=============================#2 start ld=================================="ld -m elf_i386 ${LD_ENTRY_ADDR} -e ${LD_ENTRY_FUNC} -o ${BUILD_DES} ${BUILD_SRC}dd if=${CURRENT_PATH}/${BUILD_DES} of=${CURRENT_PATH}/hd60M.img bs=512 count=200 seek=9 conv=notrunc@echo "build successful!"@echo "objdump..............."objdump -d build/kernel.bin > build/asm/kernel.bin_gcc_4.4.7.asm

第七章实验的文件结构如下,大致仿照linux的结构来建立的文件夹:
在这里插入图片描述
然而,此阶段并没有解决问题,仍然存在该问题。

2.2 反汇编kernel.bin分析原因

上一步没有结果,反复对照各博主实验过程与《操作系统真相还原》书中给出的代码,可以保证C代码和汇编代码kernel.S没有任何问题。于是反汇编kernel.bin,分析问题。通过gcc的反汇编工具objdump来反汇编:

objdump -d build/kernel.bin > build/asm/kernel.bin_gcc_4.4.7.asm

结合interrupt.c中的C代码:

interrupt.c:
/*创建中断门描述符*/
static void make_idt_desc(struct gate_desc* p_gdesc,uint8_t attr,intr_handler function){p_gdesc->func_offset_low_word=(uint32_t)function & 0x0000ffff;p_gdesc->selector=SELECTOR_K_CODE;   // 中断后进入内核代码p_gdesc->dcount=0;p_gdesc->attribute=attr;p_gdesc->func_offset_high_word=((uint32_t)function & 0xffff0000)>>16;
}/*初始化中断描述符表*/
static void idt_desc_init(void){int i;for (i=0;i<IDT_DESC_CNT;++i){make_idt_desc(&idt[i],IDT_DESC_ATTR_DPL0,intr_entry_table[i]);}put_str("   idt_desc_init done\n");
}

定位汇编中的问题命令:
在这里插入图片描述
可以看到,中断向量函数基址作为函数调用的第三个参数,被赋值给了eax并进行压栈。在此处打断点并查看eax寄存器的值,发现为0。说明此处没有把中断处理函数基址赋值给eax寄存器。

此处令我疑惑,不可能找不到中断处理函数基址,因为链接已经成功了,可以看到反汇编后的代码中有这些中断处理函数:
在这里插入图片描述
此处未能发现问题,主要是汇编代码太多了,不容易分析问题。于是做了一个简单的实验,来分析gcc编译文件与nasm编译文件的链接问题

2.3 制作test文件验证链接是否存在问题

制作main_test.c:

#include "stdint.h"
typedef void* intr_handler;
extern intr_handler intr_entry_table[0x21];
void main(void) 
{uint32_t test_low = (uint32_t)intr_entry_table[0] & 0x0000ffff;uint32_t test_high = ((uint32_t)intr_entry_table[0] & 0xffff0000)>>16;while(1); 
}

制作kernel_test.S:

[bits 32]
[section .data]
global intr_entry_table
intr_entry_table:%macro VECTOR 1
[section .text]intr%1entry:                ;每个中断处理程序都要压入中断向量号,一个中断类型一个中断处理程序out 0xa0,al              ;向从片发送iret                     ;从中断返回
[section .data]dd intr%1entry           ;存储各个中断入口程序的地址,形成intr_entry_table数组
%endmacroVECTOR 0x0
VECTOR 0x1
VECTOR 0x2
VECTOR 0x3

编译链接命令:

debug: _all@echo "==========================Debug...===================================="gcc ${GCC_MARCH} ${GCC32} ${INCLUDE} -c ${CFLAGS} -o debug/build/main_test.o debug/main_test.cnasm -f elf -o debug/build/kernel_test.o debug/kernel_test.Sld -m elf_i386 ${LD_ENTRY_ADDR} -e ${LD_ENTRY_FUNC} -o debug/build/kernel_test.bin debug/build/main_test.o debug/build/kernel_test.o  objdump -d debug/build/kernel_test.bin > debug/build/asm/kernel_test.bin.asmobjdump -d debug/build/kernel_test.o > debug/build/asm/kernel_test.o.asmobjdump -d debug/build/main_test.o > debug/build/asm/main_test.o.asmdebug_dd: _alldd if=${CURRENT_PATH}/debug/build/kernel_test.bin of=${CURRENT_PATH}/hd60M.img bs=512 count=200 seek=9 conv=notrunc

对kernel_test.bin进行反汇编,结果如下:
在这里插入图片描述
想说的都在汇编中加了注释了,关键就是0xc000252c这个地址中的数据,是不是intr0x0entry的起始地址,也就是是不是0xc0001520。但是在反汇编之后的文件中根本没找到0xc000252c这个地址,这也很让我疑惑。

将该kernel_test.bin载入bochs中运行,使用xp/2 0x252c(实地址,对应虚拟地址0xc000252c),查看0xc000252c这个地址中的数据,发现全是0。这个时候想起来了,在kernel.S中,把中断函数的地址,存在了data段中。所以说0xc000252c这个地址,应该是data段的地址。于是解析kernel_test.bin这个elf文件:
在这里插入图片描述
发现确实是data段在内存中的首地址,所以只要看一眼data段的首地址的内容(文件内偏移0x052c),就能确定是不是编译链接有问题了。通过16进制打开kernel_test.bin文件:
在这里插入图片描述
发现0x052c地址(对应虚拟地址0xc000252c)中是有内容的,并不是0,而且就是c0001520,也就是第0个中断处理函数的地址:
在这里插入图片描述
至此可以确定,编译没有问题,出问题的是data段的加载有问题,可能根本没有加载进来,也可能加载到了错误的位置。

2.4 修改loader.S解决问题

知道问题在哪了,就好改多了。回头看loader.S,错误很快就发现了:
在这里插入图片描述
在写loader.S时没有加loop这条命令,导致只加载了一段,也就是只加载了text段,没加载其他段。

三、结尾

这个问题说大不大说小不小,现在比较忙,每天只能抽出不到一个小时来做一下这个实验,一出现这种问题就心烦意乱,花了四五天的时间来搜索解决方案,完全不想调试。趁着周末沉下心来一看,一步步调试其实也能找到问题。

这篇关于操作系统真相还原--第七章中断实验BUG--找不到中断向量表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1041532

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

Linux操作系统 初识

在认识操作系统之前,我们首先来了解一下计算机的发展: 计算机的发展 世界上第一台计算机名叫埃尼阿克,诞生在1945年2月14日,用于军事用途。 后来因为计算机的优势和潜力巨大,计算机开始飞速发展,并产生了一个当时一直有效的定律:摩尔定律--当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍。 那么相应的,计算机就会变得越来越快,越来越小型化。

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

HNU-2023电路与电子学-实验3

写在前面: 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能,设计 8 重 3-1 多路复用器。 3.分析模型机的功能,设计 8 重 2-1 多路复用器。 4.分析模型机的工作原理,设计模型机控制信号产生逻辑。 二、实验内容 1.用 VERILOG 语言设计模型机的 8 重 3-1 多路复用器; 2.用 VERILOG 语言设计模型机的 8 重 2-1 多

[环境配置]ubuntu20.04安装后wifi有图标但是搜不到热点解决方法

最近刚入手一台主机,暗影精灵8plus电竞主机,安装ubuntu后wifi怎么都搜不到热点,前后重装系统6次才算解决问题。这个心酸历程只有搞技术人才明白。下面介绍我解决过程。 首先主机到手后是个windows10系统,我用无线网连接了一下,可以正常上网,说明主机有无限网卡且正常。然后我就直接开始安装Ubuntu20.04了,安装成功后发现wifi有图标但是搜不到热点,我想是不是无线网卡驱动有没有

如何保证android程序进程不到万不得已的情况下,不会被结束

最近,做一个调用系统自带相机的那么一个功能,遇到的坑,在此记录一下。 设备:红米note4 问题起因 因为自定义的相机,很难满足客户的所有需要,比如:自拍杆的支持,优化方面等等。这些方面自定义的相机都不比系统自带的好,因为有些系统都是商家定制的,难免会出现一个奇葩的问题。比如:你在这款手机上运行,无任何问题,然而你换一款手机后,问题就出现了。 比如:小米的红米系列,你启用系统自带拍照功能后

FreeRTOS学习笔记(四)Freertos的中断管理及临界保护

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Cortex-M 中断管理1.1 中断优先级分组1.2 相关寄存器1.3 相关宏定义1.4 FreeRTOS 开关中断 二、临界段及其保护2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRITICAL( )2.2 taskENTER_CRITICAL_FROM_ISR( )

Cortex-A7:ARM官方推荐的嵌套中断实现机制

0 参考资料 ARM Cortex-A(armV7)编程手册V4.0.pdf ARM体系结构与编程第2版 1 前言 Cortex-M系列内核MCU中断硬件原生支持嵌套中断,开发者不需要为了实现嵌套中断而进行额外的工作。但在Cortex-A7中,硬件原生是不支持嵌套中断的,这从Cortex-A7中断向量表中仅为外部中断设置了一个中断向量可以看出。本文介绍ARM官方推荐使用的嵌套中断实现机

1、简述linux操作系统启动流程

1、简述linux操作系统启动流程 启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它。这是因为BIOS中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信息、时钟信息、PnP特性等等。开机时将ROM中的指令映射到RAM的低地址空间,CPU读取到这些指令,硬件的健康状况进行检查,按照BIOS中设置的启

jmeter依赖jar包找不到类路径

这两天我在纠结这个问题,为啥我maven打包放在jmeter路径下后,jmeter的bean Shell 就是找不到这个类。纠结很久解开了。我记录下,留给后来的朋友。   Error invoking bsh method: eval Sourced file: inline evaluation of: ``import org.apache.jmeter.protocol.http.s