адресация памяти x86 с помощью параметров функции

#assembly #x86

#сборка #x86

Вопрос:

Итак, если у меня есть процедура, в которой первым формальным параметром является int[] , и я выполняю перечисление через этот цикл, я не понимаю, почему один фрагмент кода работает, а другой нет. Я должен быть в состоянии сделать это:

 #where ebp 8 is the location of the pointer, and ecx is the counter
mov edx, [ebp ecx*4 8]
  

Это дает мне бессмысленное значение для edx, но этот код работает нормально

 mov edx, [ebp 8]
mov edx, [edx ecx*4]
  

Я не понимаю разницы между этими утверждениями.

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

1. Должно быть, я старею. Я не помню ни одного ecx*4 на ассемблере x86.

2. @JohnSaunders: Вы забываете о байте SIB (конечно, это также описано в руководствах Intel).

3. Спасибо за ссылку. Я этого не забыл. Я перестал работать с ассемблером x86 до появления 64-разрядных процессоров.

4. @JohnSaunders: Это работает на всех процессорах, совместимых с i386 (хотя ссылка может заставить вас поверить в обратное). Даже если вы не часто кодируете ассемблер вручную, вы, вероятно, видели их в дизассемблировании, где такие вещи, как lea eax, [eax eax*4] являются общими для eax *= 5 .

5. Ах, извините, я не понял, сколько вам лет sk00l :). Если вы хотите сохранить здравомыслие, я предлагаю вам никогда не заглядывать в то, как последние коды операций кодируются на x86 (3-байтовые коды операций? проверьте. обязательные префиксы, определяющие инструкцию? проверьте ).

Ответ №1:

Они разные:

В первом коде:

 mov edx, [ebp ecx*4 8]
  

Загрузка выполняется с адреса: ebp ecx*4 8

Во втором коде:

 mov edx, [ebp 8]
mov edx, [edx ecx*4]
  

Сначала вы загружаете значение, сохраненное в ebp 8 . Затем вы используете его в качестве базового адреса для второй загрузки.

Другими словами, базовый адрес хранится в ячейке памяти, на которую указывает ebp 8 . На самом деле это не хранится в ebp самом регистре.

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

1. На «C». Первое является edx = ebp[ecx 2] , а второе — edx = (ebp[2])[ecx] .