![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
![]() Здравствуйте, уже полторы недели туплю, над "волшебной" функцией заданной мне преподом, эта "уникальная" функция должна уметь загружать библиотеки, и использовать их функции, основоваясь на входящих аргументах: имя длл, имя функции, внутренние аргументы, заданные строкой. т.е. примерно так
Код:
Function SetFunction(dll,adress:string;a:array of b;l:integer):b; var Func:function(a:array of b):HINST;stdcall; _dll:integer; begin _dll:=LoadLibrary(PChar(dll)); if(_dll<>0)then begin @Func:=getProcAddress(_dll,PChar(adress)); if(addr(Func)<>nil)then begin Func(a); //setlength(result,l); end; end; end; это то что я наклепал, я никак не могу решить праблу внутренних параметров(((( глаза уже мутные и мозг плавится, кто подскажет... помогите, всё что плохо обьяснил спросите, отвечу как смогуууу |
#2
|
||||
|
||||
![]() Веселый, однако, препод. В длл функции могут по разным соглашениям вызываться, да и кол-во аргументов ф-ии заведомо не известно может быть. Если надо чтоб идеально работало, надо писать алгоритм анализа, как устроена ф-ия в длл (самый простой вариант - искать информацию в map файле, если таковой имеется). если же простяцкое-босяцкое, то просто пушить в стек аргументы (если дллка stdcall).
Код:
asm push arg3 push arg2 push arg1 call Func end; — Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
Этот пользователь сказал Спасибо M.A.D.M.A.N. за это полезное сообщение: | ||
reqyz (22.10.2012)
|
#3
|
|||
|
|||
![]() можно подробнее пример, да функции stdcall, как этот асм использовать я с асемом просто дело не имел никогда(
с прописанием внутренних аргументов вся и загвоздка представь, есть форма, на ней куча едитов, в первый выбираешь имя длл во второй имя функции в ней, в третьем выбираешь типы параметров и значения, наример integer 8 string 'thtyhty' byte true нажимаешь кнопочку и это всё срабатывает, аргументы пусть пользователь вводит правильно, но программно то как это сформировать... ппц(( Последний раз редактировалось reqyz, 22.10.2012 в 20:27. |
#4
|
||||
|
||||
![]() А препод с каким званием? Доцент/профессор?
Чем-то смахивает на "подметать плацдарм ломом". — Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#5
|
||||
|
||||
![]() Цитата:
Код:
var hModule: DWORD; proc: pointer; a: DWORD; Params: array of DWORD; ... hModule := LoadLibrary(Edit1.Text); proc := GetProcAddress(hModule, Edit2.Text); if (proc <> 0) then begin asm mov esi, Params mov ecx, count lea esp, [esp - ecx * 4] mov edi, esp cld rep movsd mov eax, proc call eax end; end else MessageBoxA(0, 'Печальная история...', 'Ошибка', 0); jmp $ ; Happy End! The Cake Is A Lie. Последний раз редактировалось Bargest, 22.10.2012 в 21:14. |
#6
|
|||
|
|||
![]() спасибо, потестю)
а что делать если среди параметров есть строка? |
#7
|
||||
|
||||
![]() Цитата:
Тогда нужно уметь работать всего лишь с двумя типами значений -- строкой и числом (DWORD). LONGBOOL -- тоже DWORD. В синтаксисе inf-файлов строки обычно заключаются в кавычки, а числа передаются просто так. Можно еще 16-ричные числа обрабатывать, которые заданы как 0x########, но это уже на любителя. |
#8
|
|||
|
|||
![]() Цитата:
реализовал функцию, всё кроме конст работает) вары возвращает) всё работает прекрассно) вот сама функция: Код:
function SetFunction(dll, adress, param: String;out res2:string;l:integer): LongWord; type TPoint=record x:Int64; y:byte; end; Tp=record s:string; c:Char; end; var hdll: HMODULE; proc: Pointer; Params: array of LongWord; _par:array of TPoint;//0 1 2 3 Strings: array of String; PrmCount, StrCount, p,i: Integer; pp:array[0..2]of Tp; //param =var integer:const 8;boolean:1;out pchar:reqyz; integer:8; ...//например begin hdll := LoadLibrary(Pointer(dll)); if hdll = 0 then exit; try proc := GetProcAddress(hdll, Pointer(adress)); if not Assigned(proc) then exit; PrmCount := 0; StrCount := 0; setlength(_par,l); setlength(Params,l); pp[0].c:=' '; pp[1].c:=':'; pp[2].c:=';'; while param <> '' do begin for i:=0 to 2 do begin p := Pos(pp[i].c, param); pp[i].s := Copy(param, 1, p - 1); Delete(param, 1, p); end; if(pp[1].s = 'boolean')or(pp[1].s = 'integer')then Params[PrmCount] := StrToInt(pp[2].s) else if pp[1].s = 'pchar' then begin // Здесь строки нигде не сохранялись, поэтому указатели на них теряли актуальность if Length(Strings) = StrCount then SetLength(Strings, StrCount + 10); Strings[StrCount] := pp[2].s; Params[PrmCount] := longWORD(Strings[StrCount]); Inc(StrCount); end; if(pp[0].s = 'var')then begin _par[PrmCount].y:=1; _par[PrmCount].x:=Params[PrmCount]; Params[PrmCount]:=integer(@_par[PrmCount].x); end else if(pp[0].s = 'const')then _par[PrmCount].y:=2 else if(pp[0].s = 'out')then begin _par[PrmCount].y:=3; _par[PrmCount].x:=Params[PrmCount]; Params[PrmCount]:=integer(@_par[PrmCount].x); end else if(pp[0].s = '')then _par[PrmCount].y:=0; 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].y=1)or(_par[p].y=3) then res2:=res2+inttostr(p)+':'+inttostr(_par[p].x)+';'; finally FreeLibrary(hdll); end; end; но есть странные особенности при использовании констант Код:
//например так функция работает: Function func(const a,b:longword):LongWord;stdcall begin if(a<>b)then end;//часть в длл-ке procedure TForm1.Button1Click(Sender: TObject); begin SetFunction('project2.dll','func','const integer:5;const integer:4;',s,2); end;//использование //так функция тоже работает: type req=record a,b:longword; end; Function func(z:req):LongWord;stdcall begin if(z.a<>z.b)then end;//часть в длл-ке procedure TForm1.Button1Click(Sender: TObject); begin SetFunction('project2.dll','func',' integer:5; integer:4;',s,2); end;//использование //а так функция не работает: type req=record a,b:longword; end; Function func(const z:req):LongWord;stdcall begin if(z.a<>z.b)then end;//часть в длл-ке procedure TForm1.Button1Click(Sender: TObject); begin SetFunction('project2.dll','func','const integer:5;const integer:4;',s,2); end;//использование я не понимаю почему( кто нибудь знает? я предполагаю, что в последнем случае функция ожидает указатель, я прав? да, как оказалось, я прав, в случае, когда константой является несколько одновременно параметров, то нужно передавать один указатель на них Последний раз редактировалось reqyz, 25.10.2012 в 09:49. |
#9
|
|||
|
|||
![]() для общего развития неплохо бы прочитать
http://www.transl-gunsmoker.ru/2008/12/1.html http://www.transl-gunsmoker.ru/2008/12/2.html http://www.transl-gunsmoker.ru/2008/12/3.html http://www.transl-gunsmoker.ru/2008/12/4-ia64.html http://www.transl-gunsmoker.ru/2008/12/5-amd64.html Особенно третью и пятую части. По передаче параметров тут так. - говорю за x86 - stdcall Без модификаторов const,var или out boolean, char, целочисленные вплоть до (LongInt/DWORD), а так же всякие Pointer`ы- каждая величина кладётся в стек и занимает в стеке 4 байта. Int64 кладётся в стек и занимает в стеке 8 байт. String - представляет собой указатель на первый символ строки и занимает в стеке 4 байта. Перед вызовом процедуры производится увеличение количества ссылок на строку. Record, состоящий из вышеперечисленного кладётся в стек весь целиком. С модификатором const boolean, char, целочисленные вплоть до (LongInt/DWORD), а так же всякие Pointer`ы - каждая величина кладётся в стек и занимает в стеке 4 байта. Int64 - кладётся в стек и занимает в стеке 8 байт. String - представляет собой указатель на первый символ строки и занимает в стеке 4 байта. Увеличение счётчика не производится. Record`ы - в стек кладётся указатель на начало структуры. С модификатором var Для всех типов в стек кладётся адрес переменной. С модификатором out Для всех типов в стек кладётся адрес переменной. |
#10
|
|||
|
|||
![]() в догонку
Возвращаемое значение boolean, char, byte, shortint - возвращаются в регистре AL word и smallint - возвращаются в регистре AX В Win-API накой способ не используется. Как правило возвращается целиком регистр EAX. LongInt,DWORD, а так же всякие Pointer`ы- возвращаются в регистре EAX. Int64 - возвращаются в регистрах EAX:EDX. Record - вызывающая программа должна подготовить место для record`а, и передать его адрес в качестве неявного параметра, расположеного после всех явных параметров. Вызываемая процедура работает с этим параметром как с параметром с out-модификатором. |
#11
|
|||
|
|||
![]() А по теме.
тебе нужно разбить твою супер функцию на две или три части. Первая - получения адреса функции из DLL+всякие проверки. Вторая - разбор параметров и укладка их в массив. Безо всякого асма. И третья сам вызов - тут самая большая проблема, которая, если её выделить, может сильно упроститься. например до вот этого Код:
type TFunction = function():DWord;stdcall; function SuperCall(F:TFunction; const Params : Array of DWord):DWord; var I:Integer; P:Pointer; begin for I:=0 to Length(Params)-1 do begin P:=@Params[i]; asm mov EAX,P; Push [EAX]; <<<<----====== end; end; Result:=F(); end; |