На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Не поленитесь, загляните в эти разделы перед созданием темы. Возможно, так уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).

Не забывайте также про главные Правила форума!

Так что добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
  
> Вызов метода из dll ASM x64
    Добрый день.
    Помогите доперевести код на ASM x64.

    ExpandedWrap disabled
      {$IFDEF WIN64}
      function CallFunc(const AObj: TObject; AMethod: Pointer; var AResult: Variant): Variant;
      asm
        .NOFRAME
        PUSH RSI
        PUSH RDI
        
        LEA  RCX, [AObj]
        PUSH RCX
        MOV RDX, AResult
        CALL AMethod
        MOV Result, 1
                    
        POP RAX
        POP RCX
        POP RDX
      end;
       
      function CallFuncParam(const AObj: TObject; AMethod: Pointer; var AResult: Variant; const AParams: Pointer): Variant;
      asm
        .PARAMS 64
        PUSH RSI
        PUSH RDI  
       
        MOV RAX, RCX
        MOV RCX, RDX
        MOV RDX, AResult
        CALL AMethod
        MOV Result, 1
                    
        POP RAX
        POP RCX
        POP RDX
      end;
      {$ENDIF}
       
      function TmyClass.CallMethod(AObject: TObject; const AMethod: string; AParams: PVariant): Variant;
      var
        method_def: TmbMethod;
        method: pointer;
        pvar: pointer;
        param_count: integer;
        el_size: integer;
        rez: Variant;
      begin
        method_def := FindMethod(AMethod);
        if method_def = nil then
          raise Exception.CreateFmt('Method not found', [AMethod]);
       
        el_size := 0;
        pvar := AParams;
        if AParams = nil then
          param_count := 0
        else
          if VarIsArray(AParams^) then
             with PVarData(AParams).VArray^ do begin
                param_count := Bounds[0].ElementCount;
                pvar := Data;
                el_size := ElementSize;
             end
          else
             param_count := 1;
       
        if method_def.ParamCnt <> param_count then
          raise Exception.CreateFmt('BadMethodParamCount', [AMethod, method_def.ParamCnt, param_count]);
       
        method := method_def.Addr;
        // заносим параметры в стек в обратном порядке (stdcall)
        {$IFDEF WIN32}
        pvar := PAnsiChar(pvar) + (param_count - 1) * el_size;
        while param_count > 0 do begin
          asm
            push pvar
          end;
          Dec(PAnsiChar(pvar), el_size);
          Dec(param_count);
        end;
        asm
          mov  eax, [AObject]    // передаем self
          push eax
        end;
        // Если метод возвращает результат (функция), заносим Result в стек
        if method_def.Result then
          asm
            push Result
          end;
        asm
          call method
        end;
        {$ELSE}
        if param_count = 0 then
          rez := CallFunc(AObject, method, Result)
        else begin
          rez := CallFuncParam(AObject, method, Result, AParams)
        end;
        {$ENDIF}
      end;


    из dll вызываю методы:
    Код:


    ExpandedWrap disabled
      function RegEmployee(const AEmployee: Variant): Variant; stdcall;
      function GetStreets(const ASettlementID, AStreetType: Variant): Variant; stdcall;


    Для методов без параметров CallFunc отрабатывает, и все ок.
    Для методов с параметрами CallFuncParam отрабатывает, но параметры не могу заполнить.

    Помогите дописать CallFuncParam чтобы заполнялись параметры.

    Спасибо.
      D-monua, вы хотите сделать универсальную функцию, которая будет вызывать любой метод с любыми параметрами?
      Почему нельзя обычным образом вызывать методы из DLL, а нужно именно через такую функцию?

      Почему у вас push'атся одни регистры, а pop'ятся другие?
      Вы знаете, что если параметров больше 4-х, их нужно будет заносить в стек? И что надо выравнивать стек и оставлять буфер 20h при вызове процедуры?
      Почитайте про соглашения о вызовах Win x64.

      Добавлено
      И вообще, вы уверены, что вам обязательно нужно работать с типами Variant?
      user posted image Чат форума в Telegramuser posted image Чат форума в Discord (жми и подключайся!) ;)
        D-monua
        Если очень нужна именно такая "универсальная" реализация, то можно использовать методы с открытым массивом Variant-параметров: AParams: array of const. Тогда не придется городить никакой огород на асме.

        Но, судя по примеру вызова из dll
        ExpandedWrap disabled
          function RegEmployee(const AEmployee: Variant): Variant; stdcall;
          function GetStreets(const ASettlementID, AStreetType: Variant): Variant; stdcall;

        вообще не понятно, зачем нужен универсальный способ вызова через единый CallMethod? Почему бы для каждой из этих функций не написать свою реализацию с нормальным вызовом конкретного метода обычным образом без каких-либо выкрутасов с FindMethod и т.д. и т.п.?
        Сообщение отредактировано: leo -
        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
        0 пользователей:


        Рейтинг@Mail.ru
        [ Script Execution time: 0,0924 ]   [ 17 queries used ]   [ Generated: 24.04.18, 06:29 GMT ]