Проблема со встроенным ассемблером в VS 2003

Тема в разделе "WASM.WIN32", создана пользователем Son of God, 11 сен 2005.

  1. Son of God

    Son of God New Member

    Публикаций:
    0
    Регистрация:
    11 сен 2005
    Сообщения:
    125
    Всем привет, вот хочу запрячь встроенный ассемблер в VS, да напоролся на недоразумение эдакое. Следующий код:
    Код (Text):
    1.  
    2. #include <windows.h>
    3.  
    4. char msgboxC[] = "Hello, world from C code";
    5. char msgboxAsm[] = "Hello, world form Asm code";
    6.  
    7. void main()
    8. {
    9.     MessageBox(0,&msgboxC[0],0,0);
    10.  
    11.     _asm
    12.     {
    13.         push 0
    14.         push 0
    15.         push offset msgboxAsm
    16.         push 0
    17.         call MessageBox
    18.     }
    19. }
    20.  




    При запуске первый MessageBox работает, а второй - нет! После call MessageBox вылетает exception at 0x00402000 in msgbox_in_asm.exe: 0xC0000005: Access violation reading location 0xffffffff. IDA после дизассемблирования выдает следующее:
    Код (Text):
    1.  
    2. .text:00401000 main            proc near
    3. .text:00401000                 push    0
    4. .text:00401002                 push    0
    5. .text:00401004                 push    offset msgboxC  ; "Hello, world from C code"
    6. .text:00401009                 push    0
    7. .text:0040100B                 call    ds:__imp__MessageBoxA@16 ; __declspec(dllimport) MessageBoxA(x,x,x,x)
    8. ;опкод этой инструкции - FF 15 00 20 40 00
    9. .text:00401011                 push    0
    10. .text:00401013                 push    0
    11. .text:00401015                 push    offset msgboxAsm ; "Hello, world form Asm code"
    12. .text:0040101A                 push    0
    13. .text:0040101C                 call    near ptr __imp__MessageBoxA@16 ; __declspec(dllimport) MessageBoxA(x,x,x,x)
    14. ;опкод этой инструкции - E8 DF 0F 00 00
    15. .text:00401021                 retn
    16. .text:00401021 main            endp
    17.  
    18.  




    Объясните кто-нибудь, почему генерируется разный код? Буду рад любой информации по использованию встроенного ассемблера в VS. Хелп читал, но там написано именно так делать. И еще, я отключил CRT (/entry:main), Buffer Security Check и включил выравнивание на 512 байт (/opt:nowin98), это позволило получить размер исполняемого файла в 2.5 кБ. Может быть в этом проблема?

    Всем спасибо.



    ЗЫ. Если я пишу в коде что-то типа call ds:MessageBox, то функция вызывается и опкоды одинаковые, только в коде появляется лишний байт%-|. Вот дизассемблированный код:
    Код (Text):
    1.  
    2. .text:00401000 main            proc near
    3. .text:00401000                 push    0
    4. .text:00401002                 push    0
    5. .text:00401004                 push    offset msgboxC  ; "Hello, world from C code"
    6. .text:00401009                 push    0
    7. .text:0040100B                 call    ds:__imp__MessageBoxA@16 ; __declspec(dllimport) MessageBoxA(x,x,x,x)
    8. .text:00401011                 push    0
    9. .text:00401013                 push    0
    10. .text:00401015                 push    offset msgboxAsm ; "Hello, world form Asm code"
    11. .text:0040101A                 push    0
    12. .text:0040101C                 db      3Eh
    13. .text:0040101C                 call    __imp__MessageBoxA@16 ; __declspec(dllimport) MessageBoxA(x,x,x,x)
    14. .text:00401023                 retn
    15. .text:00401023 main            endp
    16.  
    17.  
     
  2. Dr.Golova

    Dr.Golova New Member

    Публикаций:
    0
    Регистрация:
    7 сен 2002
    Сообщения:
    348
    Хексдамп бы не помешал, но осмелюсь предположить.

    Незнаю как в 2003, но еще в 6-ой VS имелась фича с вызовом внешних функций - если просто писать call то глупый ассемблер так и делал call на адрес в IAT - т.е. просто прыгал на dword в iat и естесно все падало. Приходилось писать что-то вроде call ds:[MessageBoxA]

    Все дело в том что это не дельфя а нету тут jump таблиц, все надо вызывать как call dword ptr [xxxx]
     
  3. Son of God

    Son of God New Member

    Публикаций:
    0
    Регистрация:
    11 сен 2005
    Сообщения:
    125
    Вот хексдамп первого варианта (в котором call MessageBox) из OllyDbg:
    Код (Text):
    1. 00401000 >/$ 6A 00            PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
    2. 00401002  |. 6A 00            PUSH 0                                   ; |Title = NULL
    3. 00401004  |. 68 00304000      PUSH OFFSET msgbox_i.msgboxC             ; |Text = "Hello, world from C code"
    4. 00401009  |. 6A 00            PUSH 0                                   ; |hOwner = NULL
    5. 0040100B  |. FF15 00204000    CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
    6. 00401011  |. 6A 00            PUSH 0
    7. 00401013  |. 6A 00            PUSH 0
    8. 00401015  |. 68 1C304000      PUSH OFFSET msgbox_i.msgboxAsm           ;  ASCII "Hello, world from Asm code"
    9. 0040101A  |. 6A 00            PUSH 0
    10. 0040101C  |. E8 DF0F0000      CALL <&USER32.MessageBoxA>
    11. 00401021  \. C3               RETN
    12.  
    13.  


    И второго (call ds:[MessageBoxA]:
    Код (Text):
    1. 00401000 >/$ 6A 00              PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
    2. 00401002  |. 6A 00              PUSH 0                                   ; |Title = NULL
    3. 00401004  |. 68 00304000        PUSH OFFSET msgbox_i.msgboxC             ; |Text = "Hello, world from C code"
    4. 00401009  |. 6A 00              PUSH 0                                   ; |hOwner = NULL
    5. 0040100B  |. FF15 00204000      CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
    6. 00401011  |. 6A 00              PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
    7. 00401013  |. 6A 00              PUSH 0                                   ; |Title = NULL
    8. 00401015  |. 68 1C304000        PUSH OFFSET msgbox_i.msgboxAsm           ; |Text = "Hello, world from Asm code"
    9. 0040101A  |. 6A 00              PUSH 0                                   ; |hOwner = NULL
    10. 0040101C  |. 3E:FF15 00204000   CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
    11. 00401023  \. C3                 RETN
    12.  
    13.  




    Можно ли это исправить? Вот нашел пример в хелпе, там идет обычный call:
    Код (Text):
    1. An __asm block can call C functions, including C library routines. The following example calls the printf library routine:
    2.  
    3. // InlineAssembler_Calling_C_Functions_in_Inline_Assembly.cpp
    4. #include <stdio.h>
    5.  
    6. char format[] = "%s %s\n";
    7. char hello[] = "Hello";
    8. char world[] = "world";
    9. int main( void )
    10. {
    11.    __asm
    12.    {
    13.       mov  eax, offset world
    14.       push eax
    15.       mov  eax, offset hello
    16.       push eax
    17.       mov  eax, offset format
    18.       push eax
    19.       [b]call printf[/b]
    20.       //clean up the stack so that main can exit cleanly
    21.       //use the unused register ebx to do the cleanup
    22.       pop  ebx
    23.       pop  ebx
    24.       pop  ebx
    25.    }
    26. }
    27.  
     
  4. Son of God

    Son of God New Member

    Публикаций:
    0
    Регистрация:
    11 сен 2005
    Сообщения:
    125
    Ок, вариант call dword ptr [xxxx] работает, даже можно имя функции без скобок писать. Спасибо, Dr.Golova!