2016-07-06 7 views
1

GCCと小さなアセンブラブートストラップルーチンを使ってブートローダーを書いています。私はputsルーチンを書いて、文字列を正しく書いていないようなBIOS割り込みを使ってディスプレイに文字列を表示します。私のputs関数が16ビットコードで動作していません

私のブートストラップアセンブラファイルboot.sが含まれています:main.c

.code16 .section .text 

.extern main 
.globl start 
start: 

    mov  $0x7c0,  %ax 
    mov  %ax,  %ds 
    mov  %ax,  %es 
    mov  %ax,  %fs 
    mov  %ax,  %gs 

    jmp  main 

here: 
    hlt 
    jmp here 

マイCコードは次のとおりです。

/* 
* A 16 bit bootloader. 
*/ 

void putchar_bios(unsigned char ch); 
void set_videomode(unsigned short mode); 
void puts(char str[]); 

#define set_stack(ss, size)          \ 
{                \ 
    __asm__ __volatile__ (          \ 
      "mov  %%ax,  %%ss\n"       \ 
      "mov  $512,  %%sp\n" : : "a" (ss), "r" (size)\ 
     );              \ 
} 

#define set_videomode(mode)          \ 
{                \ 
    __asm__ __volatile__ (          \ 
      "int $0x10\n" : : "a" (mode)      \ 
     );              \ 
} 

void putchar_bios(unsigned char ch) 
{ 
    __asm__ __volatile__ (
      "int $0x10\n" : : "a" (0x0E | ch) 
     ); 
} 

void puts(char *str) 
{ 
    while(*str) 
     putchar_bios(*str++); 
} 

void main() 
{ 
    set_stack(0x07C0, 512); 
    set_videomode(0x03); 

    char name[] = "00"; 
    puts(name); 

    //This works fine. 
    // for(i=0; i<15; i++) 
    //  putchar_bios(name[i]); 
    while(1); 
} 

私が正常にアセンブリに完全にこれを行ってきたが、今私がしようとしていますそれをGCCに移行してください。私はクロスコンパイラ(i386-gcc)を使用しており、-m16フラグも使用しています。私はカスタムリンカースクリプトを使用しました。

OUTPUT_FORMAT("binary"); 
ENTRY(start); 
SECTIONS 
{ 
    . = 0x7C00; 
    .text : AT(0x7C00) { 
     *(.text); 
    } 
    .data : SUBALIGN(0) { 
     *(.data); 
     *(.rodata); 
    } 
    .bss : SUBALIGN(4) { 
     __bss_start = .; 
     *(.COMMON); 
     *(.bss) 
     . = ALIGN(4); 
     __bss_end = .; 
    } 
    __bss_sizel = SIZEOF(.bss)>>2; 
    __bss_sizeb = SIZEOF(.bss); 

    /* Boot signature */ 
    .sig : AT(0x7DFE) { 
     SHORT(0xaa55); 
    } 
} 

私は、リンクをコンパイルしQEMUで実行するために使用するスクリプトは、次のとおりです。

i386-elf-gcc -m16 -static -ffreestanding -nostdlib -c boot/boot.s 
i386-elf-gcc -m16 -static -ffreestanding -nostdlib -c boot/main.c 
i386-elf-ld -T link.ld -o b.bin -nostdlib --nmagic boot.o main.o 
dd if=b.bin of=HD.img conv=notrunc 
#add some noticable garbage to second sector since I also try to read it next 
echo "This is the second sector..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................." | dd seek=512 bs=1 of=HD.img 

qemu-system-i386 -hda HD.img # -boot a -s -S 

はなぜ私のプログラムは正しく私のputs機能を経由して文字列を表示しないのですか?

+0

「puts」という名前のコンパイラが組み込まれていて、それが何か別の名前に変更された場合、それはうまく動作しますか? int 0x10 ah = 0x13もあります。その代わりに文字列を一度に印刷することができます。 – Rup

+0

私はクロスコンパイラを使っているので名前が衝突しないし、そのような機能はない[全く標準ライブラリがない。]そして、私は自立して(BIOSを使用せずに)、私はBIOS機能を使用しませんでした –

+2

OK。ドキュメントから '-nostdlib'が自動的に' -fno-builtin'を意味することは明らかではありません。 – Rup

答えて

1

私はセグメントレジスタの値をいくつかのゴミ(0x7c0)に設定して、これが起こることを認識しました。アセンブリファイルを変更してセグメントレジスタをゼロにしました。コードは次のようになります:

.code16 
.section .text 

.extern main 
.globl start 
start: 

    xor  %ax,  %ax 
    mov  %ax,  %ds 
    mov  %ax,  %es 
    mov  %ax,  %fs 
    mov  %ax,  %gs 

    jmp  main 

here: 
    hlt 
    jmp here 

私は、コンパイラがセグメントレジスタを自動的に初期化すると予想しましたが、そうではありませんでした。

関連する問題