косвенная адресация в сборке (x86)

# #assembly #x86 #memory-address #cpu-registers

Вопрос:

Это формат для косвенного обращения:

 example:   | Base |   Index * Scale |   Discplacement | |------|-----------------|------------------| | EAX | EBX * 2 |8-Bit Displacement|  

Но есть некоторые вещи, которые я еще не понимаю:

  • Если у нас есть адрес EAX и добавить EBX*2 , будет ли это принимать адрес/значение, расположенное в EBX*2 , и добавлять его к значению/адресу EAX ?
  • Что именно такое Смещение, почему возможно смещение 8 бит,32 бита или вообще никакого смещения, а не, скажем, смещение 4 бита или 2 бита?
  • Если бы у нас были значения размером по 4 байта каждое — в EAX регистре мы бы умножали EAX*4 , но почему это умножение со значениями в байтах (я знаю, что каждая ячейка имеет 1 байт). Означает ли это, что он автоматически преобразует байт в бит?

Комментарии:

1. 1) нет, это простая арифметика с использованием значений регистра 2) это просто константа, которую вы можете добавить. 2 или 4 бита были бы довольно ограничены, и в любом случае пространство в кодировке машинного кода является байтовым 3) x86 использует байтовую адресацию. При использовании массива вы масштабируетесь по размеру элемента, который может быть или не быть 4. Это мало связано с размером регистра.

2. @Jester можете ли вы более подробно остановиться на 1). Что вы подразумеваете под значениями регистров: 32 бита для регистров EAX? Почему в этом случае используется имя регистра, а не просто константа?

3. Существует только 2 бита (поле mode в байте ModRM) для регистрации сигналов по сравнению с памятью без disp, памятью с 8-разрядным disp или памятью с 32-разрядным disp. Вот где это не полностью кодировка переменной длины, чтобы использовать меньше байтов для смещений среднего размера или разрешать до 64 бит в 64-разрядном режиме.

4. Перечитав, я думаю, что 1) должно было быть » ДА «, потому что вы тоже так сказали.

5. Re: значения регистра: нет, буквально значение, содержащееся в регистре EAX. Не постоянная величина. Например, lea eax, [eax eax*2] это способ сделать EAX *= 3 . (LEA вообще не обращается к памяти; он выполняет ту же математику адресов, а затем просто помещает эффективный адрес в пункт назначения вместо доступа к памяти в этом месте.)

Ответ №1:

Полная формула будет выглядеть как « address = (base index lt;lt; scale displacement) amp; mask «.

Примечание 1: «масштаб» — это количество сдвигов, и умножения нет. Это просто описывается как умножение для удобства человека.

Примечание 2: «маска» предназначена для представления переноса/усечения до целевого размера. Например, если base index lt;lt; scale displacement значение равно 0x0000000212345678, но процессору требуется 32-разрядный адрес, тогда маска будет 0x00000000FFFFFFFF, а фактический результат будет 0x12345678.

Если у нас есть адрес EAX и добавить EBX*2 , будет ли это принимать адрес/значение, расположенное в EBX*2 , и добавлять его к значению/адресу в EAX?

Да. Например, если EAX = 3 и EBX = 10, то EAX EBX*2 будет равно 23.

Что именно такое Смещение, почему возможно смещение 8 бит,32 бита или вообще никакого смещения, а не, скажем, смещение 4 бита или 2 бита?

Смещение-это просто число, добавленное к остальным. Для доступа к памяти; он часто используется для доступа к полям структуры (например, «адрес структуры смещение до n — го поля в структуре») и местоположениям стека (например, «верх стека- смещение от вершины стека»).

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

Существует только 2 бита (поле mode в байте ModRM) для регистрации сигналов по сравнению с памятью без disp, памятью с 8-разрядным disp или памятью с 32-разрядным disp. Наличие большего выбора отняло бы больше битов у чего-то другого; disp-это простое двоичное значение (которое расширяется по знаку), оно само по себе не использует кодировку переменной длины. (К счастью, в противном случае декодирование длины инструкции должно было бы учитывать это, а не только байт префикса код операции ModRM.)

Если бы у нас были значения размером по 4 байта каждое — в регистре EAX мы бы умножали EAX*4, но почему это умножение со значениями в байтах (я знаю, что каждая ячейка имеет 1 байт). Означает ли это, что он автоматически преобразует байт в бит?

«EAX * 4» на самом деле «EAX lt;lt; 2». Очень часто встречается небольшое количество сдвигов (например shl eax,cl ), потому что «слишком большое количество сдвигов» (например, больше 32 при 32-разрядном вычислении) в сочетании с маскировкой до целевого размера делает это бессмысленным. В качестве примера рассмотрим фиктивный «адрес = (EAX lt;

По сути, для 32-разрядных вычислений адресов потенциально полезно количество сдвигов от 0 до 31, а наиболее полезными являются меньшие числа сдвигов (от 0 до 3). На этом этапе мы можем вернуться к «Больше возможностей усложняет декодирование, и это должно быть оправдано полезностью», чтобы понять, почему 80×86 поддерживает только количество сдвигов от 0 до 3 (или множители 1, 2, 4 и 8); даже если другие значения сдвига (например, «EAX lt;

2, 4 и 8 являются общими размерами элементов для массивов, поэтому это число сдвигов в 2 бита позволяет индексировать массивы слов, например, с помощью регистра, который содержит номер элемента вместо смещения в байтах.