gpt4 book ai didi

delphi - 如果 eax 包含 self,为什么它给出零?

转载 作者:行者123 更新时间:2023-12-03 14:43:21 25 4
gpt4 key购买 nike

根据"Using Assembler in Delphi" , eax 将包含 Self。然而,如图所示,eax 的内容为 0。我想知道出了什么问题?

procedure TForm1.FormCreate(Sender: TObject);
var
X, Y: Pointer;
begin
asm
mov X, eax
mov Y, edx
end;
ShowMessage(IntToStr(NativeInt(X)) + ' ; ' + IntToStr(NativeInt(Y)));
end;

最佳答案

在调试设置下编译此代码时生成的代码如下所示:

  begin005A9414 55               push ebp005A9415 8BEC             mov ebp,esp005A9417 83C4E4           add esp,-$1c005A941A 33C9             xor ecx,ecx005A941C 894DEC           mov [ebp-$14],ecx005A941F 894DE8           mov [ebp-$18],ecx005A9422 894DE4           mov [ebp-$1c],ecx005A9425 8955F0           mov [ebp-$10],edx005A9428 8945F4           mov [ebp-$0c],eax005A942B 33C0             xor eax,eax005A942D 55               push ebp005A942E 6890945A00       push $005a9490005A9433 64FF30           push dword ptr fs:[eax]005A9436 648920           mov fs:[eax],esp  mov X, eax005A9439 8945FC           mov [ebp-$04],eax  mov Y, edx005A943C 8955F8           mov [ebp-$08],edx

When the code starts executing, eax is indeed the self pointer. But the compiler has chosen to save it away to ebp-$0c and then zeroise eax. That's really up to the compiler.

The code under release settings is quite similar. The compiler still chooses to zeroise eax. Of course, you cannot rely on the compiler doing that.

  begin005A82A4 55               push ebp005A82A5 8BEC             mov ebp,esp005A82A7 33C9             xor ecx,ecx005A82A9 51               push ecx005A82AA 51               push ecx005A82AB 51               push ecx005A82AC 51               push ecx005A82AD 51               push ecx005A82AE 33C0             xor eax,eax005A82B0 55               push ebp005A82B1 6813835A00       push $005a8313005A82B6 64FF30           push dword ptr fs:[eax]005A82B9 648920           mov fs:[eax],esp  mov X, eax005A82BC 8945FC           mov [ebp-$04],eax  mov Y, edx005A82BF 8955F8           mov [ebp-$08],edx

Remember that parameter passing defines the state of registers and stack when the function starts executing. What happens next, how the function decodes the parameters is down to the compiler. It is under no obligation to leave untouched the registers and stack that were used for parameter passing.

If you inject asm into the middle of a function, you cannot expect the volatile registers like eax to have particular values. They will hold whatever the compiler happened to put in them most recently.

If you want to examine the registers at the very beginning of the execution of the function, you need to use a pure asm function to be sure to avoid having the compiler modify the registers that were used for parameter passing:

var
X, Y: Pointer;
asm
mov X, eax
mov Y, edx
// .... do something with X and Y
end;
<小时/>

编译器的选择很大程度上取决于函数其余部分的代码。对于您的代码,组装要传递给 ShowMessage 的字符串的复杂性会导致相当大的前导码。请考虑以下代码:

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
i: Integer;
function Sum(j: Integer): Integer;
end;
....
procedure TForm1.FormCreate(Sender: TObject);
begin
i := 624;
Caption := IntToStr(Sum(42));
end;

function TForm1.Sum(j: Integer): Integer;
var
X: Pointer;
begin
asm
mov X, eax
end;
Result := TForm1(X).i + j;
end;

在这种情况下,代码足够简单,编译器可以忽略eaxSum 的优化发布构建代码是:

  begin005A8298 55               push ebp005A8299 8BEC             mov ebp,esp005A829B 51               push ecx  mov X, eax005A829C 8945FC           mov [ebp-$04],eax  Result := TForm4(X).i + j;005A829F 8B45FC           mov eax,[ebp-$04]005A82A2 8B80A0030000     mov eax,[eax+$000003a0]005A82A8 03C2             add eax,edx  end;005A82AA 59               pop ecx005A82AB 5D               pop ebp005A82AC C3               ret 

当您运行代码时,表单的标题将更改为预期值。

<小时/>

说实话,内联汇编作为 asm block 放置在 Pascal 函数中并不是很有用。编写汇编的问题是你需要充分理解寄存器和堆栈的状态。这是在 ABI 定义的函数的开头和结尾处明确定义的。

但在函数中间,该状态完全取决于编译器做出的决定。在其中注入(inject) asm block 需要您了解编译器所做的决定。这也意味着编译器无法理解您所做的决定。这通常是不切实际的。事实上,对于 x64 编译器,Embarcadero 禁止了此类内联 asm block 。我个人从未在代码中使用过内联 asm block 。如果我编写 asm,我总是编写纯 asm 函数。

关于delphi - 如果 eax 包含 self,为什么它给出零?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23128678/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com