Вопрос по wsprintf

Тема в разделе "WASM.BEGINNERS", создана пользователем _sheva740, 6 окт 2011.

  1. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    Что я неправильно делаю?
    Хочу вывести строку
    Код (Text):
    1. AA:BB:CC:DD:EE:FF
    Делаю
    Код (Text):
    1. .386
    2. .model      flat,stdcall
    3. option      casemap:none
    4. include     \masm32\include\windows.inc
    5. include     \masm32\include\kernel32.inc
    6. include     \masm32\include\masm32.inc
    7. include     \masm32\include\user32.inc
    8. includelib  \masm32\lib\kernel32.lib
    9. includelib  \masm32\lib\masm32.lib
    10. includelib  \masm32\lib\user32.lib
    11.  
    12. .data
    13.     szformatMAC     db '%.02X:%.02X:%.02X:%.02X:%.02X:%.02X',0
    14.     crlf            db 13,10,0
    15.     buffsz          db [MAX_PATH] dup (0)
    16.     abc         db 0aah,0bbh,0cch,0ddh,0eeh,0ffh
    17. .code
    18. start:
    19.     lea esi,abc
    20.     invoke  wsprintf,addr buffsz, addr szformatMAC, byte ptr[esi+0],\
    21.                         byte ptr[esi+1],\
    22.                         byte ptr[esi+2],\
    23.                         byte ptr[esi+3],\
    24.                         byte ptr[esi+4],\
    25.                         byte ptr[esi+5]
    26.     invoke  StdOut, addr buffsz
    27.     invoke  StdOut, addr crlf
    28.     invoke  ExitProcess,0
    29. end start
    Но на выходе -
    Код (Text):
    1. AA:BB0000:00:CC:DD0000:00
     
  2. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    _sheva740
    Точки в спецификации не нужны. Но это ерунда. А гонит, по всей видимости, masm. Вместо того, чтобы выдать ошибку на byte ptr[esi+5] и т.п., т.к. запихать байт в стек ну никак нельзя, он выдумывает собственный код, которым ещё и стековое выравнивание нарушает:
    Код (Text):
    1. push 0
    2. mov al,byte ptr [esi+5]
    3. movzx ax,al
    4. push ax
    Видимо, рассчитывает, что push 0 всего два байта на стеке займёт, вот только перфикс 66 к нему поставить забывает.
     
  3. s_d_f

    s_d_f New Member

    Публикаций:
    0
    Регистрация:
    15 май 2008
    Сообщения:
    342
    Попробуй проще сделать
    Код (Text):
    1. abc            dd 0aah,0bbh,0cch,0ddh,0eeh,0ffh
    и

    Код (Text):
    1.     invoke    wsprintf,addr buffsz, addr szformatMAC, dword ptr [esi+0*4],\
    2.                         dword ptr [esi+1*4],\
    3.                         dword ptr [esi+2*4],\
    4.                         dword ptr [esi+3*4],\
    5.                         dword ptr [esi+4*4],\
    6.                         dword ptr [esi+5*4]
    А это
    Код (Text):
    1. mov al,byte ptr [esi+5]
    2. movzx ax,al
    3. push ax
    Расчитано на 16-битные программы, но invoke не обновлялся для 32-битных, а для 64-бит вообще не делался.
     
  4. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    s_d_f
    Это очень утешает. :) А в 16-битных программах при компиляции push ax префикс 66 тоже ставится? :derisive:
     
  5. s_d_f

    s_d_f New Member

    Публикаций:
    0
    Регистрация:
    15 май 2008
    Сообщения:
    342
    По ходу дела invoke разворачивается в виде текста, а не в виде опкодов. Подставление опкода это уже следующий этап. Для 32-бит push ax разумеется с префиксом 66h.
     
  6. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    s_d_f
    l_inc
    Спасибо! Вот так получилось как и советовалось.
    Код (Text):
    1.     xor eax,eax
    2.     movzx   eax,byte ptr [esi]+5
    3.     push    eax
    4.     movzx   eax,byte ptr [esi]+4
    5.     push    eax
    6.     movzx   eax,byte ptr [esi]+3
    7.     push    eax
    8.     movzx   eax,byte ptr [esi]+2
    9.     push    eax
    10.     movzx   eax,byte ptr [esi]+1
    11.     push    eax
    12.     movzx   eax,byte ptr [esi]+0
    13.     push    eax
    14.     push    offset szformatMAC
    15.     push    offset buffsz
    16.     call    wsprintf
    Выход
    Код (Text):
    1. AA:BB:CC:DD:EE:FF
     
  7. s_d_f

    s_d_f New Member

    Публикаций:
    0
    Регистрация:
    15 май 2008
    Сообщения:
    342
    Код (Text):
    1. call    wsprintf
    Там еще нужно теперь стэк в ручную очищать. Именно поэтому, чтобы избежать этой проблемы я и предлагал в примере перейти в к dword`ам. Идеальным решением был-бы самодельный макрос invoke, уже правильно запихивающий байты и WORD`ы в стэк.
     
  8. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    s_d_f
    Спасибо. Уже понял )))

    Код (Text):
    1.     xor    eax,eax
    2.     movzx    eax,byte ptr [esi]+5
    3.     push    eax
    4.     movzx    eax,byte ptr [esi]+4
    5.     push    eax    
    6.     movzx    eax,byte ptr [esi]+3
    7.     push    eax    
    8.     movzx    eax,byte ptr [esi]+2
    9.     push    eax    
    10.     movzx    eax,byte ptr [esi]+1
    11.     push    eax    
    12.     movzx    eax,byte ptr [esi]+0
    13.     push    eax
    14.     push    offset szformatMAC
    15.     push    offset buffsz
    16.     call    wsprintf
    17.     add esp,4*8
     
  9. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    _sheva740
    Ну и зачем все эти "извращения"? Просто замени в своем коде byte ptr на dword ptr и у-се ;) Ну нарвешься на невыравненное чтение, ну потеряешь несколько единиц или даже десятков тактов, и что - от этого мир перевернется?! :)
     
  10. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    leo
    Не ну как же ...
    Код (Text):
    1. .386
    2. .model         flat,stdcall
    3. option         casemap:none
    4. include        \masm32\include\windows.inc
    5. include        \masm32\include\kernel32.inc
    6. include        \masm32\include\masm32.inc
    7. include        \masm32\include\user32.inc
    8. includelib    \masm32\lib\kernel32.lib
    9. includelib    \masm32\lib\masm32.lib
    10. includelib    \masm32\lib\user32.lib
    11.  
    12. .data
    13.     szformatMAC        db '%.02X:%.02X:%.02X:%.02X:%.02X:%.02X',0
    14.     crlf            db 13,10,0
    15.     buffsz            db [MAX_PATH] dup (0)
    16.     abc            db 0aah,0bbh,0cch,0ddh,0eeh,0ffh
    17. .code
    18. start:
    19.     lea    esi,abc    
    20.     invoke    wsprintf,addr buffsz, addr szformatMAC, dword ptr[esi+0],\
    21.                         dword ptr[esi+1],\
    22.                         dword ptr[esi+2],\
    23.                         dword ptr[esi+3],\
    24.                         dword ptr[esi+4],\
    25.                         dword ptr[esi+5]
    26.     invoke    StdOut, addr buffsz
    27.     invoke    StdOut, addr crlf
    28.     invoke    ExitProcess,0
    29. end start
    ... получится же ...
    Код (Text):
    1. DDCCBBAA:EEDDCCBB:FFEEDDCC:FFEEDD:FFEE:FF
    ... или я не уловил?
    ))
     
  11. s_d_f

    s_d_f New Member

    Публикаций:
    0
    Регистрация:
    15 май 2008
    Сообщения:
    342
    Смотри пост номер 3.
    Код (Text):
    1. abc            dd 0aah,0bbh,0cch,0ddh,0eeh,0ffh
    Все работает как надо.
     
  12. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    s_d_f
    Да понял, просто leo об этом (dd 0aah, ...) молчал ))
    Спасибо.
     
  13. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    s_d_f
    Под виндой префикс 66 ставится что бы работать с 16 разрядными регистрами, а не наоборот.
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Painter
    Ну да (если под "под виндой" имеется в виду 32-битный режим). Именно поэтому s_d_f всё верно написал.
    И наоборот тоже. В 16-битном режиме нужно ставить 66, чтобы работать с 32-битными регистрами.
     
  15. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    _sheva740
    вы выводите 2е младших цифры. можно еще

    abc db 0aah,0bbh,0cch,0ddh,0eeh,0ffh

    ...

    push ebp
    mov ebp, esp

    mov eax, abc

    push eax
    shr eax,8
    push eax
    shr eax,8
    ... ; итд
    call wsprintf

    leave

    вообщето асм это низкий уровень, язык трюков в настоящий момент. потому, особенно поначалу, не стоит пользоваться макросами вообще.
    макроразворачиватель не делает никаких предположений и не заметит ошибки, если такое может быть развернуто. а кодогенератор не заметит ошибки, если такое может быть оттранслировано в код. для трюков это преимущество.
     
  16. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    l_inc
    Вы правы, а вот слова s_d_f:
    Вот я и решил уточнить...
     
  17. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    l_inc
    Просто он уточнил что для 32 бит но при этом push ax...