Проблема в следующем: Изначально в программе имелась инструкция вида Код (Text): lea eax, [ebp + offset data_end] Прочитав про то, как можно сэкономить пару лишних байт на дельта-смещении (не вычитая предварительно из ebp "offset delta"), я написал следующее: Код (Text): lea eax, [ebp + offset data_end - offset delta] После этого возникла такая проблема: компилятор (masm) во втором случае вместо Код (Text): lea eax, [ebp+159h] генерирует Код (Text): lea eax, [[b]bp[/b]+159h] Так происходит во всех аналогичных инструкциях (даже то, что должно в конце выглядеть как lea eax, [ebp+10] превращает в lea eax, [bp+10]). Т.е., lea eax, [ebp + offset a] ; lea eax, [ebp + 10] компилируется правильно, а lea eax, [ebp + offset a - offset delta] - нет. Проверялось при помощи SoftIce (также в поддержку этого факта говорит Application Error при попытке сделать jmp eax ) Пробовал писать lea eax, [dword ptr ebp + offset data_end - delta], но не помогло. Компилятор - masm 6.15 Линкер - ms incremental linker 5.12.8087
У меня тоже 6.15 масм, линкер думаю на код не влияет. На lea eax, [ebp + offset data_end - offset delta] масм выдает ошибку два оffseta нельзя так что это не правильный синтаксис. А lea eax, [ebp + offset data_end - число] работает нормально. Где ты прочитал про "дельта смещение" может это маразм какойто. Короче убери все слова "offset" и ставь числа. Влом числа запоминать тогда обозначь их через '=' в слова и через 'equ' если это константы ер. data_end = 10, delta equ 345 ......
NCRangeR Покажи листинг. У меня (6.14, 6.15, 7.00.xx) генерируется Код (Text): 8D 85 00000159 lea eax,[ebp + offset data_end - offset delta] что соответствует описанию команды, правда появляется сообщение об ошибке, как указал zzzyab. можно сэкономить пару лишних байт Как? Afaik экономия только если (offset data_end - offset delta) < 256
q_q > Случай, о котором ты говоришь не < 256, а -128 <= offset <= 127, здесь же такой вариант: Код (Text): 67:8D86 5901 lea eax, [bp+159] и 8D85 59010000 lea eax, [ebp+159] NCRangeR > После такой LEA старшие 2 байта EAX = 0, так что ты пытаешся ваполнить код в 0й странице памяти, если бы ты лействительно отлаживал прогу в сайсе, то увидел бы это. > Покажи код с директивами .model и т.п.
S_T_A_S_ Точно -128/+127. Afaik, применительно к 32-ух разрядному режиму смещение может быть либо 1 байт, либо 4 байта.
NCRangeR > Прочитав про то, как можно сэкономить пару лишних байт на дельта-смещении... А где прочитав об этом? > (не вычитая предварительно из ebp "offset delta"), я написал следующее: > lea eax, [ebp + offset data_end - offset delta] Да, это правильная идея. Более того, выбрав delta == data_end можно было бы сэкономить ещё один байт (но не при базовой адресации от ebp, как здесь) q_q> Afaik, применительно к 32-ух разрядному режиму q_q> смещение может быть либо 1 байт, либо 4 байта. Да, это верно. Так что "пара лишних байт" == 3 байта. P.S. Я, конечно, не знаю, что такое masm 6.15, но что если некоторые (или все) операторы заключить в скобки? Так: Код (Text): lea eax, [ebp + ((offset data_end) - (offset delta))]
captain cobalt что если некоторые (или все) операторы заключить в скобки Оказывалось достаточно скобок вокруг разницы. ml 6.15 для (offset data_end - offset delta) < 127 создал Код (Text): 8D 45 ?? lea eax, [ebp + (offset data_end - offset delta)] а для 159h по прежнему Код (Text): 8D 85 ???????? lea eax, [ebp + (offset data_end - offset delta)] не знаю, что такое masm 6.15 Это ml.exe из Visual C++ 6.0 Processor Pack.
q_q > LEA хитрая команда. 2й операнд (то, что стоИт после запятой) - это адрес, соответственно, к нему можно применить префикс смены разрядности адреса (67h). При этом смещение будет 16ти битным (кодироваться 2мя байтами). Однако, добавляется байт префикса, так что экономия всего байт. Ещё нужно учитывать, что поле REG байта ModR/M имеет различное значение в различных режимах адресации, так что при добавлении префикса, это поле нужно корректировать. Вот влияние префиксов на LEA в 32х разрядном режиме: Код (Text): 8D85 59010000 lea eax, [ebp+159] 67 8D8[b]6[/b] 5901 lea eax, [bp+159] 66 8D85 59010000 lea ax, [ebp+159] 66 67 8D8[b]6[/b] 5901 lea ax, [bp+159] IMHO NCRangeR компилирует прогу в "каком-нибудь не 32х битном режиме", поэтому и появился BP.
По поводу экономии - http://www.wasm.ru/article.php?article=1010001 Вкратце, обычно пишут Код (Text): call gdelta gdelta: pop ebp sub ebp, offset gdelta и lea eax, [ebp + variable] , а в статье предлагается offset delta вычитать не сразу, а при каждом обращении. Действительно, экономия получается при <128 байтах, но даже для такого случая получается некорректный выход компилятора. Ошибок компиляции у меня masm не выдавал, убрать offset-ы или поставить 67h-ей не помогло. Помогло же поставить скобки (как для <128, так и для всех остальных): Код (Text): lea eax, [ebp + (data_end - delta)] Всем спасибо за ответы! На всякий случай прилагаю исходник (пофиксенный), но, кажется, режим там самый что ни на есть 32-битный, и т.д., и т.п. Для меня (пока) так и осталось непонятным - баг это или фича... _1193762143__v.Asm