TL;DR的意思是你正在炸毁你的程序堆栈.
我使用宏添加了一些调试printf
调用:dbgprt
- 堆栈地址是0x7be8(在进入内核
main
时)
&buffers[0][0]
是0x5f60
SCREEN_SIZE
是0xfa00
- 低
buffers
的地址范围为0x5f60-0x1f960
- 当我们在
buffers
上做memset
时,我们写的远远超出堆栈的地址.
所讨论的堆栈地址(即0x7be8)是 bootstrap 过程中使用的堆栈地址.在main.asm
中,这是通过以下方式设置的:
mov sp, 0x7C00 ; stack grows downwards from where we are loaded in memory
值为jmpToKernel
时,我们需要将esp
寄存器设置为不与任何内容冲突的值(例如:
mov esp,0x90000
以下是make run
份报告的[编辑]结果:
# qemu-system-i386 -serial file:serial.log -fda build/os-image.img
###qemu-system-i386 -serial stdio -fda build/os-image.img
qemu-system-i386 -serial stdio -fda build/os-image.img
WARNING: Image format was not specified for 'build/os-image.img' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
Unhandled IRQ 0
set_pallette: ENTER
set_pallette: EXIT
SCREEN_SIZE=fa00
STACK=7be8
screen_swap: ENTER
screen_swap: BUFFER=0xa0000 current_buffer=0/0x5f60/0x15960
screen_swap: EXIT
clear_screen: ENTER color=0x1c
clear_screen: BUFFER=0xa0000 current_buffer=1/0x15960/0x25360
clear_screen: EXIT
screen_swap: ENTER
screen_swap: BUFFER=0xa0000 current_buffer=1/0x15960/0x25360
screen_swap: EXIT
clear_screen: ENTER color=0x1c
clear_screen: BUFFER=0xa0000 current_buffer=0/0x5f60/0x15960
qemu-system-i386: Trying to execute code outside RAM or ROM at 0x1c1c1c1c
This usually means one of the following happened:
(1) You told QEMU to execute a kernel for the wrong machine type, and it crashed on startup (eg trying to run a raspberry pi kernel on a versatilepb QEMU machine)
(2) You didn't give QEMU a kernel or BIOS filename at all, and QEMU executed a ROM full of no-op instructions until it fell off the end
(3) Your guest kernel has a bug and crashed by jumping off into nowhere
This is almost always one of the first two, so check your command line and that you are using the right type of kernel for this machine.
If you think option (3) is likely then you can try debugging your guest with the -d debug options; in particular -d guest_errors will cause the log to include a dump of the guest register state at this point.
Execution cannot continue; stopping here.
make: *** [Makefile:37: run] Error 1
以下是我改变的git diff
分:
Edit:%的人为了空间而删除了这个.请参阅下面的更新.
UPDATE:个
我添加了mov esp, 0x90000
,现在我只能写入第二个缓冲区->;buffers[1]
.在内存中是否有不同的位置可以放置堆栈,或者如何存储不在堆栈中的缓冲区?
内塔·科恩
当然了.我只是从我的另一个"构建你自己的操作系统"的答案中得到了这个答案:How can I fix my VBE implementation for my OS?
这是一种黑客行为[以及原著作者正在做的事情].
起初,我打算使用make
过程来定义boot.asm
的地址.然后,我意识到一个更好的方法是让_start
在kernel_entry.asm
设置它.
- 通常的方法是探测内存并获取其大小.然后,将堆栈指针指向RAM中的最后一个可用字.
- 但是,以这种方式探测并捕获保护异常或总线错误在此阶段实现起来有点棘手.
- 因此,使用在
kernel_entry.asm
中定义的静态数组是最简单的方法.
在这样做的过程中,我仍然有一些麻烦,所以我更改了一些不相关的东西来改进调试:
- 更改了类似
printf
的函数以允许(例如%d
、%ld
和%lld
)支持int/long/long long
个数字(这样我就可以打印计时器值).
- 将
printf
更改为使用stdarg.h
- 将"debounce "代码添加到
main
,这样它只会在初始按键时更改背景 colored颜色 (例如,上升沿).
以下是代码的"无崩溃"版本:
diff --git a/Makefile b/Makefile
index 193cb35..e4cb5fa 100644
--- a/Makefile
+++ b/Makefile
@@ -1,17 +1,24 @@
+# tetos/Makefile -- make file for tetos
+#
+# SO: osdev double buffering rebooting system
+# SITE: stackoverflow.com
+# SO: 77524100
+include ./common.mk
ASM=nasm
-CC=/home/neta/opt/cross/bin/i386-elf-gcc
-LD=/home/neta/opt/cross/i386-elf/bin/ld
RM=rm
OBJCOPY=objcopy
-
SRC=src
-BUILD=build
+export BUILD=build
+
+IMGCOUNT = 2880
+KNLCOUNT = 2048
+all: $(BUILD)/os-image.img
$(BUILD)/os-image.img: boot kernel
- dd if=/dev/zero of=$@ bs=512 count=2880
+ dd if=/dev/zero of=$@ bs=512 count=$(IMGCOUNT)
dd if=$(BUILD)/boot.bin of=$@ conv=notrunc bs=512 count=1 seek=0
- dd if=$(BUILD)/kernel.bin of=$@ conv=notrunc bs=512 count=2048 seek=1
+ dd if=$(BUILD)/kernel.bin of=$@ conv=notrunc bs=512 count=$(KNLCOUNT) seek=1
boot: $(BUILD)/boot.bin
@@ -31,6 +38,7 @@ always:
run: $(BUILD)/os-image.img
# qemu-system-i386 -serial file:serial.log -fda $<
+ ###qemu-system-i386 -serial stdio -fda $<
qemu-system-i386 -serial stdio -fda $<
debug: $(BUILD)/os-image.img
@@ -38,6 +46,7 @@ debug: $(BUILD)/os-image.img
# for logs -- log: bochslog.txt
clean:
- @$(MAKE) -C $(SRC)/boot BUILD=$(abspath $(BUILD)) clean
- @$(MAKE) -C $(SRC)/kernel BUILD=$(abspath $(BUILD)) clean
+ rm -fr $(BUILD)
+ @###$(MAKE) -C $(SRC)/boot BUILD=$(abspath $(BUILD)) clean
+ @###$(MAKE) -C $(SRC)/kernel BUILD=$(abspath $(BUILD)) clean
diff --git a/common.mk b/common.mk
new file mode 100644
index 0000000..f0f2b8b
--- /dev/null
+++ b/common.mk
@@ -0,0 +1,18 @@
+# common.mk -- common definitions for make
+
+CC:=/home/neta/opt/cross/bin/i386-elf-gcc
+LD:=/home/neta/opt/cross/i386-elf/bin/ld
+
+ifeq ($(wildcard $(CC)*),)
+ CC:=gcc -m32
+ LD:=ld -melf_i386
+endif
+
+export CC
+export LD
+
+IMGCOUNT = 2880
+KNLCOUNT = 2048
+
+###OBJ := obj
+OBJ := o
diff --git a/src/boot/Makefile b/src/boot/Makefile
index 4c9a266..c6d6f8d 100644
--- a/src/boot/Makefile
+++ b/src/boot/Makefile
@@ -1,12 +1,15 @@
+include ../../common.mk
BUILD?=build/
ASM?=nasm
+###AFLAGS += -DKSTACK_SECTOR=$(KNLCOUNT)
+
.PHONY: all clean
all: $(BUILD)/boot.bin
$(BUILD)/boot.bin: main.asm
- $(ASM) main.asm -f bin -o $(BUILD)/boot.bin
+ $(ASM) main.asm -f bin -o $(BUILD)/boot.bin -l $(BUILD)/boot.lst $(AFLAGS)
clean:
rm -f $(BUILD)/boot.bin
diff --git a/src/boot/main.asm b/src/boot/main.asm
index 9a37335..8cc8d06 100644
--- a/src/boot/main.asm
+++ b/src/boot/main.asm
@@ -51,8 +51,7 @@ jmpToKernel:
mov ds, ax
mov ss, ax
- call KERNEL_OFFSET
- hlt
+ jmp KERNEL_OFFSET
bits 16
EnableA20:
diff --git a/src/kernel/Makefile b/src/kernel/Makefile
index 7bf9326..1e1f7a4 100644
--- a/src/kernel/Makefile
+++ b/src/kernel/Makefile
@@ -1,38 +1,43 @@
+include ../../common.mk
BUILD?=build/
ASM?=nasm
ASMFLAGS?=-f elf
-CC?=/home/neta/opt/cross/bin/i386-elf-gcc
-LD=/home/neta/opt/cross/bin/i386-elf-ld
-LGCC=/home/neta/opt/cross/lib/gcc/i386-elf/13.1.0
+###CC?=/home/neta/opt/cross/bin/i386-elf-gcc
+###LD=/home/neta/opt/cross/bin/i386-elf-ld
+###LGCC=-L /home/neta/opt/cross/lib/gcc/i386-elf/13.1.0
# CCFLAGS= -ffreestanding -nostdlib -c
-CCFLAGS=-m32 -std=c11 -O2 -g -Wall -Wextra -Wpedantic -Wstrict-aliasing
+CCFLAGS+=-m32 -std=c11 -O2 -g -Wall -Wextra
+CCFLAGS+=-Werror
+###CCFLAGS+=-Wpedantic -Wstrict-aliasing
CCFLAGS+=-Wno-pointer-arith -Wno-unused-parameter
-CCFLAGS+=-nostdlib -nostdinc -ffreestanding -fno-pie -fno-stack-protector
+CCFLAGS+=-nostdlib -ffreestanding -fno-pie -fno-stack-protector
+###CCFLAGS+=-nostdinc
CCFLAGS+=-fno-builtin-function -fno-builtin -c -mgeneral-regs-only
-LDFLAGS=-ffreestanding -O2 -nostdlib -m32 -L $(LGCC) -lgcc
+LDFLAGS=-ffreestanding -O2 -nostdlib -m32 $(LGCC) -lgcc
SOURCES_C=$(wildcard *.c)
SOURCES_ASM=$(wildcard *.asm)
-OBJECTS_C=$(patsubst %.c,$(BUILD)/kernel/c/%.obj,$(SOURCES_C))
-OBJECTS_ASM=$(patsubst %.asm,$(BUILD)/kernel/asm/%.obj,$(SOURCES_ASM))
+OBJECTS_C=$(patsubst %.c,$(BUILD)/kernel/c/%.$(OBJ),$(SOURCES_C))
+OBJECTS_ASM=$(patsubst %.asm,$(BUILD)/kernel/asm/%.$(OBJ),$(SOURCES_ASM))
.PHONY: all clean always
-all: kernel.bin
+all: always kernel.bin
kernel.bin: $(OBJECTS_ASM) $(OBJECTS_C)
- $(CC) -T link.ld -o $(BUILD)/kernel.bin $^ $(LDFLAGS)
- # $(LD) -o $(BUILD)/kernel.bin $(LDFLAGS) -Tlink.ld $^
+ @###$(CC) -T link.ld -o $(BUILD)/kernel.bin $^ $(LDFLAGS)
+ $(CC) -Wl,-Map=$(BUILD)/kernel.map -T link.ld -o $(BUILD)/kernel.bin $^ $(LDFLAGS)
+ @# $(LD) -o $(BUILD)/kernel.bin $(LDFLAGS) -Tlink.ld $^
-$(BUILD)/kernel/c/%.obj: %.c always
+$(BUILD)/kernel/c/%.$(OBJ): %.c ###always
$(CC) $(CCFLAGS) -o $@ $<
-$(BUILD)/kernel/asm/%.obj: %.asm always
- $(ASM) $(ASMFLAGS) -o $@ $<
+$(BUILD)/kernel/asm/%.$(OBJ): %.asm ###always
+ $(ASM) $(ASMFLAGS) -o $@ $< -l $(basename $@).lst
always:
mkdir -p $(BUILD)/kernel/c
mkdir -p $(BUILD)/kernel/asm
clean:
- rm -f $(BUILD)/kernel.bin
+ rm -f $(BUILD)/kernel.bin $(BUILD)/kernel.map
diff --git a/src/kernel/hal.c b/src/kernel/hal.c
index 1b5a7b1..433447c 100644
--- a/src/kernel/hal.c
+++ b/src/kernel/hal.c
@@ -7,13 +7,15 @@
#include "keyboard.h"
void HAL_init(){
+ init_serial(); // init the COM1 port (for qemu and bochs)
+
IDT_init(); // init the IDT
ISR_init(); // init the ISR's
IRQ_init(); // init the IRQ's and pic
timer_install(); // register timer in irq
+#if 1
keybrd_install(); // register keyboard in irq
-
- init_serial(); // init the COM1 port (for qemu and bochs)
+#endif
write_serial('\n'); // print a new line to seperate the qemu things
diff --git a/src/kernel/irq.c b/src/kernel/irq.c
index d3ac3fa..6140a4d 100644
--- a/src/kernel/irq.c
+++ b/src/kernel/irq.c
@@ -10,7 +10,9 @@ void IRQ_handler(Registers_t *regs){
u8 irq = regs->interrupt - PIC_OFFSET;
if (g_IRQHandlers[irq] != 0){
+ //dbgprt("IRQ_handler: ENTER irq=%u\n",irq);
g_IRQHandlers[irq](regs);
+ //dbgprt("IRQ_handler: EXIT\n");
} else {
QemuPrintf("Unhandled IRQ %d\n", irq);
}
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index 7136655..4dbf35a 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -9,19 +9,62 @@
void main(){
HAL_init();
set_palette();
+ dbgprt("SCREEN_SIZE=0x%x\n",SCREEN_SIZE);
+ dbgprt("STACK=0x%x\n",__builtin_frame_address(0));
screen_swap();
+#if 0
clear_screen(COLOR(0,0,0));
+#else
+ clear_screen(COLOR(0,255,0));
+#endif
screen_swap();
+ clear_screen(COLOR(0,255,0));
+ screen_swap();
+
+ u64 otimer = get_timer();
+ dbgprt("main: OTIMER otimer=%llu\n",otimer);
+
+ u32 kcount = 0;
+ u8 color = 0;
+ bool kpress_old = 0;
+ bool kpress_cur = 0;
+
+ while (true) {
+ //dbgprt("main: ENTER/GTIMER\n");
+ u64 ctimer = get_timer();
+ //dbgprt("main: EXIT/GTIMER\n");
- while (true){
- if (is_key_pressed('a')){
- clear_screen(COLOR(255,0,0));
+ if (ctimer != otimer) {
+ //dbgprt("\rmain: CTIMER %llu\n",ctimer);
+ otimer = ctimer;
+ }
+
+ kpress_cur = is_key_pressed('a');
+
+ if ((kpress_cur != kpress_old) && kpress_cur) {
+ dbgprt("\n");
+ dbgprt("main: KTIMER kcount=%u ctimer=%llu\n",ctimer);
+ switch (kcount % 3) {
+ case 0:
+ color = COLOR(255,0,0);
+ break;
+ case 1:
+ color = COLOR(0,255,0);
+ break;
+ default:
+ color = COLOR(0,0,255);
+ break;
+ }
+ ++kcount;
+ clear_screen(color);
screen_swap();
}
+
+ kpress_old = kpress_cur;
}
- while(1){
+ while (1) {
__asm__ volatile("hlt");
}
}
diff --git a/src/kernel/kernel_entry.asm b/src/kernel/kernel_entry.asm
index d9a22bf..8e3e9c7 100644
--- a/src/kernel/kernel_entry.asm
+++ b/src/kernel/kernel_entry.asm
@@ -1,8 +1,31 @@
[bits 32]
[extern main]
+KSTACK_SIZE equ 64 * 1024 ; stack size 64 KB
+
+extern __end
+
section .entry
global _start
_start:
+ ;;;mov esp,__end ; this didn't work too well
+ mov esp,__stack ; point to start of stack
+
+ add esp,KSTACK_SIZE ; point past the end
+
+ ; get mask to align to 16 byte boundary
+ mov eax,0x0f
+ not eax
+
+ ; align stack
+ and esp,eax
+
+ ; point stack pointer to last valid part of stack
+ sub esp,16
+
call main
hlt
+
+section .bss
+__stack:
+ times KSTACK_SIZE db 0
diff --git a/src/kernel/keyboard.h b/src/kernel/keyboard.h
index 8091212..8476a61 100644
--- a/src/kernel/keyboard.h
+++ b/src/kernel/keyboard.h
@@ -88,6 +88,7 @@ enum KEYBOARD_SPECIAL_KEYS {
DOWN = 0x80
};
+void keybrd_install();
bool is_special_key(u8 key); // check in mode if key is pressed
bool is_key_pressed(u8 key); // check if key is pressed
diff --git a/src/kernel/printf.c b/src/kernel/printf.c
index 435d799..af5f85e 100644
--- a/src/kernel/printf.c
+++ b/src/kernel/printf.c
@@ -1,4 +1,5 @@
#include "util.h"
+#include <stdarg.h>
// define qemu logs
void QemuPrintStr(i8* s){
@@ -9,12 +10,12 @@ void QemuPrintStr(i8* s){
// convert binary number to ascii
const i8 g_chars[] = "0123456789abcdef";
-void printf_unsigned(u32 num, u32 base){
+void printf_unsigned(u64 num, u32 base){
i8 string[32];
i32 pos = 0;
do {
- u32 rem = num % base;
+ u64 rem = num % base;
num /= base;
string[pos++] = g_chars[rem];
} while (num > 0);
@@ -24,7 +25,7 @@ void printf_unsigned(u32 num, u32 base){
}
}
-void printf_signed(i32 num, u32 base){
+void printf_signed(s64 num, u32 base){
if (num < 0){
write_serial('-'); // changed
printf_unsigned(-num, base);
@@ -36,11 +37,22 @@ void printf_signed(i32 num, u32 base){
#define STATE_NORMAL 0
#define STATE_FORMAT 1
void QemuPrintf(const i8* str, ...){
+#if 0
u32* argp = (u32*)&str;
+#endif
u8 state = STATE_NORMAL;
+ int llflg;
+#if 0
argp += sizeof(str)/sizeof(u32);
+#else
+ va_list ap;
+ va_start(ap,str);
+ u64 uval;
+ s64 sval;
+#endif
+
while (*str){
switch (state){
case STATE_NORMAL: // wait for % or print
@@ -55,35 +67,59 @@ void QemuPrintf(const i8* str, ...){
}
// fall through
case STATE_FORMAT: // check what char is after %
+ llflg = 0;
+ if (*str == 'l') {
+ ++llflg;
+ ++str;
+ }
+ if (*str == 'l') {
+ ++llflg;
+ ++str;
+ }
+
switch (*str){
case '%':
write_serial('%'); // changed
break;
case 'c': // print char
- write_serial((char)*argp); // changed
- argp++;
+ write_serial(va_arg(ap,int)); // changed
break;
case 's': // print string
- QemuPrintStr((char*)*argp);
- argp++;
+ QemuPrintStr(va_arg(ap,char *));
break;
case 'd': // print signed base 10
- printf_signed((i32)*argp, 10);
- argp++;
+ switch (llflg) {
+ case 0:
+ sval = va_arg(ap,i32);
+ break;
+ case 1:
+ sval = va_arg(ap,long);
+ break;
+ default:
+ sval = va_arg(ap,long long);
+ break;
+ }
+ printf_signed(sval, 10);
break;
case 'u': // print unsigned base 10
- printf_unsigned((u32)*argp, 10);
- argp++;
- break;
-
case 'x':
case 'p': // print unsigned base 16
- printf_unsigned((u32)*argp, 16);
- argp++;
+ switch (llflg) {
+ case 0:
+ uval = va_arg(ap,u32);
+ break;
+ case 1:
+ uval = va_arg(ap,unsigned long);
+ break;
+ default:
+ uval = va_arg(ap,unsigned long long);
+ break;
+ }
+ printf_unsigned(uval, (*str == 'u') ? 10 : 16);
break;
default: break; // ignore invalid char
@@ -93,5 +129,10 @@ void QemuPrintf(const i8* str, ...){
}
str++;
}
+
+#if 1
+ va_end(ap);
+#endif
+
return;
}
diff --git a/src/kernel/screen.c b/src/kernel/screen.c
index 45f1de1..3713ad3 100644
--- a/src/kernel/screen.c
+++ b/src/kernel/screen.c
@@ -7,21 +7,39 @@ static u8 *BUFFER = (u8*) 0xA0000;
u8 buffers[2][SCREEN_SIZE];
u8 current_buffer = 0;
+#if 0
#define CURRENT (buffers[current_buffer])
+#else
+#define CURRENT (&buffers[current_buffer][0])
+#endif
+#if 0
#define SWAP() (current_buffer = 1 - current_buffer)
+#else
+#define SWAP() current_buffer = current_buffer ? 0 : 1
+#endif
#define VGA_MASK 0x3c6
#define VGA_READ_ADD 0x3c7
#define VGA_WRITE_ADD 0x3c8
#define VGA_DATA 0x3c9
+#define CURRENT_SHOW \
+ dbgprt("%s: BUFFER=0x%x current_buffer=%d/0x%x/0x%x\n", \
+ __FUNCTION__,BUFFER,current_buffer,CURRENT,CURRENT + SCREEN_SIZE)
+
void screen_swap(){
+ dbgprt("screen_swap: ENTER\n");
+ //CURRENT_SHOW;
memcpy(BUFFER, CURRENT, SCREEN_SIZE);
SWAP();
+ dbgprt("screen_swap: EXIT\n");
}
void clear_screen(u8 color){
- memset(&CURRENT, color, SCREEN_SIZE);
+ dbgprt("clear_screen: ENTER color=0x%x\n",color);
+ CURRENT_SHOW;
+ memset(CURRENT, color, SCREEN_SIZE);
+ dbgprt("clear_screen: EXIT\n");
}
void plot_pixel(i32 x, i32 y, u8 color){
@@ -30,6 +48,7 @@ void plot_pixel(i32 x, i32 y, u8 color){
}
void set_palette(){
+ dbgprt("set_pallette: ENTER\n");
outb(VGA_WRITE_ADD, 0);
for(u8 i=0; i < 255; i++){
// we shift it by 2 because each color is 6 bits
@@ -43,6 +62,7 @@ void set_palette(){
outb(VGA_DATA, 0xff >> 2);
outb(VGA_DATA, 0xff >> 2);
outb(VGA_DATA, 0xff >> 2);
+ dbgprt("set_pallette: EXIT\n");
}
u8 COLOR(u8 r, u8 g, u8 b){
diff --git a/src/kernel/timer.c b/src/kernel/timer.c
index 748de08..7e283c0 100644
--- a/src/kernel/timer.c
+++ b/src/kernel/timer.c
@@ -2,36 +2,38 @@
#include "util.h"
#include "irq.h"
-static struct {
- u32 divisor;
- u32 frequency;
- u64 ticks;
-} state;
-
/* u64 timer = 0; */
void timerFunction(Registers_t *regs){
- state.ticks++;
+ timer_state.ticks++;
+ //dbgprt("timerFunction: ticks=%llu\n",timer_state.ticks);
}
void PIT_setCount(){
// set the frequency of the pit to 1/TIMER_FREQ
- state.divisor = TIMER_FREQ;
- state.frequency = PIT_INTERNAL_FREQUENCY / state.divisor; // get the desired freq
+ timer_state.divisor = TIMER_FREQ;
+ timer_state.frequency = PIT_INTERNAL_FREQUENCY / timer_state.divisor; // get the desired freq
CLI();
outb(PIT_COMMAND, PIT_SET);
- outb(PIT_CHANNEL0, state.frequency & 0xff); // low byte
- outb(PIT_CHANNEL0, ((state.frequency & 0xff00) >> 8)); // high byte
+ outb(PIT_CHANNEL0, timer_state.frequency & 0xff); // low byte
+ outb(PIT_CHANNEL0, ((timer_state.frequency & 0xff00) >> 8)); // high byte
STI();
return;
}
u64 get_timer(){
- return state.ticks;
+ return timer_state.ticks;
}
void timer_install(){
+ dbgprt("timer_install: ENTER\n");
+#if 0
PIT_setCount();
IRQ_RegisterHandler(0, timerFunction);
+#else
+ IRQ_RegisterHandler(0, timerFunction);
+ PIT_setCount();
+#endif
+ dbgprt("timer_install: EXIT\n");
}
diff --git a/src/kernel/timer.h b/src/kernel/timer.h
index 9d6de1e..daecf36 100644
--- a/src/kernel/timer.h
+++ b/src/kernel/timer.h
@@ -13,6 +13,14 @@
#define PIT_SET 0x36
+struct timer {
+ u32 divisor;
+ u32 frequency;
+ u64 ticks;
+};
+
+struct timer timer_state;
+
void timer_install();
u64 get_timer();
diff --git a/src/kernel/util.h b/src/kernel/util.h
index df2e92b..4935576 100644
--- a/src/kernel/util.h
+++ b/src/kernel/util.h
@@ -10,6 +10,8 @@ typedef char i8;
typedef short i16;
typedef int i32;
typedef long long i64;
+typedef int s32;
+typedef long long s64;
typedef u32 size_t;
typedef u32 uintptr_t;
typedef float f32;
@@ -41,6 +43,9 @@ typedef u8 bool;
void QemuPrintStr(i8* s);
void QemuPrintf(const i8* str, ...);
+#define dbgprt(_fmt...) \
+ QemuPrintf(_fmt)
+
// communiation via ports --> io.c
int init_serial();
void write_serial(char a);