Здравствуйте, у меня возник такой вопрос. Я пишу код, точка входа которого разположена по адресу 0xfedbf000. Собственно вот он: Код (Text): model tiny .486p jmpback macro db 0EAh, 1Ah, 80h, 30h, 00h ;jmp far ptr 30h:801Ah endm INCLUDE common.inc ; константы ;handler code .code s: mov al, 44h out 80h, al ; init stack mov ax, STACK_SEG mov ss, ax mov esp,STACK_OFF debug 47h mov byte ptr ds:[0f06dh], 0b0h ; mov al, 77h mov byte ptr ds:[0f06eh], 077h mov byte ptr ds:[0f06fh], 0e6h ; out 80h, al mov byte ptr ds:[0f070h], 080h mov byte ptr ds:[0f071h], 0c3h ; retn debug 48h call testproc ;вот тут все падает mov al, 49h out 80h, al ; original code mov ax, 0F000h mov ds, ax lgdt fword ptr ds:8163h mov eax, cr0 or al, 1 mov cr0, eax jmpback testproc proc debug 0ddh ret testproc endp end s Вопрос заключается в том, что при вызове testproc все падает. Управление вместо адреса fedbf06d передается на 0000f06d и я вижу код 77h на POST-плате. То есть управление передается по cs:ip, а надо cs:eip. Соответственно вопрос, как можно обойти этот косяк? Я пока имею только такой способ: mov eax, offset testproc add eax, 0fedbf000h call eax И смогу ли я вернуться командой retn из процедуры?
В общем с вызовом я разобрался, и описанный мной вариант работает, возврат в принципе аналогичен. А вот условный переход сделать не получается( команда типа je eax невозможна, а остальные варианты скидывают управление в 1й мегабайт(
drem1lin Про особенности кода в SMM ничего не знаю, но знаю, что в 16-битном коде любые инструкции передачи управления (прыжки, вызовы подпрограмм) за пределы первого мегабайта, в том числе и с относительной адресацией, нужно делать с префиксом переопределения размера 66h, иначе верхнее слово eip будет сбрасываться в нуль, т.е. происходит "скидывание управления в 1й мегабайт".
Я попытвлся ставить и 66h и 67h, как минимум в иде ситуация не поменялась. Но обязательно попробую. попробовал, заработало. откуда ты взял это знание? я читал интеловскую доку на команды, там было про это сказано только для absolute near call & jmp
drem1lin Лично я взял это знание от уважаемого diamond, которое, неочевидно, но возможно извлечь из Intel Manuals.
Слушай, я тут поковырялся и с префиксом 66h правильно делаются jmp, jcc, ret, а вот call не делается( не подскажешь почему?
drem1lin У меня с call всё работало аналогично. Разве что перепроверьте, действительно ли компилятор генерирует префикс.
drem1lin Хех. Ну вот поэтому и не работает. В 16-битном режиме генерируется двухбайтовое смещение у call (у jcc near, кстати, тоже... просто Вам до сих пор везло прыгать на короткие дистанции). А префикс говорит, что оно 4-байтовое. Соответственно в смещение уходит кусок следующей инструкции. Не знаю, что там masm на эту тему умеет делать. Подобный код удобнее писать в fasm.
drem1lin В зависимости от того, где находится someproc. Если адресу старше этой инструкции, то да. А если по младшему, то dw 0FFFFh. А вообще рекомендую взять fasm и писать call dword someproc вместо всяких извращений в tasm.