ассемблер gcc - создайте только минимальные необходимые инструкции - PullRequest
0 голосов
/ 29 октября 2019

Я создал очень минимальное приложение в сборке. Он устанавливает некоторые регистры в 0 и выполняет умножение. Ничего особенного.

Однако gcc добавляет много машинного кода к ненужному машинному коду.

Небольшой список вещей, которые я нахожу в objdump:

  • deregister_tm_clones
  • register_tm_clones
  • __ do_global_dtors_aux
  • frame_dummy
  • __ libc_fini_array
  • memset

Я знаю, что они мне не нужны, но я понятия не имею, как я могу сказать компилятору прекратить включать их. Я пытался использовать параметры оптимизации, но это ничего не изменило.

Я компилирую его в основном так: GCC -o ./main.elf ./main.S

Большое спасибо залюбая помощь!

Ответы [ 2 ]

2 голосов
/ 30 октября 2019

GCC автоматически связывает запуск C / C ++ во время выполнения crt0.o и стандартную библиотеку. Вы можете предоставить свой собственный код запуска для переопределения по умолчанию и параметры командной строки, чтобы заставить его не связывать никакую стандартную библиотеку.

Параметры, управляющие библиотеками запуска и по умолчанию, включают:

-nostartfiles
-nostdlib
-nodefaultlubs
-nolibc

Каждый из них влияет на ссылку по-своему, но в этом случае -nostdlib исключит как crt0.o, так и стандартные библиотеки. Конечно, если ваш код не ссылается на стандартную библиотеку, то в любом случае ничто не будет связано, но явное его исключение будет полезно генерировать ошибку ссылки, если что-то ссылается на нее.

См .: https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

Имейте в виду, что если ваш код не устанавливает допустимую среду выполнения C, обеспечивающую, например, статическую инициализацию и стек (минимум), то некоторый код C может работать не так, как задумано. Вам также может понадобиться указать точку входа через --entry=entry, если вы не используете ту же точку входа по умолчанию, что и crt0 (_start Я думаю).

В качестве альтернативы вы можете вызывать gcc с опцией -cи отдельно вызывать компоновщик ld без указания какой-либо библиотеки.

1 голос
/ 01 ноября 2019

so.S:

nop
nop

, затем сборка.

as so.S -o so.o
ld -Ttext=0x1000 so.o -o so.elf
objdump -D so.elf

Disassembly of section .text:

0000000000001000 <__bss_start-0x200002>:
    1000:   90                      nop
    1001:   90                      nop

objcopy -O binary so.elf so.bin
hexdump -C so.bin
00000000  90 90                                             |..|
00000002

с использованием gcc

gcc -nostartfiles -nostdlib -nodefaultlibs -ffreestanding so.S -Xlinker "-Ttext=0x1000" -o so.elf

это оставляет дополнительный мусор в файле, но

gcc so.S -c -o so.o
ld -Ttext=0x2000 so.o -o so.elf
ld: warning: cannot find entry symbol _start; defaulting to 0000000000002000
objdump -D so.elf


Disassembly of section .text:

0000000000002000 <__bss_start-0x200002>:
    2000:   90                      nop
    2001:   90                      nop

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

_start не требуется, если вам не нужна точка входа, определенная в файле, тогда вам нужно сделать это:

.globl _start
_start:

плюс, возможно, что-то в компоновщике, чтобы вызвать это как точку входа для файловых форматов, таких как elf, exe и т. Д.

также работает для кросс-компиляции

arm-none-eabi-as so.s -o so.o
arm-none-eabi-ld -Ttext=0x3000 so.o -o so.elf
arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000000003000
arm-none-eabi-objdump -D so.elf

so.elf:     file format elf32-littlearm


Disassembly of section .text:

00003000 <__bss_end__-0x10008>:
    3000:   e1a00000    nop         ; (mov r0, r0)
    3004:   e1a00000    nop         ; (mov r0, r0)


pdp11-aout-as so.s -o so.elf
pdp11-aout-as so.s -o so.o
pdp11-aout-ld -Ttext=0x400 so.o -o so.elf
pdp11-aout-objdump -D so.elf

so.elf:     file format a.out-pdp11


Disassembly of section .text:

00000400 <so.o>:
 400:   00a0            nop
 402:   00a0            nop

и т. Д.

...