Этот вопрос основан на previous, но это только FYI.Метод вызова объекта с использованием ASM - Часть 2
Мне удалось заставить его работать, однако я нашел то, что мне непонятно, поэтому, если кто-нибудь может объяснить следующее поведение, это было бы потрясающе.
У меня есть следующий класс:
type
TMyObj = class
published
procedure testex(const s: string; const i: integer);
end;
procedure TMyObj.testex(const s: string; const i: integer);
begin
ShowMessage(s + IntToStr(i));
end;
и следующие две процедуры:
procedure CallObjMethWorking(AMethod: TMethod; const AStrValue: string; const AIntValue: Integer);
begin
asm
PUSH DWORD PTR AIntValue;
PUSH DWORD PTR AStrValue;
CALL AMethod.Code;
end;
end;
procedure CallObjMethNOTWorking(AInstance, ACode: Pointer; const AStrValue: string; const AIntValue: Integer);
begin
asm
MOV EAX, AInstance;
PUSH DWORD PTR AIntValue;
PUSH DWORD PTR AStrValue;
CALL ACode;
end;
end;
Для того, чтобы проверить рабочую версию, нужно назвать следующие:
procedure ...;
var
LObj: TMyObj;
LMethod: TMethod;
LStrVal: string;
LIntVal: Integer;
begin
LObj := TMyObj.Create;
try
LMethod.Data := Pointer(LObj);
LMethod.Code := LObj.MethodAddress('testex');
LStrVal := 'The year is:' + sLineBreak;
LIntVal := 2012;
CallObjMethWorking(LMethod, LStrVal, LIntVal);
finally
LObj.Free;
end; // tryf
end;
и для тестирования NOT рабочий вариант иона:
procedure ...;
var
LObj: TMyObj;
LCode: Pointer;
LData: Pointer;
LStrVal: string;
LIntVal: Integer;
begin
LObj := TMyObj.Create;
try
LData := Pointer(LObj);
LCode := LObj.MethodAddress('testex');
LStrVal := 'The year is:' + sLineBreak;
LIntVal := 2012;
CallObjMethNOTWorking(LData, LCode, LStrVal, LIntVal);
finally
LObj.Free;
end; // tryf
end;
И, наконец, вопрос: почему не CallObjMethNOTWorking работать, в то время как CallObjMethWorking это? Я предполагаю, что есть что-то особенное в том, как компилятор относится к TMethod ... но поскольку мои знания сборки ограничены, я не могу этого понять.
Я был бы очень признателен, если бы кто-нибудь мог объяснить это мне, спасибо!
3 параметра передаются в регистры. Я не знаю, куда вступает игра. Вы прочитали раздел управления программой руководства по delphi? –
@ Давид, я просто сделал, кажется, что если я позвоню PUSH EAX, MOV EDX, DWORD PTR AStrValue; MOV ECX, DWORD PTR AIntValue; CALL ACode; он работает отлично, за исключением того, что он вызывает исключение (после выполнения) ..., я понимаю, что строка уже передана по ссылке и целое значение по значению, но я до сих пор не получаю ее ... – ComputerSaysNo
почему вы толкаете EAX? И зачем вам нужно использовать метод asm для вызова метода? –