gcc - 64 位内核奇怪的行为
问题描述
我很难理解这个问题:
我有这段代码被引导加载程序调用,但是当我编译并运行应该打印 HELLO 的测试时,可能会发生以下三件事之一:
如果我声明另一个无符号类型的变量,代码将只打印字符串的一半(HE)。
如果我声明另一种类型的 var,它根本不会打印任何东西()。
如果我不声明任何东西,代码会很好用(你好)。
主程序
#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]);
}
}
构建.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;
代码效果很好。
我对组装不太了解,也许我错过了有关如何管理内存的重要信息。
解决方案
迈克尔·佩奇的回答
查看您的 kernel.bin 文件内部,HELLO 字符串似乎部分位于前 512 个字节中,其余部分位于外部。当您添加或删除代码时,它会改变该字符串的放置位置(无论它是否在前 512 个字节中),这可能是您的代码行为不同的原因。您肯定必须阅读超过 1 个扇区才能解决此问题。
问题是加载器文件只读取 kernel.bin 的一个扇区,所以我试图打印的字符串只是部分加载。解决方案是修改引导加载程序,使其加载足够的扇区来运行代码。
[编辑]
正如 Michael Petch 建议在 buildscript 中添加 -z max-page-size=0x1000
的ld
那样,大大减少了 .bin 文件的大小。
推荐阅读
- javascript - 将 webpack 从版本“^4.30.0”更新到“^5.16.0”我收到路径和进程的奇怪错误
- unity3d - Unity 中可查询的动态纹理
- react-native - Flatlist 选择所有收藏夹,而不是一个
- node.js - 使用 Mongoose 进行索引
- go - break 如何在无限循环中工作?
- angular - Angular 中的 iframe
- php - 如何在 wordpress 中获取单个帖子的查看次数?
- html - HTML浏览器打印不尊重css风格
- laravel - Laravel (Echo, Sanctum, websockets) + Pusher + Nuxtjs SPA
- javascript - 如何制作一个使用javascript搜索网站中特定字段的搜索栏?