我正在编写自己的操作系统作为家庭作业,我的C代码遇到了一些麻烦。我已经设置了我的引导头和链接器文件以及一个打印' H'的简单汇编脚本。然后调用我的C代码。汇编代码打印到视频内存很好(我打印到0xb8000)但我的C代码中的while循环不是。
const char *str = "My first kernel";
char *vidptr = (char*)0xb8002; //My ASM code writes to 0xb8000 for testing purposes
while(*str){
*vidptr++ = 0x07;
*vidptr++ = *str++;
}
vidptr[0] = 0x07;
vidptr[1] = 'f';
' H'和' f'字符打印得很好,但我的循环不打印任何东西到屏幕上。我尝试了多种编写循环的方法,例如
unsigned int j = 0;
char c;
while(c = *(str++)){
vidptr[j] = 0x07;
vidptr[j+1] = c;
j+=2;
}
当然我已经尝试了
int i, j;
while(str[i] != '\0'){
vidptr[j] = 0x07;
vidptr[j+1] = str[i];
i++;
j+=2;
}
但似乎没有任何效果。我很困惑。
编辑:
我做了一些小改动,导致str中的字符被打印到屏幕上。我只是将vidptr更改为指向整数的指针。
int *vidptr = (int*)0xb8000;
这似乎有效。但是,当vidptr被声明为char指针时,我仍然感到困惑的原因是它为什么不起作用。即使我宣布它不稳定,我仍然没有输出到屏幕。
编辑2:
根据要求,这是有效的ASM代码。
global start
extern main
section .text
bits 32
start:
mov word [0xb8000], 0x0748
mov esp, stack_space
call main
hlt
section .bss
resb 8192
stack_space:
main是我上面提供的C代码中的函数。
我的Github Repository可以找到我的源代码的完整副本。我的Makefile是:
default: build
.PHONY: clean
build/boot_header.o: multiboot_header.asm
mkdir -p build
nasm -f elf64 multiboot_header.asm -o build/boot_header.o
build/asmk.o: kernel.asm
mkdir -p build
nasm -f elf64 kernel.asm -o build/asmk.o
build/ckern.o: kernel.c
gcc -m64 -c kernel.c -o build/ckern.o
build/kernel.bin: build/boot_header.o build/asmk.o build/ckern.o link.ld
ld -n -o build/kernel.bin -T link.ld build/boot_header.o build/ckern.o build/asmk.o
build/os.iso: build/kernel.bin grub.cfg
mkdir -p build/isofiles/boot/grub
cp grub.cfg build/isofiles/boot/grub
cp build/kernel.bin build/isofiles/boot/
grub-mkrescue -o build/os.iso build/isofiles
run: build/os.iso
qemu-system-x86_64 -curses -cdrom build/os.iso
build: build/os.iso
clean:
rm -rf build
答案 0 :(得分:1)
来自上述评论:
在您的更新中,您执行了
mov word [0xb8000], 0x0748
。这将16位字0x0748移动到0xb8000。因为x86是小端,所以当放入存储器时,一个字被存储到最高有效字节的最低有效字节。因此0xb8000将在其中具有0x48并且在0b8001处具有0x07。请参阅上面的评论,关于您将字节颠倒过来。 - Michael Petch 2016年11月21日19:33