Массив записей в HLA, ошибка в книге "Искусство собрания"?
В настоящее время я пытаюсь выучить ассемблер HLA и читаю книгу "Искусство сборки". Я застрял в следующем примере:
тип RecType: запись arrayField: dword[4,5]; // Другие поля.. endrecord; статический aryOfRecs: recType [3,3]; // Доступ к aryOfRecs [i, j].arrayField [k, l]: intmul (5, i, ebx); // Вычисляет индекс в aryOfRecs добавить ( j, ebx); // as (i*5 +j)*@size( recType). intmul (@size (recType), ebx); intmul (3, k, eax); // Вычисляет индекс в aryOfRecs добавить ( l, eax); // as (k*3 + j) (*4 обрабатывается позже). mov (aryOfRecs.arrayField [ebx + eax * 4], eax);
Итак, прежде всего. recType - это запись, имеющая arrayField: dword [4,5] plus - некоторые другие неуказанные поля. Затем - у нас есть aryOfRecs, который является массивом [3,3] recType, объявленным в статическом разделе. Это нормально.
В настоящее время код умножает ebx на @size (recType), чтобы вычислить адрес внутреннего массива (arrayField[4,5]), что не имеет никакого смысла, imho.
Итак, вся формула в книге для вычисления адреса работает так:
БАЗОВЫЙ АДРЕС (aryOfRecs) + (k * 3 + l) * 4 + ((i * 5 + j) * @size (recType)
Я думаю, это должно быть:
БАЗОВЫЙ АДРЕС (aryOfRecs) + (k * 3 + l) * @size( recType) + ((i * 5 + j) * 4 вместо?
Так что, либо - Рэндалл Хайд допустил ошибку в этом примере (и да, я проверил ошибки на странице HLA. Об этом ничего не сказано), или у меня со вчерашнего дня был мозговой перебор;>
Последняя строка: mov( aryOfRecs.arrayField[ ebx + eax*4 ], eax);
По сути, он суммирует смещение (aryOfRecs) + смещение (arrayField) + смещение (ebx) + смещение (eax * 4)
arrayField является первым полем в записи recType, поэтому я предположил, что в этом конкретном случае значение смещения arrayField (по отношению к recType) будет равно +0. Это в основном - карты в начале recType. Так что, я думаю, это было включено только в качестве общего правила, чтобы охватить случаи, когда порядок полей в записи recType был бы другим (и arrayField не был бы первым полем в recType). Итак - я пропустил значение OFFSET(arrayField) в двух формулах выше.
И снова - OFFSET(eax*4) идет с "внешним" массивом. Умножать eax на размер меча (4) - не имеет никакого смысла..
Итак, я ожидаю, что код будет делать что-то вроде этого:
intmul (5, i, ebx); // Вычисляет индекс вaryOfRecsarrayField добавить ( j, ebx); //как (i*5 +j)*@size( recType)как (i*5 +j)*4 или (i*5 +j)*@size(dword) // *4 обрабатывается позже, в последней строке с адресацией с масштабированным индексом, // сохранить одну (shl ebx на 2 или intmul ebx на 4) инструкциюintmul (@size (recType), ebx);intmul (3, k, eax); // Вычисляет индекс в aryOfRecs добавить (l, eax); //как (k * 3 + j) (* 4 обрабатывается позже)как (k * 3 + l) * @size( recType) intmul (@size (recType), eax);mov (aryOfRecs.arrayField [ebx + eax * 4], eax);mov (aryOfRecs.arrayField [ebx * 4 + eax], eax); // ebx * 4 потому что @size(dword) = 4 // сложение коммутативно
Я ошибаюсь и что-то упустил?