FASM. Не понимаю логику cominvk-макроса для win64. Зачем там push ???

Тема в разделе "WASM.BEGINNERS", создана пользователем f2065, 20 дек 2010.

  1. f2065

    f2065 Eugene

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Адрес:
    Russia,Moscow
    Пишу такую программу:
    Код (Text):
    1. format PE64 GUI 4.0 DLL
    2. include 'WIN64A.INC'
    3. ...
    4. mov rax, [m_pDataObj]
    5. comcall rax, IDataObject, GetData, etc, stg
    6. ...
    7. interface IDataObject,\
    8.     QueryInterface,\
    9.     AddRef,\
    10.     Release,\
    11.     GetData,\
    12.     GetDataHere,\
    13.     QueryGetData,\
    14.     GetCanonicalFormatEtc,\
    15.     SetData,\
    16.     EnumFormatEtc,\
    17.     DAdvise,\
    18.     DUnadvise,\
    19.     EnumDAdvise
    При компиляции для win32 - всё нормально и всё работает как надо:
    Код (Text):
    1. push    offset stg
    2. push    offset etc
    3. push    eax
    4. mov     eax, [eax]
    5. call    dword ptr [eax+0Ch]
    А при компиляции для win64 - получается такой код:
    Код (Text):
    1. sub     rsp, 20h
    2. mov     rcx, rax
    3. mov     rdx, offset etc
    4. mov     r8, offset stg
    5. push    rax
    6. mov     rax, [rax]
    7. call    qword ptr [rax+18h]
    8. add     rsp, 20h
    и программа через некоторое время падает из-за нарушения RSP.
    Если я не использую макрос cominvk, и вручную пишу аналог но без push rax - то всё работает!

    Почему так ?!

    Дизассемблировал WIN64\USECOM.EXE - там тоже cominvk с push (но имхо проблемы c RSP нет потому что затем leave).

    Посмотрел в FASM\INCLUDE\MACRO\COM64.inc - там явно не по ошибке push, там какое-то условие что если handle eqtype rax | handle eqtype 0 то поставить push, а иначе - нормальный fastcall. Однако использование rbx вместо rax - проблему не решает, макрос пишет push rbx...

    как надо использовать этот cominvk чтобы он не писал в стек ничего ?
     
  2. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    f2065
    Код (Text):
    1. mov    rax, [m_pDataObj]
    2. comcall    rax, IDataObject, GetData, etc, stg
    В общем-то Вы везде пишете, что используете cominvk, что не очень-то согласуется с этим кодом. Если бы Вы использовали вместо этого кода вызов cominvk m_pDataObj, GetData, etc, stg, было бы всё в порядке.
    rax в условии никак не связан с rax. :) В условии может стоять любой регистр. Само условие проверяет, является ли переданный указатель на объект регистром, прямым адресом или адресным выражением. В последнем случае (например, если это локальная переменная вида [rbp-20h]) его нельзя просто так запихать в скобки и таким образом разыменовать. Поэтому это условие является некоторой оптимизацией: получить указатель на методы в одну или, если не получается, то в две инструкции.
    Что же до push rax, Вы правы. Он там лишний, и это — ошибка.