小编Mar*_*adu的帖子

德尔福:记录领域的抵消

我正在寻找获得Delphi记录中字段偏移的方法.以下两种方法有效,但我希望有一种更清洁的方式.基本上我会喜欢第三个showmessage工作.有任何想法吗?

type
 rec_a=record
  a:longint;
  b:byte;
  c:pointer;
 end;

{$warnings off}
function get_ofs1:longint;
var
 abc:^rec_a;
begin
 result:=longint(@abc.c)-longint(abc);
end;
{$warnings on}

function get_ofs2:longint;
asm
 mov eax,offset rec_a.c
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 showmessage(inttostr(get_ofs1));
 showmessage(inttostr(get_ofs2));
// showmessage(inttostr(longint(addr(rec_a.c)))); // is there a way to make this one work?
end;
Run Code Online (Sandbox Code Playgroud)

编辑:好的,下面的答案很好,谢谢!作为参考,这里是各种选项的汇编输出:

---- result:=longint(@abc.c)-longint(abc); ----
lea edx,[eax+$08]
sub edx,eax
mov eax,edx

---- mov eax,offset rec_a.c ----
mov eax,$00000008

---- result:=longint(@rec_a(nil^).c); ----
xor eax,eax
add eax,$08
Run Code Online (Sandbox Code Playgroud)

edit2:看起来这是前一个问题的重复:RRUZ下面提到的类似问题.如图所示,另一种方法是声明一个全局变量并按如下方式使用它.奇怪的是,编译器仍然无法在编译时分配正确的值,如汇编器输出中所示,因此为了效率和可读性,最好使用nil方法.

---- var ----
----  rec_a_ofs:rec_a; ----
---- ... ---- …
Run Code Online (Sandbox Code Playgroud)

delphi record offset

17
推荐指数
1
解决办法
2534
查看次数

"或eax,eax"和"test eax,eax"之间的区别

or eax,eax和之间有什么区别test eax,eax?我已经看到不同的编译器生成两者用于相同的比较,并且就文档而言它们做的完全相同,所以我想知道为什么它们并非全部使用test eax,eax.考虑它and eax,eax会以同样的方式设置标志,但我没有在freepascal,delphi或msVC++中看到它.

我确实在delphi中编译了一些asm块并检查了汇编源代码,并且所有3种形式在操作码中的长度完全相同,并且还检查了英特尔性能PDF并且它说它们具有相同的延迟和吞吐量.

编辑:
问题具体是关于具体案例之间的区别test eax,eax,or eax,eax和and eax,eax.对于寄存器,标志,操作码长度,延迟,吞吐量,所有3都给出完全相同的结果.然而,如果测试0,如果不是零,或者如果签名,一些编译器会在使用test eax,eax时使用or eax,eax,我想知道为什么它们并非全部使用,test eax,eax因为它使代码更加清晰.

编辑2:
作为参考,我在家里只有老版本的msvc ++和Delphi,但测试一个变量,如果为零,msvc ++就是这样test eax,eax,而Delphi则是or eax,eax.

x86 assembly micro-optimization

8
推荐指数
1
解决办法
3727
查看次数

标签 统计

assembly ×1

delphi ×1

micro-optimization ×1

offset ×1

record ×1

x86 ×1