Войти
ПрограммированиеФорумОбщее

FASM + язык высокого уровня для получения сырого бинарника (3 стр)

Страницы: 1 2 3
#30
16:16, 23 дек. 2010

oistalker
А сырые бинарные файлы он не поддерживает? А то ввёл:

objdump -d boot.bin

В ответ только строчку с иероглифами получил. Сейчас качаю IDA Pro 5, посмотрю как. Кстати, W32Dasm попробовал, вроде работает.


#31
16:20, 23 дек. 2010

Хотя когда переделал ассемблерный листинг на:

format ELF
use16
org 0x7C00

boot__code16:
  mov AX,CS
  mov DS,AX
  mov ES,AX
  mov FS,AX
  mov GS,AX
  mov SS,AX
  mov AX,boot_stack16_start
  mov SP,AX
  
  mov AH,0x02
  mov AL,10          ; Количество читаемых секторов
  mov CL,2          ; Сектор
  mov CH,0          ; Цилиндр
  mov DH,0          ; Головка
  mov DL,0          ; Диск
  mov BX,boot__continuation
  int 0x13
  
  jmp boot__continuation

boot__stack16:
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  boot_stack16_start:
  db 0,0,0,0,0,0,0,0

rb 510-($-$$)
db 0x55,0xAA

boot__continuation:

То получил:

D:\01>objdump -d boot.bin

boot.bin:     ╤Д╨╛╤А╨╝╨░╤В ╤Д╨░╨╣╨╗╨░ elf32-i386


╨Ф╨╕╨░╤Б╤Б╨╡╨╝╨▒╨╗╨╕╤А╨╛╨▓╨░╨╜╨╕╨╡ ╤А╨░╨╖╨┤╨╡╨╗╨░ .flat:

00000000 <.flat>:
   0:   8c c8                   mov    %cs,%eax
   2:   8e d8                   mov    %eax,%ds
   4:   8e c0                   mov    %eax,%es
   6:   8e e0                   mov    %eax,%fs
   8:   8e e8                   mov    %eax,%gs
   a:   8e d0                   mov    %eax,%ss
   c:   b8 5d 7c 89 c4          mov    $0xc4897c5d,%eax
  11:   b4 02                   mov    $0x2,%ah
  13:   b0 0a                   mov    $0xa,%al
  15:   b1 02                   mov    $0x2,%cl
  17:   b5 00                   mov    $0x0,%ch
  19:   b6 00                   mov    $0x0,%dh
  1b:   b2 00                   mov    $0x0,%dl
  1d:   bb 00 7e cd 13          mov    $0x13cd7e00,%ebx
  22:   e9 db 01 00 00          jmp    0x202
        ...
 1fb:   00 00                   add    %al,(%eax)
 1fd:   00 55 aa                add    %dl,-0x56(%ebp)

D:\01>pause
Для продолжения нажмите любую клавишу . . .
#32
16:20, 23 дек. 2010

Сейчас ищу, можно ли переключить дизассемблер в 16-битный режим.

#33
23:53, 23 дек. 2010

Всем доброго вечера!

Сижу в Windows 7, использую FASM и MinGW. У меня есть папка src, в которой находятся четыре файла: boot.asm, preparing.asm, startup.c и kernel.c. Теперь приведу исходный код каждого файла.

boot.asm:

use16
org 0x7C00

boot__code16:
  mov AX,CS
  mov DS,AX
  mov ES,AX
  mov FS,AX
  mov GS,AX
  mov SS,AX
  mov AX,boot_stack16_start
  mov SP,AX
  
  mov AH,0x02
  mov AL,5          ; Количество читаемых секторов
  mov CL,2          ; Сектор
  mov CH,0          ; Цилиндр
  mov DH,0          ; Головка
  mov DL,0          ; Диск
  mov BX,boot__continuation
  int 0x13
  
  jmp boot__continuation

boot__data16:
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0

boot__stack16:
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0,0,0
  boot_stack16_start:
  db 0,0,0,0,0,0,0,0

rb 510-($-$$)
db 0x55,0xAA

boot__continuation:
  include "preparing.asm"

rb 1023-($-$$)
db 0x00

preparing.asm:

preparing__code16:
  cli
  
  in AL,0x92
  or AL,0x02
  out 92h,AL
  
  lgdt [preparing__data16_gdtr]
  
  mov EAX,CR0
  or EAX,00000000000000000000000000000001b
  mov CR0,EAX
  
  mov AX,0000000000010000b
  mov DS,AX
  mov ES,AX
  mov FS,AX
  mov GS,AX
  mov AX,0000000000011000b
  mov SS,AX
  
  jmp 0000000000001000b:preparing__pmode

preparing__data16:
  preparing__data16_gdtr:
    dw 8*4-1
    dd preparing__data16_gdt
  preparing__data16_gdt:
    preparing__data16_gdt_null:
      dw 0000000000000000b    ; Segment Limit(16)
            dw 0000000000000000b    ; Base Address(16)
            db 00000000b            ; Base Address(8)
            db 00000000b            ; P(1), DPL(2), S(1), Type(4)
            db 00000000b            ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4)
            db 00000000b            ; Base Address(8)
    preparing__data16_gdt_code:
      dw 1111111111111111b    ; Segment Limit(16)
            dw 0000000000000000b    ; Base Address(16)
            db 00000000b            ; Base Address(8)
            db 10011000b            ; P(1), DPL(2), S(1), Type(4)
            db 11001111b            ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4)
            db 00000000b            ; Base Address(8)
    preparing__data16_gdt_data:
      dw 1111111111111111b    ; Segment Limit(16)
            dw 0000000000000000b    ; Base Address(16)
            db 00000000b            ; Base Address(8)
            db 10010010b            ; P(1), DPL(2), S(1), Type(4)
            db 11001111b            ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4)
            db 00000000b            ; Base Address(8)
    preparing__data16_gdt_stack:
      dw 1111111111111111b    ; Segment Limit(16)
            dw 0000000000000000b    ; Base Address(16)
            db 00000000b            ; Base Address(8)
            db 10010110b            ; P(1), DPL(2), S(1), Type(4)
            db 11001111b            ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4)
            db 00000000b            ; Base Address(8)

preparing__pmode:

startup.c:

void _mainCRTStartup() 
{ 
   kernel(); 
}

kernel.c:

void kernel(void)
{
  for(;;)
  {
  }
}

Загрузочный сектор занимает 512 байт. Следом ещё 512 байт отводится для входа в защищённый режим. Итого 1024 (0x0400) байта ассемблерного кода. Загрузчик начинает работать по адресу 0x7C00, поэтому прибавив 0x0400 мы получим 0x8000.

Поднимемся на каталог выше и познакомимся с build.bat:

fasm "src/boot.asm" BOS.img
gcc -ffreestanding -c -o startup.o "src/startup.c"
gcc -ffreestanding -c -o kernel.o "src/kernel.c"
ld -Ttext 0x8000 -o Test.img startup.o kernel.o
objcopy Test.img -O binary
del startup.o
del kernel.o
pause

В результате появятся два файла: BOS.img (размером 1024 байта) и Test.img (размером 4116 байт). С помощью программы Hex Workshop, я к BOS.img приклею Test.img. Результат спаривания я отправлю в Bochs. В результате виртуальный компьютер у меня по кругу перезагружается.

Что я сделал не так?

#34
0:06, 24 дек. 2010

s3dworld
> по адресу 0x7C00, поэтому прибавив 0x0400 мы получим 0x8000.

Наивный,...

#35
0:09, 24 дек. 2010

oistalker
Особо и не углублялся. Так то знаю что идёт 0x0000:0x0000. Поэтому этот 0x7C00 будет как 0x0007C000. Но я тут почитал что:

--section-start SECTION=ADDRESS    Set address of named section
-Tbss ADDRESS               Set address of .bss section
-Tdata ADDRESS              Set address of .data section
-Ttext ADDRESS              Set address of .text section
-Ttext-segment ADDRESS      Set address of text segment

Вот оно и получается что ничего не влияет. Так как быть?

#36
0:17, 24 дек. 2010

s3dworld
> Особо и не углублялся. Так то знаю что идёт 0x0000:0x0000. Поэтому этот 0x7C00
> будет как 0x0007C000.

А вот и нет,... сегментная адресация в реальном режиме работает немного хитрее - запись 0x7C00:0000 означает на самом деле абсолютный адрес 0x0007C000. Таким образом, если ты к 0x7C00:0000 прибавишь 0x0400, то получишь 0x7C00:0400 или, что тоже самое,... - 0x7C40:0000

ЗЫ.
16ти битный режим, - он потому и 16ти битный, что для адресации использует 16ти битные адреса и сегментные регистры, а не из-за того, что есть возможность ипользовать 32х битные регистры.

#37
11:06, 24 дек. 2010

Написал:

fasm "src/boot.asm" BOS.img
gcc -ffreestanding -c -o startup.o "src/startup.c"
gcc -ffreestanding -c -o kernel.o "src/kernel.c"
ld -Ttext 0x0007C400 -o Test.img startup.o kernel.o
objcopy Test.img -O binary
del startup.o
del kernel.o
pause

Никакой разницы. Так как делать?

#38
1:03, 25 дек. 2010

Всем доброй ночи!

С чужой помощью удалось добиться работы кода. Во всём был виноват дескриптор сегмента данных, который я решил описать как стек (не нравилось ему что я бит EW установил в 1). Заработал и C++ код (компилирую через g++). Смог C++ кодом очищать экран и выводить символы. Но возникла проблема с вводом текста. Почему-то у меня не передаётся в функцию указатель на текст:

#define VIDEO_RAM 0x000B8000

void Clear(const char _color);
void DrawChar(const char _char,const unsigned int _x,const unsigned int _y,const char _color);
void DrawText(const char* _text,const unsigned int _x,const unsigned int _y,const char _color);

void kernel(void)
{
  Clear(0b00010000);
  DrawText("Hello!\0",0,0,0b00011110);
  DrawChar('1',4,1,0b00001010);

  for(;;)
  {
  }
}

void Clear(const char _color)
{
  unsigned int i=0;
  char* address=0;
  
  address=(char*)VIDEO_RAM;
  
  for(i=0;i<80*25*2;i+=2)
  {
    *(address+i)=' ';
    *(address+i+1)=_color;
  }
}

void DrawChar(const char _char,const unsigned int _x,const unsigned int _y,const char _color)
{
  unsigned int i=0;
  char* address=0;
  
  i=160*_y+2*_x;
  address=(char*)VIDEO_RAM;
  
  *(address+i)  = _char;
  *(address+i+1)  = _color;
}

void DrawText(const char* _text,const unsigned int _x,const unsigned int _y,const char _color)
{
  unsigned int i=0;
  unsigned int j=0;
  unsigned int length=0;
  char* address=0;
  
  i=160*_y+2*_x;
  address=(char*)VIDEO_RAM;
  
  while(_text[length]) length++;
  
  while(length)
  {
    *(address+i)  = _text[j];
    *(address+i+1)  = _color;
    
    i+=2;
    j++;
    length--;
  }
}

В результате у меня выводится только символ 1 от функции DrawChar(). Почему функция DrawText() не получает указатель на текст и как это исправить?

#39
2:22, 25 дек. 2010

s3dworld
> while(_text[length]) length++;
>
> while(length)
> {
> *(address+i) = _text[j];
> *(address+i+1) = _color;
>
> i+=2;
> j++;
> length--;
> }
задумайся над этим кодом...

и попробуй сделать так

void kernel()
{
char text[] = "Hello";
DrawText( text, .. );
}

если так работает, то ты не правильно грузишь в память ядро...

#40
3:59, 25 дек. 2010

Pushkoff
Да, так работает. А в смысле не правильно гружу? А как правильно? Весь проект тут.

#41
5:32, 25 дек. 2010

s3dworld
либо все грузится не по тому адресу но работает из-за относительных смещений в коде, либо сегменты data и rdata находятся по другим адресам...

#42
10:12, 25 дек. 2010

Всё дело было в линковке C++ кода. У меня было так:

ld -Ttext 0x00080000 -o Test.img startup.o kernel.o

А надо было так:

ld -Ttext 0x00008000 -o Test.img startup.o kernel.o

Только я вот не понимаю, почему именно 0x00008000 нужно, почему именно смещение как в реальном режиме (R-Mode)? Ведь у меня C++ код работает в защищённом 32-битном коде, почему тогда не 0x7C00:0x0000 как 0x0007C000?

Прошло более 9 месяцев
#43
22:45, 5 окт. 2011

s3dworld
> Только я вот не понимаю, почему именно 0x00008000 нужно, почему именно смещение
> как в реальном режиме (R-Mode)? Ведь у меня C++ код работает в защищённом
> 32-битном коде, почему тогда не 0x7C00:0x0000 как 0x0007C000?

А все очень просто: вот цитата из BIOS boot specification
When the boot handler is called, the BIOS passes a pointer to the PnP Installation
Check Structure in ES:DI. This is so that once the boot handler has successfully
loaded the device’s boot sector into memory at address 0000:7C00h, execution control
can be transferred with the following register contents:
ES:DI = Pointer to PnP Installation Check Structure
DL = Drive number used for the INT 13h (00h, 80h, etc.)

Код грузится по адресу 0000:7C00h.
поэтому 7С00h + 400h = 8000h

#44
22:50, 5 окт. 2011

logree
Ну ты очнулся)) Уже почти год прошёл.

Страницы: 1 2 3
ПрограммированиеФорумОбщее

Тема в архиве.