2016-12-18 17 views
0

Привет, у меня снова есть проблема, я пытаюсь написать ядро ​​с языком сборки GNU, но у меня есть некоторые проблемы. Мой файл ядра versuch.c выглядеть так:ядро ​​в c встроенной сборке

void kprintf(char hello[]) 
    { 
    /*char* video=(char*)0xb8000; 
for(int i=0;hello[i]!='\0';i++) 
{ 
    video[i*2]=hello[i]; 

    video[i*2+1]=0x06; 

}*/ 
    asm("mov %0,%%si"::""(hello)); 
    //asm("mov 'a',%al;"); 
    asm("call Schreibe;"  
     "Schreibe:;" 
     "lodsb;" 
     "cmp $0x00,%al;" 
     "je Schreibeende;" 
     "mov $0x0e,%ah;" 
     "mov $0x00,%bh;" 
     "int $0x10;" 
     "jmp Schreibe;" 
     "Schreibeende:;" 
     "ret"); 

} 

void main() 
{ 
    asm("jmp 0x10000"); 
    char hello[]="hallo"; 
    kprintf(hello); 
    asm(".rept 512;" 
     " hlt ;" 
     ".endr"); 
}` 

и мой Загрузчик bootloader.asm:

org 0x7c00 
bits 16 



    section .text 

xor ax,ax 
mov ss,ax 
xor sp,sp 

;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 

, когда я использую команды: gcc -c versuch.c objcopy -O binary versuch.o versuch.bin cat bootloader.bin versuch.bin>myOS.bin qemu-system-i386 myOS.bin вы можете увидеть, что она проходит через загрузчик до конца распечатывает «soweit so gut», но он не отображает versuch.c (ядро) текст «hallo». Может, кто-то знает, что я сделал не так здесь!

Дело в том, что код ядра я был до того, который был лишь немного изменен на код выше, по крайней мере распечатал символ после «soweit так кишка», который показывает, что код ядра был каким-то образом выполняется и

mov $0xe,%ah 
mov $0x0,%bh 
int $0x10 

был запущен. Но когда я смотрю на hexcode из myOS.bin Теперь с помощью objdump -Mi8086 -mi386 -bbinary -D myOS.bin я получаю:

28: b8 00 10 8e c0   mov $0xc08e1000,%eax 
    2d: 31 db     xor %ebx,%ebx 
    2f: b4 02     mov $0x2,%ah 
    31: b0 01     mov $0x1,%al 
    33: b9 02 00 30 f6   mov $0xf6300002,%ecx 
    38: 8a 16     mov (%esi),%dl 
    3a: 76 7c     jbe 0xb8 
    3c: cd 13     int $0x13 

который является mov ah,0x1000xor bx,bx диск чтения часть загрузчика и

60: e9 9d 83 68 65   jmp 0x65688402 

, который является частью jmp 0x10000 и

27d: b4 0e     mov $0xe,%ah 
27f: b7 00     mov $0x0,%bh 
281: cd 10     int $0x10 

, который является частью записи, поэтому каким-то образом он должен перегружать часть записи, но она находится в файле myOS.bin. И, как я сказал, когда мой код немного отличался от строки, он что-то потушил! У вас есть совет, что я мог бы изменить?

Недавно я изменил код ядра versuch.c, а команда и код загрузчика остались прежними.

код ядра (versuch.c):

void kprintf() 
{ 
    char* video=(char*)0xb8000; 
    for(int i=0;video[i]!=0;i++) 
    { 
     video[i*2]=0x00; 
     video[i*2+1]=0x06; 
    } 
} 
void main() 
{ 
    asm("jmp 0x10000"); 
    asm("mov $0x1000,%eax;" 
     "mov %eax,%es;" 
     "mov %eax,%ds"); 
    asm("mov $0x0e,%ah;" 
     "mov $0x00,%bh;" 
     "mov 'Q',%al;" 
     "int $0x10"); 
    asm(".rept 512;" 
     " hlt ;" 
     ".endr"); 
} 

теперь, кажется, чтобы переключиться в режим видео показывает мигающий курсор, но это не распечатать «Q».

я наконец-то напечатать письмо со следующим кодом ядра: versuch.c:

void kprintf() 
{ 
    char* video=(char*)0xb8000; 
    for(int i=0;video[i]!=0;i++) 
    { 
     video[i*2]=0x00; 
     video[i*2+1]=0x06; 
    } 
} 
void main() 
{ 
    asm("jmp 0x10000"); 
    asm("mov $0x1000,%eax;" 
     "mov %eax,%es;" 
     "mov %eax,%ds"); 
    asm("mov $0x0e,%ah"); 
    asm("mov $0x00,%bh"); 
    asm("mov %0,%%al":: "" ('T')); 
    asm("int $0x10"); 
    asm(".rept 512;" 
     " hlt ;" 
     ".endr"); 
} 

но когда я добавить еще одну функцию его снова не работает, что очень странно.

Мой новый код ядра выглядит следующим образом:

asm("jmp main"); 



void main() 
{ 
    char* video=(char*)0xb000; 
    for(int i=0;video[i]!=0;i++) 
     video[i]=0x07; 
    asm("mov $0x1000,%eax;" 
     "mov %eax,%es;" 
     "mov %eax,%ds"); 
    char string[]="hall0"; 
    //kprintf(string); 
    for(int i=0;i<5;i++) 
    { 

    asm("mov $0x0e,%ah"); 
    asm("mov $0x00,%bh"); 
    asm("mov %0,%%al":: "" ('a')); 
    asm("int $0x10"); 
    } 

    asm(".rept 512;" 
     " hlt ;" 
     ".endr"); 
} 

я использовал следующие команды: gcc kernel.c -m16 -c kernel.o -nostdlib -ffreestanding ld -melf_i386 kernel.o -o versuch.elf и я использую Mint Linux 64-битной машине, и я получаю сообщение об ошибке: no eh_frame_hdr_table will be created

+0

Комментарии для расширенного обсуждения; этот разговор был [перемещен в чат] (http://chat.stackoverflow.com/rooms/130996/discussion-on-question-by-albert-kernel-in-c-inline-assembly). – Flexo

ответ

2

Какой компилятор C вы используете?

32-разрядный или даже 64-разрядный компилятор?

(Потому что вы просто использовать gcc, а не что-то вроде x86-16bit-gcc я думаю, что вы используете 32-разрядную или 64-битный компилятор.)

Это не будет работать - вам придется переключиться на защищенный режим, чтобы иметь возможность запускать 32-разрядный код. Запуск 64-битного кода еще сложнее.

Даже если вы используете встроенную сборку «только», сам компилятор добавит некоторые инструкции - и это 32-разрядные или 64-разрядные инструкции!

Или вы действительно используете 16-битный компилятор?

В этом случае вам нужно быть очень осторожным: какую модель памяти вы используете и какие побочные эффекты у вас есть?

Пример: Использование "вблизи" модели памяти строки:

video=(char*)0xb8000; 

... усекает адрес 0xb8000 к 16-битному значению (0x8000).

Использование «далекой» модели памяти, однако 0xb8000 обычно рассматривается как 0x000b: 0x8000 (что равно линейному адресу 0x13000) на большинство компиляторов. Для этих компиляторов значение 0xb8000000 должно использоваться для доступа к 0xb800: 0x0000 (линейный адрес 0xB8000).

Использование objcopy следующая строка, безусловно, не будет работать:

kprintf(hello); 

Причина заключается в том, что компилятор будет внутренне сделать что-то вроде этого:

kprintf((char *)0x12345); 

0x12345 является адресом, где строка " привет ". Однако этот адрес еще не известен, когда программа скомпилирована.

По этой причине объектный файл содержит некоторую информацию о том, что число 0x12345 должно быть заменено реальным адресом строки позже. Ссылка сделает это, когда вы свяжете программу. Однако, используя objcopy, эта информация просто теряется, а число остается 0x12345.

Кстати:

Ваша программа содержит строку:

jmp 0x1000:0x000 

Почему вы думаете, что это место main?

+0

он знает, что отображает некоторый wierd символ вместо «hallo» его 65-битный компилятор – albert

+0

64-битный компилятор – albert

+1

Вы можете попытаться разобрать свой код, чтобы увидеть, что на самом деле сделано: 'objdump -Mi8086 -mi386 -bbinary -D versuch.bin '. Затем вы можете увидеть, как код, сгенерированный 64-битным компилятором, действительно выглядит ... –

 Смежные вопросы

  • Нет связанных вопросов^_^