Цитата:
Сообщение от 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
из этой статьи
но я не знаю как это применить, так как в ассеме полный нуб помогите плиз, чуток осталось
|