【发布时间】:2019-04-01 17:06:55
【问题描述】:
我无法理解这个问题:
我有这段代码被引导加载程序调用,但是当我编译并运行一个应该打印 HELLO 的测试时,可能会发生以下三件事之一:
如果我声明另一个无符号类型的变量,代码将只打印字符串的一半 (HE)。
如果我声明另一种类型的 var,它根本不会打印任何东西 ()。
如果我不声明任何内容,代码将运行良好(HELLO)。
main.c
#include "system.h"
int main(void)
{
init_video();
move_csr();
p("HELLO\0");
while(1){}
return 1;
}
系统.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;
代码运行良好。
我对汇编不太了解,也许我错过了有关如何管理内存的重要信息。
【问题讨论】:
-
要运行 64 位代码,您需要处于 64 位模式。您的 boot.asm 是否真的变为 64 位模式?还是您在 32 位保护模式下运行?您所描述的通常与在 32 位保护模式下运行 64 位代码有关。很可能是别的东西,但这是一个没有看到你项目的其余部分的猜测。
-
我可能需要查看 boot.asm(甚至可能是 loader.asm)才能知道您是处于 32 位保护更多还是 64 位长模式)
-
嘿@MichaelPetch 很高兴再次收到您的来信。加载器代码太大,无法在此处发布,如果可以帮助您猜出问题,我已将其上传到我的 github github.com/TretornESP/shell。与此同时,我试图弄清楚我是否在做你猜到的事情。谢谢。
-
看起来你试图进入 64 位长模式(看起来没问题,但我只是快速浏览了一下)。从磁盘读取内核的代码只读取内核的 1 个扇区。是您的内核可能大于 512 字节吗?您可能必须将您的完整项目放在 github 上才能解决问题。
-
非常感谢,我会弄清楚如何从磁盘加载多个扇区,另外,我已将原始文件夹上传到 github,以便您查看。 (它基本上是我发布的代码 + 加载器 + 一些内存功能)。再次感谢您!