# #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 бита позволяет индексировать массивы слов, например, с помощью регистра, который содержит номер элемента вместо смещения в байтах.