2016-07-06 30 views
1

Ich schreibe einen Bootloader mit GCC und eine kleine Assembler-Bootstrap-Routine. Ich habe eine puts Routine geschrieben, die eine Zeichenfolge auf die Anzeige mit BIOS-Interrupts druckt, die keine Zeichenfolgen richtig zu schreiben scheint.Meine Puts-Funktion funktioniert nicht in 16-Bit-Code

Meine Bootstrap-Assembler-Datei boot.s enthält:

.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 

Mein C Code in main.c ist:

/* 
* 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); 
} 

ich erfolgreich diese vollständig in der Montage getan haben, aber jetzt versuche ich zu migrieren Sie es zu GCC. Ich verwende einen Cross-Compiler (i386-gcc) und verwendet auch -m16 Flag. Ich habe ein benutzerdefiniertes Linker-Skript verwendet.

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); 
    } 
} 

Das Skript, das ich zu kompilieren verwendet, Link und laufen in QEMU sind:

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 

Warum über meine puts Funktion richtig funktioniert mein Programm nicht Strings angezeigt werden?

+0

Jede Chance, dass es mit einem integrierten Compiler namens 'puts' kollidiert, d. H. Funktioniert es, wenn Sie es in etwas anderes umbenennen? Es gibt auch int 0x10 ah = 0x13, die Sie stattdessen verwenden könnten, um die Zeichenfolge auf einmal zu drucken. – Rup

+0

Keine Namen kollidieren nicht, da ich einen Cross Compiler verwende und keine solche Funktion hat [Keine Standardbibliothek.]. Und ich werde selbstständig sein (ohne BIOS zu verwenden), also habe ich die BIOS-Funktionen –

+2

OK nicht verwendet. Aus der Dokumentation geht nicht hervor, dass "-nostdlib" automatisch "-fno-builtin" bedeutet. – Rup

Antwort

1

Ich erkannte, dass ich die Werte der Segmentregister auf einige Müll (0x7c0) gesetzt, die dies verursacht haben. Ich habe meine Assembly-Datei modifiziert, um die Segmentregister auf Null zu setzen. Der Code sieht jetzt aus wie:

.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 

ich, dass die Compiler automatisch die Segmentregister initialisieren würden erwartet hatte, aber es war nicht.