- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
根据"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;
在这种情况下,代码足够简单,编译器可以忽略eax
。 Sum
的优化发布构建代码是:
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/
让我们写一个简单的类在我的脑海中解释: class SomeClass { var happyToUsed = 10 } 并创建一个对象 let someObject = SomeClass(
采用 self 的方法与采用 &self 甚至 &mut self 的方法有什么区别? 例如 impl SomeStruct { fn example1(self) { } fn ex
请观察以下代码(Win10上的python 3.6,PyCharm),函数thread0(self)作为线程成功启动,但是 thread1(self)似乎与thread0(self)不同已设置。 se
backbone.js 开始于: //Establish the root object, `window` (`self`) in the browser, or `global` on the s
做的事: self = self.init; return self; 在 Objective-C 中具有相同的效果: self.init() 快速? 例如,在这种情况下: else if([form
我查看了关于堆栈溢出的一些关于使用[weak self]和[unowned self]的问题的评论。我需要确保我理解正确。 我正在使用最新的 Xcode - Xcode 13.4,最新的 macOS
我面临在以下模型类代码中的 self.init 调用或分配给 self 之前使用 self 的错误tableview单元格项目,它发生在我尝试获取表格单元格项目的文档ID之后。 应该做什么?请推荐。
晚上好。 我对在 Swift 中转义(异步)闭包有疑问,我想知道哪种方法是解决它的最佳方法。 有一个示例函数。 func exampleFunction() { functionWithEsca
我需要在内心深处保持坚强的自我。 我知道声明[weak self]就够了外封闭仅一次。 但是guard let self = self else { return }呢? ,是否也足以为外部闭包声明一
代码 use std::{ fs::self, io::self, }; fn rmdir(path: impl AsRef) -> io::Result { fs::remo
我检查了共享相同主题的问题,但没有一个解决我遇到的这种奇怪行为: 说我有一个简单的老学校struct : struct Person { var name: String var age:
我应该解释为什么我的问题不是重复的:TypeError: can only concatenate list (not “str”) to list ...所以它不是重复的,因为该帖子处理代码中出现的
我有一个 trait,它接受一个类型参数,我想说实现这个 trait 的对象也会符合这个类型参数(使用泛型,为了 Java 的兼容性) 以下代码: trait HandleOwner[SELF
这个问题在这里已经有了答案: Why would a JavaScript variable start with a dollar sign? [duplicate] (16 个答案) 关闭 8
我总是找到一些类似的代码newPromise.promiseDispatch.apply(newPromise, message),我不明白为什么不使用newPromise.promiseDispat
我看到类似的模式 def __init__(self, x, y, z): ... self.x = x self.y = y self.z = z ... 非
mysql查询示例: SELECT a1.* FROM agreement a1 LEFT JOIN agreement a2 on a1.agreementType = a2.agreementTy
self.delegate = self; 这样做有什么问题吗?正确的做法是什么? 谢谢,尼尔。 代码: (UITextField*)initWith:(id)sender:(float)X:(flo
为什么要声明self在类中需要的结构中不需要?我不知道是否还有其他例子说明了这种情况,但在转义闭包的情况下,确实如此。如果闭包是非可选的(因此是非转义的),则不需要声明 self在两者中的任何一个。
这个问题已经有答案了: What does the ampersand (&) before `self` mean in Rust? (1 个回答) 已关闭去年。 我不清楚 self 之间有什么区别
我是一名优秀的程序员,十分优秀!