Более короткая инструкция вызова x86

Для контекста я играю в x86.

00000005 <start>:
   5:   e8 25 00 00 00          call   2f <cube>
   a:   50                      push   %eax

Несколько звонков позже...

0000002f <cube>:
  2f:   89 c8                   mov    %ecx,%eax
  31:   f7 e9                   imul   %ecx
  33:   f7 e9                   imul   %ecx
  35:   c3                      ret   

call заняло 5 байтов, хотя смещение укладывается в один байт! Есть ли способ написать call cube и собрать с GNU ассемблером и получить меньшее смещение? Я понимаю, что можно использовать 16-битные смещения, но в идеале я хотел бы иметь 2-байтовую инструкцию, например call reg,

1 ответ

Решение

Здесь нет call rel8 или любой способ отправить обратный адрес и jmp менее чем 5 байтов.

Чтобы выйти вперед с call reg Вам необходимо создать полный адрес в регистре менее чем за 3 байта. Даже REA-относительный LEA не помогает, потому что он существует только в rel32 форма, а не rel8,

Для одного call явно не стоит. Если вы можете использовать один и тот же регистр указателя функции для нескольких 2-байтовых call reg инструкции, то вы выходите вперед даже с всего 2 call s (5 байт mov reg, imm32 амортизируется в течение 2 call s стоит 2,5 байта за вызов.) Но это стоит вам зарегистрироваться.


Большинство операционных систем не позволяют отображать что-либо на самых низких страницах (так что ошибки по нулевому указателю разыскиваются), поэтому используемые адреса имеют размер больше 16 бит, вне 16-битного режима.

В 32-битном / 64-битном коде я бы рассмотрел параметры компоновщика, необходимые для отображения вашего кода на нулевой странице, как часть количества байтов в вашем ответе на код-гольф. ( А также /proc/sys/vm/mmap_min_addr настройка ядра или эквивалент в других ОС)


Вообще избегайте call в код-гольфе, если можете. Обычно лучше структурировать циклы, чтобы избежать повторного использования кода. например jmp в середину цикла, чтобы заставить часть цикла запускаться нужное количество раз вместо вызова блока несколько раз.

Я думаю, что я обычно смотрю на вопросы по коду-гольфу, которые естественным образом поддаются машинному коду и могут избежать необходимости одного и того же блока кода из разных мест. Я уже могу часами дорабатывать короткую функцию, поэтому начать ответ на вопрос, который займет больше кода (и, таким образом, будет еще больше места для оптимизации между / по его частям), для меня редко.

Другие вопросы по тегам