Правильное использование binutils в Linux для написания простого загрузчика

В настоящее время я пишу простой загрузчик в качестве личного проекта. У меня есть рабочий прототип, который был построен с использованием NASM в качестве ассемблера. Однако я хотел бы лучше познакомиться с инструментами GNU, и поэтому я пытаюсь переписать свою работу, используя их.

В Интернете есть небольшой образец 'Hello World' Bootloader, который демонстрирует использование нескольких инструментов для написания и сборки «Bootloader». Однако после некоторого чтения я понял, что «газ» — это бэкенд для gcc, и что его не следует вызывать напрямую. Я столкнулся с этой информацией, когда пытался написать выражения внутри моего файла сборки, которые использовали символы для расчета размера программы, чтобы я знал, сколько 0 байтов мне нужно будет записать, прежде чем писать 0x55 и 0xAA, что может быть выполнено используя этот бит кода NASM:

;---------------------------------------------
; Write Zeros up to end of program - 2 then boot signature
;---------------------------------------------
size    equ     $ - entry
        times   (512 - size - 2) db 0
        db      0x55, 0xAA              ;2  byte boot signature

Есть ли способ написать этот эквивалентный набор выражений, используя синтаксис, изначально читаемый GAS? Мои попытки не увенчались успехом, например:

.size len, ( 512 - ( (message + 12) - _start) )

Использование этого выражения и передача его в as дает мне следующую ошибку:

./gasbootloader.asm:24: Error: invalid sections for operation on `message' and `_start'

Нужно ли мне передавать мою программу через gcc, чтобы символы могли быть разрешены?


person Matthew Hoggan    schedule 05.03.2012    source источник
comment
Я не понимаю, как ваша попытка соотносится с исходным кодом. Можете ли вы объяснить, что такое len, message и _start?   -  person Carl Norum    schedule 05.03.2012


Ответы (1)


В ассемблере GNU есть директива .org, которая делает ненужными математические вычисления, которые вам приходилось делать в NASM. Вот пример исходного файла:

entry:
  xor %eax, %eax
  ret

  .org 510
  .byte 0x55, 0xAA

И дамп объектного файла после сборки:

$ clang -c -o example.o example.s
$ otool -t example.o
example.o:
(__TEXT,__text) section
0000000000000000 31 c0 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0000000000000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000001c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000000000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa 

Как видите, 0x55 0xAA оказывается там, где вы хотите, без особых усилий.

person Carl Norum    schedule 05.03.2012
comment
Быстрый вопрос: я просматриваю sourceware.org/binutils/docs-2.22/as /index.html, пытаясь увидеть, есть ли директива, которую можно использовать для указания начального адреса символа. Например, я хочу, чтобы _start загружался по адресу 0x7c00. - person Matthew Hoggan; 05.03.2012
comment
Вы можете использовать --image-base при связывании или, что еще лучше, скрипт компоновщика, чтобы сделать это. Я бы рекомендовал не пытаться сделать это непосредственно в исходном файле. - person Carl Norum; 05.03.2012
comment
Осторожно, gcc не генерирует 16-битный код, поэтому вам придется написать 16-битный и 32-битный ассемблерный код, чтобы переключиться в 32-битный защищенный режим, чтобы выполнить то, что генерирует gcc. - person Alexey Frunze; 05.03.2012
comment
as генерирует 16-битный код, когда вы указываете директиву? - person Matthew Hoggan; 05.03.2012
comment
Да, по моему опыту, .code16 отлично работает. Однако я использовал только наборы инструментов Apple. - person Carl Norum; 05.03.2012