我正在研究基本内核。我关注了一些在线课程并开始从头开始编写。我在编写这个内核时看到了不寻常的行为。我在 C 中编写内核,在汇编中编写bootloader。源代码可用here。
问题:
打印*const char*
时我发现0索引会产生一些垃圾值,而真正的字符串只能从索引1中看到。我决定坚持这个黑客并继续编写内核,希望我能解决这个问题稍后。
当我开始编写用于更新打印例程中光标位置的例程时,我遇到了另一个问题。我更新了代码,使用光标位置作为我之前使用的x-y坐标的偏移量。令我惊讶的是,索引现在从2而不是1开始。
/** print msg at (x,y) or cursor */
void print_at(const char* msg, int x, int y){
unsigned char *video = (unsigned char *)VIDEO_ADDRESS;
unsigned int offset = 0, i = 1; // i=1?
// decide offset value
if(x>=0||y>=0){
// get offset from coordinates
offset = get_offset(x,y);
}else{
// get cursor
offset = get_cursor();
i+=1; // i=2?
}
while(1){
char c = msg[i];
if(c==0){
// end of string
break;
}else if(c=='\n'||(offset/(2*MAX_ROWS)==MAX_COLS)){
// go to next line
offset = get_offset((offset/(2*MAX_COLS)),MAX_COLS-1);
}else{
// print the character
video[offset] = c;
video[offset+1] = WHITE_ON_BLUE;
}
offset+=2;i++;
}
update_cursor(offset);
}
我的 get_offset(int row,int col)例程表现异常。偏移的正常计算应为(row*MAX_COLS+col)*2
。但是,这会产生如下结果:
如果我将公式设为(row*MAX_COLS+col)*2+1
,则打印功能正常工作:
我的Makefile是:
# Makefile for OS
# Note: $^ = all dependencies, $< = first dependency, $@ = target
# Generate list of sources using wildcards
C_SOURCES= $(wildcard drivers/*.c kernel/*.c)
HEADERS = $(wildcard drivers/*.h kernel/*.h)
# List of objects to build
OBJ = ${C_SOURCES:.c=.o}
all: os-image
# run
run: all
qemu-system-i386 -drive format=raw,file=os-image
# debug mode
debug: all
qemu-system-i386 -s -S -drive format=raw,file=os-image
# build
os-image: boot/boot_sect.bin kernel.bin
cat $^ > os-image
kernel.bin: kernel/kernel_entry.o ${OBJ}
ld -o $@ -Ttext 0x1000 $^ --oformat binary
# Generic rule for compiling C code to an object file
# For simplicity , the C files depend on all header files .
%.o : %.c ${HEADERS}
gcc -ffreestanding -c $< -o $@
# Assemble the kernel_entry .
%.o : %.asm
nasm $< -f elf64 -o $@
%.bin : %.asm
nasm $< -f bin -o $@
clean :
rm -rf *.bin *.dis *.o os-image
rm -rf kernel/*.o boot/*.bin drivers/*.o
我的同事们也无法确定问题所在。我该如何开始调试呢?
答案 0 :(得分:1)
我错过了一个事实,我需要在64位系统上精细地编译32位代码。我通过在GCC中添加-m32
和-fno-PIC
标志,在LD上添加-melf_i386
并在我的Makefile中的NASM中将elf64
更改为elf32
来解决了这个问题。>