Показать сообщение отдельно
  #25  
Старый 24.10.2012, 11:56
reqyz reqyz вне форума
Начинающий
 
Регистрация: 13.02.2010
Сообщения: 104
Репутация: 10
По умолчанию

Цитата:
Сообщение от poli-smen
Теоретически конечно можно, но будет посложнее. Например out (а также часто и var) означает, что эта функция может возвращать результат через эти параметры, а значит в функции SetFunction нужно как-то предусмотреть возможность получения дополнительных результатов от вызываемой функции.

я представляю как в этой функции получать результаты, но я не знаю совсем ассемблер и не знаю что писать там.

как я представляю:
Код:
function SetFunction(dll, adress, param: String;out res2:string): LongWord;
var
  hdll: HMODULE;
  LastError: LongWord;
  proc: Pointer;
  Params: array of LongWord;
  _par:array of byte;//0 1 2 3
  Strings: array of String;
  PrmCount, StrCount, p: Integer;
  p0, p1, p2: String;
  //param =var integer:const 8;boolean:1;out char:reqyz; integer:8; ...//например
begin
  hdll := LoadLibrary(Pointer(dll));
  if hdll = 0 then
  begin
    LastError := GetLastError;
    RaiseErrorFmt('При загрузке библиотеки "%s" возникла ошибка №%d: "%s"',
      [dll, LastError, SysErrorMessage(LastError)]);
  end;

  try
    proc := GetProcAddress(hdll, Pointer(adress));
    if not Assigned(proc) then
      RaiseErrorFmt('В библиотеке "%s" отсутствует процедура "%s"', [dll, adress]);

    PrmCount := 0;
    StrCount := 0;

    while param <> '' do
    begin
      p := Pos(' ', param);
      if p = 0 then RaiseErrorFmt('Ожидался символ " " в строке "%s"', [param]);
      p0 := Copy(param, 1, p - 1);
      Delete(param, 1, p);

      p := Pos(':', param);
      if p = 0 then RaiseErrorFmt('Ожидался символ ":" в строке "%s"', [param]);
      p1 := LowerCase(Copy(param, 1, p - 1));
      Delete(param, 1, p);

      p := Pos(';', param);
      if p = 0 then RaiseErrorFmt('Ожидался символ ";" в строке "%s"', [param]);
      p2 := Copy(param, 1, p - 1);
      Delete(param, 1, p);

      if Length(Params) = PrmCount then
      begin
        SetLength(Params, PrmCount + 10);
        SetLength(_par, PrmCount + 10);
      end;

      if(p0 = 'var')then
        _par[PrmCount]:=1
      else
      if(p0 = 'const')then
        _par[PrmCount]:=2
      else
      if(p0 = 'out')then
        _par[PrmCount]:=3
      else
      if(p0 = '')then
        _par[PrmCount]:=0
      else
        RaiseErrorFmt('Неподдерживаемый тип "%s"', [p0]);

      if p1 = 'integer' then
        Params[PrmCount] := StrToInt(p2)
      else
      if p1 = 'boolean' then
        Params[PrmCount] := StrToInt(p2)
      else
      if p1 = 'pchar' then
      begin // Здесь строки нигде не сохранялись, поэтому указатели на них теряли актуальность
        if Length(Strings) = StrCount then
          SetLength(Strings, StrCount + 10);
        Strings[StrCount] := p2;
        Params[PrmCount] := DWORD(Strings[StrCount]);
        Inc(StrCount);
      end else
      begin
        RaiseErrorFmt('Неподдерживаемый тип "%s"', [p1]);
      end;
      Inc(PrmCount);
    end;

    asm
      PUSH ESI
      PUSH EDI
      MOV  ESI, Params
      MOV  ECX, PrmCount
      NEG  ECX
      LEA  ESP, [ESP + ECX * 4] // Здесь была ошибочная инструкция lea esp, [esp - ecx * 4]
      NEG  ECX
      MOV  EDI, ESP
      CLD
      REP  MOVSD
      MOV  EAX, proc
      CALL EAX
      MOV  Result, EAX // Сохраняем результат работы вызванной функции
      POP  EDI
      POP  ESI
    end;
    res2:='';
    for p:=0 to length(_par)-1 do
      if(_par[p]=1)or(_par[p]=3)
        then
          res2:=res2+inttostr(p)+':'+inttostr(Params[p])+';';
  finally
    FreeLibrary(hdll);
  end;
end;

нарыл вот это

Передача параметров по значению говорится о const?

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

Например, если параметры передаются в регистрах:
Код:
        mov        ax,word ptr value   ; сделать копию значения
        call       procedure           ; вызвать процедуру
Передача параметров по ссылке напоминает out

Процедуре передается не значение переменной, а ее адрес, по которому процедура должна сама прочитать значение параметра. Этот механизм удобен для передачи больших массивов данных и для тех случаев, когда процедура должна модифицировать параметры, хотя он и медленнее из-за того, что процедура будет выполнять дополнительные действия для получения значений параметров.
Код:
        mov        ax,offset value
        call       procedure
Передача параметров по возвращаемому значению//похоже на var

Этот механизм объединяет передачу по значению и по ссылке. Процедуре передают адрес переменной, а процедура делает локальную копию параметра, затем работает с ней, а в конце записывает локальную копию обратно по переданному адресу. Этот метод эффективнее обычной передачи параметров по ссылке в тех случаях, когда процедура должна обращаться к параметру достаточно большое число раз, например, если используется передача параметров в глобальной переменной:
Код:
        mov        global_variable,offset value
        call       procedure
        [...]
procedure proc near
        mov        dx,global_variable
        mov        ax,word ptr [dx]
       (команды,  работающие с АХ в цикле десятки тысяч раз)
        mov        word ptr [dx],ax
procedure endp

из этой статьи

но я не знаю как это применить, так как в ассеме полный нуб помогите плиз, чуток осталось
Ответить с цитированием