【发布时间】:2016-12-20 14:02:15
【问题描述】:
我想在我的 c 代码中实现头文件,其中部分包含用于 16 位实模式的 GCC 内联汇编代码,但我似乎有链接问题。这是我的头文件console.h 的样子:
#ifndef CONSOLE_H
#define CONSOLE_H
extern void kprintf(char*);
#endif
这是console.c:
#include "console.h"
void kprintf(char *string)
{
for(int i=0;string[i]!='\0';i++)
{
asm("mov $0x0e,%%ah;"
"mov $0x00,%%bh;"
"mov %0,%%al;"
"int $0x10"::"g"(string[i]):"eax", "ebx");
}
}
最后一个hellworld.c:
asm("jmp main");
#include "console.h"
void main()
{
asm("mov $0x1000,%ax;"
"mov %ax,%es;"
"mov %ax,%ds");
char string[]="hello world";
kprintf(string);
asm(".rept 512;"
"hlt;"
".endr");
}
我的引导程序在bootloader.asm:
org 0x7c00
bits 16
section .text
mov ax,0x1000
mov ss,ax
mov sp,0x000
mov esp,0xfffe
xor ax,ax
mov es,ax
mov ds,ax
mov [bootdrive],dl
mov bh,0
mov bp,zeichen
mov ah,13h
mov bl,06h
mov al,1
mov cx,6
mov dh,010h
mov dl,01h
int 10h
load:
mov dl,[bootdrive]
xor ah,ah
int 13h
jc load
load2:
mov ax,0x1000
mov es,ax
xor bx,bx
mov ah,2
mov al,1
mov cx,2
xor dh,dh
mov dl,[bootdrive]
int 13h
jc load2
mov ax,0
mov es,ax
mov bh,0
mov bp,zeichen3
mov ah,13h
mov bl,06h
mov al,1
mov cx,13
mov dh,010h
mov dl,01h
int 10h
mov ax,0x1000
mov es,ax
mov ds,ax
jmp 0x1000:0x000
zeichen db 'hello2'
zeichen3 db 'soweit so gut'
bootdrive db 0
times 510 - ($-$$) hlt
dw 0xaa55
现在我使用下面的 buildscript build.sh:
#!bin/sh
nasm -f bin bootloader.asm -o bootloader.bin
gcc hellworld.c -m16 -c -o hellworld.o -nostdlib -ffreestanding
gcc console.c -m16 -c -o console.o -nostdlib link.ld -ffreestanding
ld -melf_i386 -Ttext=0x0000 console.o hellworld.o -o hellworld.elf
objcopy -O binary hellworld.elf hellworld.bin
cat bootloader.bin hellworld.bin >disk.img
qemu-system-i386 disk.img
和链接脚本link.ld:
/*
* link.ld
*/
OUTPUT_FORMAT(elf32-i386)
SECTIONS
{
. = 0x0000;
.text : { *(.startup); *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
不幸的是,它无法正常工作,因为它没有打印出预期的hello world。我认为链接命令一定有问题:
ld -melf_i386 -Ttext=0x0000 console.o hellword.o link.ld -o hellworld.elf`
如何正确链接 16 位模式的头文件?
当我直接在hellworld.c 中编写kprintf 函数时,它工作正常。我正在使用Linux Mint Cinnamon Version 18 64 bit 进行开发。
【问题讨论】:
-
引导加载程序是否工作? qemu 是否不允许您附加调试器以便您可以单步执行代码?
-
引导加载程序可以正常工作,因为正如我所说,当我在
hellworld.c中给出函数定义时,它会打印出`“hello world”` -
你能不能告诉我调试的命令是什么
-
如果您有多个 .o 文件,您如何知道您的
asm("jmp main");代码是在正确的位置生成的?如果你的 console.o 代码被添加到它前面怎么办。也许您的链接器脚本需要一个 `STARTUP(hellworld.o) 指令。 -
如果我改变他们的位置或忽略
asm("jmp main")问题仍然存在也没关系
标签: gcc x86 header-files x86-16 osdev