64位内核异常行为

时间:2018-10-28 17:15:19

标签: gcc kernel x86-64 osdev

我无法理解此问题:

我有一个由引导程序调用的代码,但是当我编译并运行应该打印HELLO的测试时,可能会发生以下三种情况之一:

如果我声明另一个类型为unsigned的变量,则代码将仅打印字符串(HE)的一半。

如果我声明另一种类型的var,它将根本不会打印任何内容()。

如果我不声明任何内容,则代码会正常工作(HELLO)。

main.c

#include "system.h"

int main(void)
{
    init_video();
    move_csr();
    p("HELLO\0");
    while(1){}
    return 1;

}

system.h

#ifndef __SYSTEM_H
#define __SYSTEM_H

/* MAIN.C */

extern void move_csr(void);

extern void init_video();
extern void pc(unsigned char);
extern void p(char*);

#endif

scrn.c

#include "system.h"

unsigned char *textmemptr;
int attrib = 0x0F;
int csr_x = 0, csr_y = 0;

void init_video() {
    textmemptr = (unsigned char*) 0xB8000;
    return;
}

void move_csr(void) {
        unsigned temp = csr_y * 80 + csr_x;
}

void pc(unsigned char c) {
    *textmemptr = c;
    textmemptr += 2;
}

void p(char* string) {
    for (int i = 0; ; i++) {
        if (string[i]=='\0') return;
        pc(string[i]);
    }
}

build.sh

#!/bin/bash

nasm -f bin boot.asm -o boot.bin
nasm -f elf64 loader.asm -o loader.o

#cc -m64  -ffreestanding -fno-builtin -nostdlib -c main.c
#-Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin
cc -m64 -masm=intel -fno-builtin -c main.c scrn.c
ld  -Ttext 0x100000 -o kernel.elf loader.o main.o scrn.o
objcopy -R .note -R .comment -S -O binary kernel.elf kernel.bin

dd if=/dev/zero of=image.bin bs=512 count=2880
dd if=boot.bin of=image.bin conv=notrunc
dd if=kernel.bin of=image.bin conv=notrunc bs=512 seek=1

rm ./boot.bin ./kernel.bin ./main.o ./loader.o ./kernel.elf

#qemu-system-x86_64 image.bin format=raw

qemu-system-x86_64 -drive file=image.bin,format=raw,index=0,media=disk -m 512

如果我禁止显示行:

unsigned temp = csr_y * 80 + csr_x;

代码效果很好。

我对汇编不了解太多,也许我缺少关于内存管理方式的重要信息。

1 个答案:

答案 0 :(得分:3)

Michael Petch的答案

  

在您的kernel.bin文件中,HELLO字符串似乎是   部分在前512个字节中,其余部分在外部。当您添加   或删除代码,它会更改该字符串的放置位置(无论它是否在   前512个字节与否),很可能是您的代码起作用的原因   不一样。您肯定需要阅读超过1本书   部门来解决这个问题。

问题在于,加载程序文件仅读取kernel.bin的一个扇区,因此我尝试打印的字符串仅部分加载。解决方案是修改引导加载程序,以便加载足够的扇区来运行代码。

[编辑]

Michael Petch建议在构建脚本中将-z max-page-size=0x1000添加到ld中,从而大大减小了.bin文件的大小。