直接输出到文本视频内存时的异常内核行为

时间:2017-12-27 11:05:23

标签: gcc x86 kernel screen osdev

我正在研究基本内核。我关注了一些在线课程并开始从头开始编写。我在编写这个内核时看到了不寻常的行为。我在 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。但是,这会产生如下结果:

enter image description here

如果我将公式设为(row*MAX_COLS+col)*2+1,则打印功能正常工作:

enter image description here

我的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

我的同事们也无法确定问题所在。我该如何开始调试呢?

1 个答案:

答案 0 :(得分:1)

我错过了一个事实,我需要在64位系统上精细地编译32位代码。我通过在GCC中添加-m32-fno-PIC标志,在LD上添加-melf_i386并在我的Makefile中的NASM中将elf64更改为elf32来解决了这个问题。