将错误的字符写入帧缓冲区

时间:2018-06-20 19:45:47

标签: c assembly x86 framebuffer

我一直在关注一个名为"The little book about OS development"的教程。我可以将单个字符写入帧缓冲区,但不能将下一个字符写入。这些是文件:

kmain.c

#include "io.h"

#define FB_BLACK 0
#define FB_BLUE 1
#define FB_GREEN 2
#define FB_CYAN 3
#define FB_RED 4
#define FB_MAGENTA 5
#define FB_BROWN 6
#define FB_LIGHTGREY 7
#define FB_DARKGREY 8
#define FB_LIGHTBLUE 9
#define FB_LIGHTGREEN 10
#define FB_LIGHTCYAN 11
#define FB_LIGHTRED 12
#define FB_LIGHTMAGENTA 13
#define FB_LIGHTBROWN 14
#define FB_WHITE 15

#define FB_COMMAND_PORT 0x3D4
#define FB_DATA_PORT 0x3D5
#define FB_HIGH_BYTE_COMMAND 14
#define FB_LOW_BYTE_COMMAND 15
char *fb = (char*)0x000B8000;

void fb_move_cursor(unsigned short pos) {
    outb(FB_COMMAND_PORT, FB_HIGH_BYTE_COMMAND);
    outb(FB_DATA_PORT, ((pos >> 8) & 0x00FF));
    outb(FB_COMMAND_PORT, FB_LOW_BYTE_COMMAND);
    outb(FB_DATA_PORT, pos & 0x00FF);
}

void fb_write_cell(unsigned int i, char c, unsigned char fg, unsigned char bg)
{
    fb[i] = c;
    fb[i + 1] = ((fg & 0x0F) << 4) | (bg & 0x0F);
}


void kmain(void) {
    fb_write_cell(0, 'H', FB_WHITE, FB_BLACK);
    fb_move_cursor(2);
    fb_write_cell(1, 'i', FB_WHITE, FB_BLACK);
}

io.h

#ifndef INCLUDE_IOH
#define INCLUDE_IOH


void outb(unsigned short port, unsigned char data);


#endif

io.s

global outb
global hang
;Sends a byte to an io port
; [esp + 8] data byte
; [esp + 4] the io port

outb:
    mov al, [esp + 8]
    mov dx, [esp + 4]
    out dx, al
    ret
hang:
    jmp hang; so that program can hang

loader.s

global loader

MAGIC_NUMBER equ 0x1BADB002    ;Multiboot constant
FLAGS        equ 0x0           ;Multiboot flags
CHKSUM       equ -MAGIC_NUMBER   ;Multiboot checksum. Valid if CHKSUM + FLAGS + MAGIC_NUMBER == 0 


KERNEL_STACK_SIZE equ 4096
section .bss
align 4
kernel_stack:
    resb KERNEL_STACK_SIZE

section .text
align 4
    dd MAGIC_NUMBER
    dd FLAGS
    dd CHKSUM

loader:
    mov esp,kernel_stack+KERNEL_STACK_SIZE
    extern kmain
    call kmain
hang:
    jmp hang

link.ld

ENTRY(loader)                /* the name of the entry label */

SECTIONS {
    . = 0x00100000;          /* the code should be loaded at 1 MB */

    .text ALIGN (0x1000) :   /* align at 4 KB */
    {
        *(.text)             /* all text sections from all files */
    }

    .rodata ALIGN (0x1000) : /* align at 4 KB */
    {
        *(.rodata*)          /* all read-only data sections from all files */
    }

    .data ALIGN (0x1000) :   /* align at 4 KB */
    {
        *(.data)             /* all data sections from all files */
    }

    .bss ALIGN (0x1000) :    /* align at 4 KB */
    {
        *(COMMON)            /* all COMMON sections from all files */
        *(.bss)              /* all bss sections from all files */
    }
}

Makefile

OBJECTS = loader.o kmain.o io.o
CC = gcc
CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector \
     -nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c
LDFLAGS = -T link.ld -melf_i386
AS = nasm
ASFLAGS = -f elf

all: kernel.elf

kernel.elf: $(OBJECTS)
ld $(LDFLAGS) $(OBJECTS) -o kernel.elf

os.iso: kernel.elf
cp kernel.elf iso/boot/kernel.elf
genisoimage -R                \
        -b boot/grub/stage2_eltorito    \
        -no-emul-boot          \
        -boot-load-size 4          \
        -A os              \
        -input-charset utf8      \
        -quiet            \
        -boot-info-table        \
        -o os.iso              \
        iso

run: os.iso
bochs -f bochsrc.txt -q

%.o: %.c
$(CC) $(CFLAGS)  $< -o $@

%.o: %.s
$(AS) $(ASFLAGS) $< -o $@

clean:
rm -rf *.o kernel.elf os.iso

您可以下载项目在here中的文件夹 我希望在左上角看到“ Hi”,但是我看到两个奇怪的字符:incorrect characters打印第一个字符并移动光标可以正常工作,但是当我尝试打印第二个字符时,它弄乱了。

编辑:我意识到第一个字符是错误彩色H。

1 个答案:

答案 0 :(得分:2)

@Margaret Bloom的评论解决了我的问题。问题是一个字符是16位,我需要将I增加2,但是我将其增加1,导致它像这样重叠:

目标:char1Data char1Color char2Data char2Color

问题:char1Data char2Data char2Color