标签: osdev

在从中断处理程序返回之前,是否必须弹出由某些异常推送到堆栈的错误代码?

我已经加载了一个包含256个条目的idt表,它们都指向类似的处理程序:

  • 对于例外8和10-14,推送异常编号(这些异常会自动推送错误代码)
  • 对于其他人,推送"虚拟"错误代码和异常号码;
  • 然后跳转到一个公共处理程序

因此,当公共处理程序进入时,堆栈正确对齐并包含异常/中断号,错误代码(可能只是虚拟代码),eflags,cs和eip.

我的问题是关于从中断处理程序返回.我iret从堆栈中取出异常编号和错误代码后使用返回,但这不适用于异常nr 8; 如果我把错误代码留在堆栈上,那么它返回正常!

问题:

  • 我是否必须将错误代码留在堆栈上,以便将错误代码放在那里?如果是这样,如何iret确定是否必须弹出错误代码?
  • 一旦我启用中断,我总是得到异常8(双故障),但一切都运行正常(我正在开发一个爱好操作系统).这是正常行为还是某处有错误?

x86 assembly operating-system interrupt osdev

6
推荐指数
1
解决办法
4158
查看次数

自包含C例程来打印字符串

我想创建一个自包含的C函数来打印一个字符串.这将是操作系统的一部分,所以我无法使用stdio.h.如何创建一个函数来打印我传递给它的字符串而不使用stdio.h?我必须在汇编中写它吗?

c assembly operating-system osdev

6
推荐指数
1
解决办法
287
查看次数

为什么在从实模式切换到保护模式之前需要禁用中断?

我在许多ose(和一些引导程序)中看到,它们cli在从实模式切换到保护模式之前都禁用了interrupt().为什么我们需要这样做?

x86 operating-system real-mode osdev bootloader

6
推荐指数
1
解决办法
1049
查看次数

调度程序的RTC与PIT

我的教授说,建议使用PIT而不是RTC来实现基于纪元的循环调度程序.他没有真正提到任何具体原因,我也想不出任何理由.有什么想法吗?

operating-system osdev

6
推荐指数
1
解决办法
1307
查看次数

奇怪的链接器行为:重定位被截断以适应

我有一个带有两个绝对符号的内核的链接描述文件:_kernel_start_kernel_end.但是,我只收到链接器重定位错误_kernel_end:

In function `kernel::mem::mm::setup_memorymap':
/home/virtlink/kernel/src/mem/mm.rs:25:(.text._ZN3mem2mm15setup_memorymap):
  relocation truncated to fit: R_X86_64_PC32 against symbol `_kernel_end'
  defined in *ABS* section in ./kernel.bin
Run Code Online (Sandbox Code Playgroud)

这里有很多关于这个错误的问题,但我没有找到解决我特定问题的问题.

显然,这个:

_kernel_start = .;
Run Code Online (Sandbox Code Playgroud)

...被视为32位,而这:

. += KERNEL_BASE;
_kernel_end = . - KERNEL_BASE;
Run Code Online (Sandbox Code Playgroud)

...被视为64位.如果我将_kernel_end符号移动到. += KERNEL_BASE线上方,如下所示:

_kernel_end = .;
. += KERNEL_BASE;
Run Code Online (Sandbox Code Playgroud)

......然后再次运作.但我想_kernel_end在我的链接器脚本的末尾.

链接描述文件将引导代码放在内存开头,其余代码放在64位虚拟内存空间的上半部分.它看起来像这样:

OUTPUT_FORMAT(elf64-x86-64)

KERNEL_BASE = 0xFFFFFFFF80000000;

SECTIONS
{
    /* Boot code at 1 MiB */
    . = 1M;
    _kernel_start = .;
    .boot :
    {
        KEEP( *(.multiboot) …
Run Code Online (Sandbox Code Playgroud)

linker relocation osdev rust

6
推荐指数
0
解决办法
548
查看次数

Write :: write_fmt在裸机上无法正常工作

在x86_64体系结构上,write!宏使用字符串参数按预期工作,但不使用整数.当使用整数参数时,我得到一个奇怪的循环(例如write!(writer, "Hello {}!", 123)产生无限的"Hello Hello Hello ...").在aarch64上,write!宏根本不起作用.

我使用以下命令构建libcore:

rustc -C opt-level=3 -Z no-landing-pads -C no-stack-check \
  --crate-type rlib --target {arch}-unknown-linux-gnu lib.rs
Run Code Online (Sandbox Code Playgroud)

{arch}分别在哪里x86_64aarch64.

我的代码使用相同的代码生成选项构建.libcore版本对应于我的编译器.有问题的代码在这里.你能说出问题的可能原因吗?

重要更新:

是更精简的代码.libcore是在项目中构建的,因此一切都在掌控之中.上面的循环来自机器重启.代码完全适用于aarch64,但奇怪的是在x86_64上的Write :: write_fmt内崩溃.仔细检查我的启动程序集 - 似乎没有错误.

osdev rust

6
推荐指数
1
解决办法
312
查看次数

我应该制作自己的操作系统内核ELF还是原始二进制文件?

我已经开始了我的OS开发之旅.人们通常会大声说使用原始二进制而不是ELF(或其他结构化格式)是自定义操作系统中应用程序的常见错误.我可以说,因为ELF提供了额外的好处(存储元信息的地方,如符号表,.debug和.line).但是,让我们考虑内核二进制本身一分钟.它应该是结构化的(如ELF),如果是,为什么?否则写一个ELF加载器并在stage1加载器之后立即挤压它似乎是浪费.

AFAIK Linux内核是一个ELF文件,但我不知道原因.

operating-system kernel elf osdev bootloader

6
推荐指数
1
解决办法
2230
查看次数

切换到更高的分辨率

最近,我开始在NASM和C中开发一个操作系统.我已经制作了一个启动加载程序,内核,文件系统等.到目前为止,我直接使用VGA文本模式来写入地址0x000B8000.所以,我决定切换到视频模式而不是文本模式.我选择了最大显示分辨率320x200,但后来我意识到有三个问题.首先,只有256种不同的颜色.其次,分辨率太小.第三,写入地址0x000A0000太慢了.我尝试做一些动画,但它非常迟钝,有时它会在下一帧之前等待超过一秒钟.

我在互联网上搜索了一些关于如何切换到更高分辨率的解释,例如1920x1080如何使用256*256*256颜色而不仅仅是256.我发现的一切都说很难使用更高的分辨率,因为你必须开发所有不同的驱动程序显卡类型和某些卡没有文档,所以我们必须使用逆向工程.

我真的想在我的操作系统中引入高分辨率图形.真的很难还是有简单的方法?关于如何解决这个问题的任何建议?

c nasm osdev

6
推荐指数
1
解决办法
388
查看次数

将完整操作系统编写为UEFI应用程序的现实性

从技术上讲,UEFI提供了许多功能,这些功能是操作系统(如文件系统)的基础工作的一部分.在某种程度上,遗憾的是,在启动过程中,操作系统会丢弃并重新实现所有内容.

我想知道将多少功能操作系统作为简单的UEFI应用程序实现它.我在考虑图形用户界面和多任务处理.使用FAT32作为文件系统,UEFI应该可以用于很多目的,因此应该标识映射内存.它将构成一个非常精简和简单的操作系统,甚至可能无需安装.

问题是在完全成熟的操作系统的功能方面提供什么是可行的限制?有什么建议?

c osdev uefi

6
推荐指数
1
解决办法
311
查看次数

x86内核中的键盘IRQ

我正在尝试编写一个非常简单的内核用于学习目的.在阅读了大量有关x86架构中PIC和IRQ的文章后,我发现这IRQ1是键盘处理程序.我正在使用以下代码打印正在按下的键:

#include "port_io.h"

#define IDT_SIZE 256
#define PIC_1_CTRL 0x20
#define PIC_2_CTRL 0xA0
#define PIC_1_DATA 0x21
#define PIC_2_DATA 0xA1

void keyboard_handler();
void load_idt(void*);

struct idt_entry
{
    unsigned short int offset_lowerbits;
    unsigned short int selector;
    unsigned char zero;
    unsigned char flags;
    unsigned short int offset_higherbits;
};

struct idt_pointer
{
    unsigned short limit;
    unsigned int base;
};

struct idt_entry idt_table[IDT_SIZE];
struct idt_pointer idt_ptr;

void load_idt_entry(char isr_number, unsigned long base, short int selector, char flags)
{
    idt_table[isr_number].offset_lowerbits = base & 0xFFFF;
    idt_table[isr_number].offset_higherbits …
Run Code Online (Sandbox Code Playgroud)

c x86 kernel irq osdev

6
推荐指数
1
解决办法
1841
查看次数

标签 统计

osdev ×10

operating-system ×5

c ×4

x86 ×3

assembly ×2

bootloader ×2

kernel ×2

rust ×2

elf ×1

interrupt ×1

irq ×1

linker ×1

nasm ×1

real-mode ×1

relocation ×1

uefi ×1