标签: osdev

设置IRQ映射

我正在按照几个教程和参考试图设置我的内核.我在一个没有解释它的教程中遇到了一些不熟悉的代码.这是我告诉的代码映射16 IRQs (0-15)到ISR位置的代码32-47:

void irq_remap(void)
{
    outportb(0x20, 0x11);
    outportb(0xA0, 0x11);
    outportb(0x21, 0x20);
    outportb(0xA1, 0x28);
    outportb(0x21, 0x04);
    outportb(0xA1, 0x02);
    outportb(0x21, 0x01);
    outportb(0xA1, 0x01);
    outportb(0x21, 0x0);
    outportb(0xA1, 0x0);
}
Run Code Online (Sandbox Code Playgroud)

代码outportb()如下,但我已经清楚地了解它的作用:

void outPortB(unsigned short port, unsigned char data)
{
    __asm__ __volatile__ ("outb %1, %0" : : "dN" (port), "a" (data));
}
Run Code Online (Sandbox Code Playgroud)

我应该提一下,这是在受保护模式下的x86架构上.这个源代码工作正常,我理解它的作用,但我不明白它是如何做到的.有人可以向我解释这里发生了什么,所以如果我需要扩展这个,我会知道我在做什么吗?

x86 assembly kernel irq osdev

9
推荐指数
1
解决办法
3130
查看次数

使用自定义引导加载程序创建可引导的ISO映像

我试图将我用汇编语言编写的引导加载程序转换为ISO映像文件.以下是MikeOS bootloader 的代码.这是我的引导程序代码:

   BITS 16
start:
    mov ax, 07C0h     ; Set up 4K stack space after this bootloader
    add ax, 288       ; (4096 + 512) / 16 bytes per paragraph
    mov ss, ax
    mov sp, 4096

    mov ax, 07C0h     ; Set data segment to where we're loaded
    mov ds, ax

    mov si, text_string   ; Put string position into SI
    call print_string ; Call our string-printing routine

    jmp $         ; Jump here - infinite loop!
    text_string db 'This …
Run Code Online (Sandbox Code Playgroud)

linux assembly dd nasm osdev

9
推荐指数
2
解决办法
7724
查看次数

内存文件系统简单

任何人都可以点我一个简单的(不能强调这一点),在内存中的文件系统实现的?如果我可以创建一个文件并做一个简单的cat file.txt就足够了.

我想将它作为我玩具操作系统的一部分.

filesystems operating-system osdev

8
推荐指数
1
解决办法
6890
查看次数

如何将bin文件(512字节)写入软盘的第一个扇区(扇区0)?

如何将.bin文件写入软盘/虚拟软盘/软盘映像的第一个扇区?

我正在尝试启动一个简单的512字节引导加载程序.各地的大小都说"512字节",所以我应该已经很好了.

附加信息:

引导程序只显示一个字符串,我正在学习简单的汇编.一些工作是在Windows中完成的,一些是在Ubuntu 14.04(Trusty Tahr)中完成的(如果这很重要).

即使它具有引导加载程序标志,它也无法启动.

assembly floppy bios osdev bootloader

8
推荐指数
2
解决办法
5992
查看次数

如何为我的bootloader制作内核?

我正在尝试制作自己的自定义操作系统,我需要一些代码帮助.这是我的bootloader.asm:

[ORG 0x7c00]

start:
    cli
    xor ax, ax
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov [BOOT_DRIVE], dl
    mov bp, 0x8000
    mov sp, bp
    mov bx, 0x9000
    mov dh, 5
    mov dl, [BOOT_DRIVE]
    call load_kernel
    call enable_A20
    call graphics_mode
    lgdt [gdtr]
    mov eax, cr0
    or al, 1
    mov cr0, eax
    jmp CODE_SEG:init_pm

[bits 32]
init_pm:
    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov ebp, 0x90000 …
Run Code Online (Sandbox Code Playgroud)

x86 assembly kernel osdev bootloader

8
推荐指数
1
解决办法
1866
查看次数

GCC - 标签地址返回当前EIP而不是真实标签地址

在尝试编写OS时,我需要获取当前函数结束的地址(在结尾之前)以进行任务切换.
具体来说,我的问题是让EIP分配给复制堆栈内新创建的任务(进程).我已经设法为进程保存/恢复寄存器,但我需要找到子进程在其EIP中具有的值.

我使用了GCC对C标准的扩展:标签作为值本地标签
从文档中:您可以使用一元运算符'&&'获取当前函数(或包含函数)中定义的标签的地址.该值的类型为void*.
和:GCC允许您在任何嵌套块范围内声明本地标签.本地标签就像普通标签一样,但您只能在声明它的块中引用它(使用goto语句或通过获取其地址).

pid_t fork(void)
{
    __label__ fork_end;
    ...
    task->regs.eip = (uintptr_t)&&fork_end;
    ...
    return task->pid;
    fork_end:;
}
Run Code Online (Sandbox Code Playgroud)

GCC确实编译它,只是警告非标准代码.
但是在反汇编时,gdb显示:

    task->regs.eip = (uintptr_t)&&fork_end;
0x00105008 <+87>:   mov    $0x105008,%edx
0x0010500d <+92>:   mov    -0xc(%ebp),%eax
0x00105010 <+95>:   mov    %edx,0x40(%eax)
...
    fork_end:;
    }
0x00105096 <+229>:  leave  
0x00105097 <+230>:  ret 
Run Code Online (Sandbox Code Playgroud)

我希望task->regs.eip = (uintptr_t)&&fork_endl能节省0x00105096而不是0x00105008.
CFLAGS-O0 -std=gnu99 -fgnu89-inline -DDEBUG -ggdb3 -ffreestanding -fbuiltin(此处未显示警告相关选项).

评论__label__ fork_end;没有任何改变.

c gcc osdev

8
推荐指数
1
解决办法
191
查看次数

如何解决qemu gdb调试错误:远程'g'数据包回复太长了?

我正在进入引导程序和内核开发(非常开始)我正在关注https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev的组合 .pdfhttps://github.com/cfenollosa/os-tutorial中的代码

唯一不同的是,我的目标是x86_64而不是i386.我也使用qemu模拟(qemu-system-x86_64).现在跟随GitHub回购到第16部分视频驱动程序之后,我被卡住了,因为屏幕驱动程序确实在屏幕上打印了一些东西,但是有些事情正在发生,数据不对齐.接下来我想尝试调试我的程序.这部分也包含在回购的第14部分检查点中.所以我为目标x86_64-elf构建了gdb.但是,当我尝试运行qemu和gdb使用system-qemu-x86_64 -s -S -fda os-image ,然后运行gdb并尝试通过运行连接到qemu target remote localhost:1234,一旦我运行,我得到以下错误消息

Remote debugging using localhost:1234
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
Remote 'g' packet reply is too long (expected 308 bytes, got 536 bytes):
000000000000000000000000000000000000000000000000630600000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000f0ff0000000000000200000000f00000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000007f03000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000801f0000
Run Code Online (Sandbox Code Playgroud)

关于我遗失/做错的任何想法?如果需要更多信息,请告诉我.

谢谢

编辑:我已经应用了@MichaelPetch提到的补丁,现在g包错误消失了.但是看起来gdb在运行后无法解释我的可执行文件target remote localhost:1234,然后symbol-file kernel.elf …

x86 gcc gdb qemu osdev

8
推荐指数
1
解决办法
1968
查看次数

你如何解释gcc对i386的IN,OUT指令的内联汇编约束?

据我所知,gcc内联汇编中使用的约束告诉gcc输入和输出变量必须(或必须),以便生成有效的汇编.正如精细手册所说,"对操作数放置的限制".

这是一个教程中特定的工作示例.

static inline uint8_t inb(uint16_t port)
{
    uint8_t ret;
    asm volatile ( "inb %1, %0"
                   : "=a"(ret)
                   : "Nd"(port) );
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

inb是AT&T语法 - 代表IN从I/O端口接收一个字节的i386 指令.

以下是本指令的规格,取自i386手册.需要注意的是端口号,从去0x00000xFFFF.

IN AL,imm8  // Input byte from immediate port into AL
IN AX,imm8  // Input word from immediate port into AX
IN EAX,imm8 // Input dword from immediate port into EAX
IN AL,DX    // Input byte from port DX into AL
IN AX,DX …
Run Code Online (Sandbox Code Playgroud)

x86 gcc g++ inline-assembly osdev

8
推荐指数
1
解决办法
349
查看次数

通过将EFLAGS.VM设置为1,问题从32位保护模式切换到v8086模式

我处于以当前权限级别(CPL = 0)运行的32位保护模式.我试图通过将EFLAGS.VM(位17)标志设置为1(和IOPL为0)并对我的16位实模式代码执行FAR JMP来进入v8086模式.我使用当前的标志PUSHF; 将EFLAGS.VM(第17位)设置为1; 将EFLAGS.IOPL(第22位和第23位)设置为0; 设置新的EFLAGS POPF.这个代码看起来像:

    bits 32
    cli
    [snip]
    pushf                       ; Get current EFLAGS
    pop eax
    or eax, 1<<EFLAGS_VM_BIT    ; Set VM flag to enter v8086 mode
    and eax, ~(3<<EFLAGS_IOPL_BITS)
                                ; Set IOPL to 0
                                ; IF flag already 0 because of earlier CLI
    push eax
    popf                        ; Reload new flags
    jmp CODE32_SEL:v86_mode_entry
                                ; Far JMP to v8086 entry point

    ; v8086 code entry point
    bits 16
    v86_mode_entry:
        hlt                         ; Halt should double fault …
Run Code Online (Sandbox Code Playgroud)

x86 assembly x86-64 nasm osdev

8
推荐指数
1
解决办法
261
查看次数

PS / 2键盘不会发送按键中断,但会响应命令

我对OS开发还很陌生,最近我开始了一个业余爱好项目,它创建了一个尽可能简单的纯文本操作系统。它是用C语言编写的,并得到了汇编的帮助,并使用GRUB进行引导,我已经在VirtualBox中对其进行了测试,有时还将其放在闪存驱动器上,以便在古老的(〜2009)笔记本电脑上进行测试。到目前为止,我已经实现了一些基本的文本输出功能,考虑到最近没有崩溃,我认为我的GDT和IDT实现是可以的。目前,我正在尝试使中断驱动的键盘驱动程序正常工作。

我认为我已经正确设置了PIC,并且似乎很幸运能向PS / 2控制器和键盘发出命令并通过中断处理程序捕获响应。例如,这是在为键盘提供识别命令时的调试输出:

Initializing kernel...
Setting PS/2 controller status: 0x05
Sending keyboard command: 0xF2
Keyboard interrupt: 0xFA
Keyboard interrupt: 0xAB
Keyboard interrupt: 0x83
Run Code Online (Sandbox Code Playgroud)

返回的数据似乎是正确的,这证明我的中断处理程序可以连续多次工作而不会崩溃或发生任何事情,因此我不必担心我的IDT或ISR实现。现在,这是我将0xF4命令发送到键盘以开始扫描按键时的输出:

Initializing kernel...
Setting PS/2 controller status: 0x05
Sending keyboard command: 0xF4
Keyboard interrupt: 0xFA
Run Code Online (Sandbox Code Playgroud)

状态代码为“确认”(0xFA)的中断看起来很有希望,但是之后按键时什么也没有发生。对于这两个示例,在VirtualBox和我一直使用的笔记本电脑上运行时,我得到的结果都是相同的。

以下是键盘驱动程序中的一些相关代码:

#define KEYBD_DATA 0x60
#define KEYBD_CMD 0x64

// wrapper for interrupt service routine written in assembly
extern void keyboard_interrupt();

// called from assembly ISR
void keyboard_handler() {
    u8 data = read_port(KEYBD_DATA);
    print("Keyboard interrupt: 0x");
    printx(data);
    putc('\n');
    pic_eoi();
}

// functions …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly interrupt osdev

8
推荐指数
1
解决办法
151
查看次数

标签 统计

osdev ×10

assembly ×6

x86 ×6

gcc ×3

bootloader ×2

c ×2

kernel ×2

nasm ×2

bios ×1

dd ×1

filesystems ×1

floppy ×1

g++ ×1

gdb ×1

inline-assembly ×1

interrupt ×1

irq ×1

linux ×1

operating-system ×1

qemu ×1

x86-64 ×1