Преобразование индексированного режима на основе в режим косвенной адресации (сборка x86) часть 2 - PullRequest
0 голосов
/ 30 апреля 2018

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

movzbl  string+8, %eax

Я пробовал это:

addl    $8, string
movzbl  string, %eax

После компиляции этого кода появляется всплывающее сообщение об ошибке.

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

string+8 не является режимом адресации на основе индекса. Он собирается по абсолютному адресу disp32 без базового регистра. +8 разрешается во время сборки / соединения. (См. Ссылка на содержимое ячейки памяти. (Режимы адресации x86) )

movzbl string+8, %eax собирается в машинный код с тем же режимом адресации (байт ModR / M), что и movzbl string, %eax, только с другим смещением disp32. См. Как работает связывание C ++ на практике? для получения подробной информации о том, как сборка + связывание заботятся о +8, поэтому во время выполнения нет дополнительной работы.


Вы можете сделать это, потому что string+8 не режим адресации, это константа времени соединения, которую вы можете использовать в качестве непосредственного операнда .

mov     $string+8, %edx
movzbl  (%edx), %eax

Использование mov вместо lea проясняет этот момент, IMO. Единственная причина использовать lea для помещения статического адреса в регистр кроется в x86-64, когда вы можете использовать его для относительной RIP-адресации для кода, не зависящего от позиции (или для кода за пределами младших 2 ГБ, как в OS X ). например lea string+8(%rip), %rdx.


Самый сложный способ сделать самые бесполезные вещи во время выполнения вместо времени сборки будет

mov     $string, %edx
add     $8, %edx
movzbl  (%edx), %eax

Полагаю, использование lea было бы еще более сложным, или вы могли бы inc 8 раз или записать цикл в inc 8 раз, но это слишком сложно по-другому.


Например, с учетом этого источника:

.globl _start
_start:
   mov  $string, %eax
   mov  $string+8, %eax
   movzbl string+8, %eax

.section .rodata
string:

Я собрал с gcc -m32 foo.S -c и разобрал с objdump -drwC foo.o (опция -r показывает перемещения):

foo.o:     file format elf32-i386
Disassembly of section .text:
00000000 <_start>:
   0:   b8 00 00 00 00          mov    $0x0,%eax        1: R_386_32     .rodata
   5:   b8 08 00 00 00          mov    $0x8,%eax        6: R_386_32     .rodata
   a:   0f b6 05 08 00 00 00    movzbl 0x8,%eax         d: R_386_32     .rodata

Вместо реальных адресов заполнители 0 и 0x8 являются смещениями от значения символа для этого перемещения. Они против раздела .rodata объектного файла, а не string, потому что я не использовал .globl _string, чтобы сделать этот символ глобальным.

Если я собираю + ссылку с gcc -static -m32 -nostdlib foo.S и разбираю, я получаю:

 8048098:       b8 a9 80 04 08          mov    $0x80480a9,%eax
 804809d:       b8 b1 80 04 08          mov    $0x80480b1,%eax
 80480a2:       0f b6 05 b1 80 04 08    movzbl 0x80480b1,%eax

Обратите внимание, что абсолютный адрес для загрузки находится прямо в последних 4 байтах movzbl (в младшем порядке), того же 4-байтового значения, которое является непосредственным для кода операции b8 (mov-imm32 -в-EAX).

Также обратите внимание, что string и string+8 просто приводят к разным адресным байтам, но с одинаковым кодом операции.

0 голосов
/ 30 апреля 2018
lea string, %eax
add $8, %eax
movzbl (%eax), %eax

но строка movzbl + 8,% eax не является «сложным режимом адресации», он разрешается ассемблером / компоновщиком.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...