Специфический вызов

Тема в разделе "WASM.ASSEMBLER", создана пользователем drem1lin, 13 дек 2010.

  1. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Здравствуйте, у меня возник такой вопрос. Я пишу код, точка входа которого разположена по адресу 0xfedbf000. Собственно вот он:
    Код (Text):
    1. model tiny
    2. .486p
    3. jmpback macro      
    4.     db 0EAh, 1Ah, 80h, 30h, 00h     ;jmp     far ptr 30h:801Ah
    5.     endm
    6.    
    7. INCLUDE common.inc ; константы
    8.  
    9. ;handler code
    10. .code
    11. s: 
    12.     mov al, 44h
    13.     out 80h, al
    14.  
    15. ; init stack
    16.     mov ax, STACK_SEG
    17.     mov ss, ax     
    18.     mov esp,STACK_OFF
    19.  
    20.     debug 47h
    21.  
    22.     mov byte ptr ds:[0f06dh], 0b0h   ; mov al, 77h
    23.     mov byte ptr ds:[0f06eh], 077h
    24.     mov byte ptr ds:[0f06fh], 0e6h   ; out 80h, al
    25.     mov byte ptr ds:[0f070h], 080h
    26.     mov byte ptr ds:[0f071h], 0c3h   ; retn
    27.  
    28.     debug 48h
    29.  
    30.     call testproc ;вот тут все падает
    31.    
    32.     mov al, 49h
    33.     out 80h, al
    34.  
    35. ; original code
    36.  
    37.     mov     ax, 0F000h
    38.     mov     ds, ax
    39.     lgdt    fword ptr ds:8163h
    40.     mov     eax, cr0
    41.     or      al, 1
    42.     mov     cr0, eax
    43.     jmpback
    44.    
    45. testproc proc
    46.     debug 0ddh
    47.     ret
    48. testproc endp
    49.     end s
    Вопрос заключается в том, что при вызове testproc все падает. Управление вместо адреса fedbf06d передается на 0000f06d и я вижу код 77h на POST-плате. То есть управление передается по cs:ip, а надо cs:eip. Соответственно вопрос, как можно обойти этот косяк? Я пока имею только такой способ:
    mov eax, offset testproc
    add eax, 0fedbf000h
    call eax
    И смогу ли я вернуться командой retn из процедуры?
     
  2. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    В общем с вызовом я разобрался, и описанный мной вариант работает, возврат в принципе аналогичен. А вот условный переход сделать не получается( команда типа je eax невозможна, а остальные варианты скидывают управление в 1й мегабайт(
     
  3. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Код (Text):
    1. jne $+7
    2. jmp eax
    Код (Text):
    1. mov edx, @f
    2. cmovne eax, edx
    3. jmp eax
    4. @@:
     
  4. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    drem1lin
    Про особенности кода в SMM ничего не знаю, но знаю, что в 16-битном коде любые инструкции передачи управления (прыжки, вызовы подпрограмм) за пределы первого мегабайта, в том числе и с относительной адресацией, нужно делать с префиксом переопределения размера 66h, иначе верхнее слово eip будет сбрасываться в нуль, т.е. происходит "скидывание управления в 1й мегабайт".
     
  5. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Я попытвлся ставить и 66h и 67h, как минимум в иде ситуация не поменялась. Но обязательно попробую.
    попробовал, заработало. откуда ты взял это знание? я читал интеловскую доку на команды, там было про это сказано только для absolute near call & jmp
     
  6. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Спасибо большое) это точно будет работать
     
  7. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    drem1lin
    Лично я взял это знание от уважаемого diamond, которое, неочевидно, но возможно извлечь из Intel Manuals.
     
  8. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Слушай, я тут поковырялся и с префиксом 66h правильно делаются jmp, jcc, ret, а вот call не делается( не подскажешь почему?
     
  9. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    drem1lin
    У меня с call всё работало аналогично. Разве что перепроверьте, действительно ли компилятор генерирует префикс.
     
  10. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Я тупо делаю так:
    Код (Text):
    1. db 66h
    2. call SomeProc
     
  11. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    drem1lin
    Хех. Ну вот поэтому и не работает. :) В 16-битном режиме генерируется двухбайтовое смещение у call (у jcc near, кстати, тоже... просто Вам до сих пор везло прыгать на короткие дистанции). А префикс говорит, что оно 4-байтовое. Соответственно в смещение уходит кусок следующей инструкции.
    Не знаю, что там masm на эту тему умеет делать. Подобный код удобнее писать в fasm.
     
  12. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    У меня tasm) то есть
    Код (Text):
    1. db 66h
    2. call Someproc
    3. dw 0
    должно работать?
     
  13. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    drem1lin
    В зависимости от того, где находится someproc. Если адресу старше этой инструкции, то да. А если по младшему, то dw 0FFFFh.
    А вообще рекомендую взять fasm и писать call dword someproc вместо всяких извращений в tasm.
     
  14. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Старше, да проект относительно большой, боюсь что не смогу перенести на fasm да и время сейчас нет(
     
  15. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Перенося на tasm
    Код (Text):
    1. call dword someproc
    =
    Код (Text):
    1. call large near prt someproc