我在网上遵循了一些教程并创建了自己的内核。它正在使用 QEMU 在 GRUB 上成功启动。但是我有这个 SO question中描述的问题,我无法解决它。我可以描述该解决方法,但我还需要使用全局变量,这会使工作更容易,但我不明白我应该在链接器中更改什么以正确使用全局变量和内联字符串。
主程序
struct grub_signature {
unsigned int magic;
unsigned int flags;
unsigned int checksum;
};
#define GRUB_MAGIC 0x1BADB002
#define GRUB_FLAGS 0x0
#define GRUB_CHECKSUM (-1 * (GRUB_MAGIC + GRUB_FLAGS))
struct grub_signature gs __attribute__ ((section (".grub_sig"))) =
{ GRUB_MAGIC, GRUB_FLAGS, GRUB_CHECKSUM };
void putc(unsigned int pos, char c){
char* video = (char*)0xB8000;
video[2 * pos ] = c;
video[2 * pos + 1] = 0x3F;
}
void puts(char* str){
int i = 0;
while(*str){
putc(i++, *(str++));
}
}
void main (void)
{
char txt[] = "MyOS";
puts("where is this text"); // does not work, puts(txt) works.
while(1){};
}
生成文件:
CC = gcc
LD = ld
CFLAGS = -Wall -nostdlib -ffreestanding -m32 -g
LDFLAGS = -T linker.ld -nostdlib -n -melf_i386
SRC = main.c
OBJ = ${SRC:.c=.o}
all: kernel
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
kernel: ${OBJ} linker.ld
@echo CC -c -o $@
@${LD} ${LDFLAGS} -o kernel ${OBJ}
clean:
@echo cleaning
@rm -f ${OBJ} kernel
.PHONY: all
链接器.ld
OUTPUT_FORMAT("elf32-i386")
ENTRY(main)
SECTIONS
{
.grub_sig 0xC0100000 : AT(0x100000)
{
*(.grub_sig)
}
.text :
{
*(.text)
}
.data :
{
*(.data)void main (void)
}
.bss :
{
*(.bss)
}
/DISCARD/ :
{
*(.comment)
*(.eh_frame)
}
}
什么有效:
void main (void)
{
char txt[] = "MyOS";
puts(txt);
while(1) {}
}
什么不起作用:
1)
char txt[] = "MyOS";
void main (void)
{
puts(txt);
while(1) {}
}
2)
void main (void)
{
puts("MyOS");
while(1) {}
}
汇编输出:(外部链接,因为有点长)http://hastebin.com/gidebefuga.pl