标签: basm

英特尔x86汇编优化技术中的示例问题

我正在学习汇编程序很长一段时间,我正在尝试重写一些简单的过程\函数来查看性能优势(如果有的话).我的主要开发工具是Delphi 2007,第一个例子将使用该语言,但它们也可以很容易地翻译成其他语言.

问题表明:

我们给出了一个无符号字节值,其中八位中的每一位代表一行屏幕中的一个像素.每个单个像素可以是实心(1)或透明(0).换句话说,我们在一个字节值中包含8个像素.我想将这些像素解压缩成一个8字节的数组,就像最年轻的像素(位)将落在数组的最低索引之下一样,依此类推.这是一个例子:

One byte value -----------> eight byte array

10011011 -----------------> [1][1][0][1][1][0][0][1]

Array index number ------->  0  1  2  3  4  5  6  7
Run Code Online (Sandbox Code Playgroud)

下面我介绍解决问题的五种方法.接下来,我将展示他们的时间比较以及我如何衡量这些时间.

我的问题包括两部分:

1.

我问您详细的有关方法的答案DecodePixels4aDecodePixels4b.为什么方法4b有点慢4a

例如,如果我的代码没有正确对齐,它会慢一些,那么告诉我给定方法中哪些指令可以更好地对齐,以及如何做到这一点不破坏方法.

我想看看这个理论背后的真实例子.请记住,我正在学习汇编,我想从你的答案中获得知识,这使我将来能够编写更好的优化代码.

2.

你能写更快的常规DecodePixels4a吗?如果是,请提供并描述您已采取的优化步骤.通过更快的例程,我的意思是在测试环境中在最短的时间段内运行的例程,在此处提供的所有例程中.

允许使用所有Intel系列处理器以及与之兼容的处理器.

您将在下面找到我编写的例程:

procedure DecodePixels1(EncPixels: Byte; var DecPixels: TDecodedPixels);
var
  i3: Integer;
begin
  DecPixels[0] := EncPixels and $01;
  for i3 := 1 to 7 do
  begin
    EncPixels := EncPixels shr 1;
    DecPixels[i3] := …
Run Code Online (Sandbox Code Playgroud)

delphi optimization x86 assembly basm

21
推荐指数
3
解决办法
3835
查看次数

在Delphi中的asm过程结束时要恢复哪些CPU寄存器

在汇编代码中编写Delphi过程或函数时,必须保存哪些寄存器并在过程结束时将其恢复为原始值?

从(内联)汇编代码调用另一个Delphi过程或函数时,我还能期望其他函数与寄存器有什么关系?哪些寄存器将恢复为原始值,哪些可能不会?

(显然,同样的答案适用于这两个问题)

我假设Delphi 的默认调用约定.我知道这EAX用于32位返回值.而看着SysUtils.pas的汇编代码,似乎EBX,ESIEDI推而恢复,但有些则没有.但是,我找不到任何关于此的文档.

delphi assembly cpu-registers basm

13
推荐指数
1
解决办法
1852
查看次数

如果eax包含self,为什么eax为零?

根据"在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;
Run Code Online (Sandbox Code Playgroud)

delphi basm

9
推荐指数
1
解决办法
427
查看次数

为什么Delphi编译器没有内联汇编函数?

有时我会编写很短的汇编函数

function SeniorBit(Value: LongWord): Integer;
asm
        OR    EAX,EAX
        JZ    @@Done
        BSR   EAX,EAX
        INC   EAX
@@Done:
end;
Run Code Online (Sandbox Code Playgroud)

这似乎是内联的最佳候选人:

function SeniorBit(Value: LongWord): Integer; inline;
Run Code Online (Sandbox Code Playgroud)

但是Delphi编译器不允许它.为什么?


更新:

感谢ldsandon,有一份关于QC的一份有着5.5年历史的公开报告.该报告包含一些提议(如扩展asm指令)以简化编译器的asm内联.我更倾向于在过程/函数级别上引入"裸"指令,该指令向编译器说它不必为过程创建堆栈帧,并且可选地应保留哪些寄存器(在eax,edx和ecx中).

如果使用BASM代码进行高效内联过程的一般任务很困难(并且可能是不必要的),那么一个好主意是为最重要的案例启用内联(如明确声明的寄存器使用的裸函数).

delphi assembly inlining basm

7
推荐指数
2
解决办法
1947
查看次数

交换Word变量的字节(低/高)的过程

我有这个过程交换Word变量的字节(低/高)(它做与System.Swap函数相同的东西).当编译器优化为OFF时,该过程有效,但当它处于ON状态时,该过程无效.任何人都可以帮我吗?

procedure SwapWord(VAR TwoBytes: word);   
asm
  Mov EBX, TwoBytes
  Mov AX, [EBX]
  XCHG AL,AH
  Mov [EBX], AX
end;
Run Code Online (Sandbox Code Playgroud)

delphi assembly basm

7
推荐指数
4
解决办法
5271
查看次数

删除用纯汇编编写的函数的序言

我正在使用Delphi 2010.是否可以告诉Delphi不为函数生成序言?我正在写一些像这样的纯汇编函数:

procedure SomeAssembly; stdcall;
begin
    asm
        ...
    end;
end;
Run Code Online (Sandbox Code Playgroud)

我想告诉Delphi不要为这个函数生成一个序言和结语,比如C++的__declspec(naked)特性.

所以没有人浪费他们的时间,我不需要帮助让这些功能序幕一起工作; 我已经可以做到了.这只是一个很大的不便,将使维护成为一个巨大的麻烦.我将不得不手动检查编译器生成的序言以查看它们的长度,如果更改,我的程序将崩溃.

我也知道我可以将函数编写为字节数组中的一系列字节,但这比查找Delphi序言的长度更糟糕.

delphi assembly procedure basm

7
推荐指数
1
解决办法
855
查看次数

Delphi读溢出标志

如果我这样做

var
  a,b,c:cardinal;
begin
  a:=$80000000;
  b:=$80000000;
  c:=a+b;
end;
Run Code Online (Sandbox Code Playgroud)

c将等于0,因为加法溢出.捕获这个溢出的布尔值的最佳方法是什么?(a+b<a) or (a+b<b)?一个非常好的方法是使用内联汇编程序,但我不是那么多的汇编程序(虽然我猜它会包含类似的内容JO)

delphi math inline-assembly basm

7
推荐指数
3
解决办法
662
查看次数

在Delphi中使用Assembly的好资源?

有没有资源学习如何在Delphi中使用汇编?

背景资料

我已经找到并阅读了一些通用程序集和指令集引用(x86,MMX,SSE等).但我发现很难在Delphi中应用这些信息.一般的事情,如如何获得类属性的价值等.

我希望在优化代码时可以选择使用汇编.

我明白:

  • 打败编译器会很困难.
  • 与低级装配优化相比,高级优化技术更有可能将性能提高几个数量级.(例如选择不同的算法,缓存等)
  • 分析至关重要.我正在使用Sampling Profiler进行实际性能分析,并将cpu循环计数用于低级细节.

我有兴趣学习如何在Delphi中使用汇编,因为:

  • 在工具箱中使用另一个工具不会有什么坏处.
  • 它将有助于理解编译器生成的程序集输出.
  • 了解编译器正在做什么可能有助于编写性能更好的pascal代码.
  • 我很好奇.

delphi optimization assembly basm

7
推荐指数
3
解决办法
1740
查看次数

如何探究英特尔®高级矢量扩展的可用性?

如何使用Delphi 2007检查盒子是否支持AVX.

我的问题仅限于查询CPU中的支持(假设操作系统正常/带有SP1的Windows 7).

由Chris Lomont 撰写的题为"英特尔®高级矢量扩展简介 "的PDF文档解释了如何执行此操作,并提供了一个示例代码实现,但在c ++中.

它也可以在这个页面上找到.

delphi delphi-2007 avx basm

7
推荐指数
1
解决办法
1048
查看次数

如何在Delphi XE3中使用align-data-move SSE?

我试图运行以下,

type
  Vector = array [1..4] of Single;

{$CODEALIGN 16}
function add4(const a, b: Vector): Vector; register; assembler;
asm
  movaps xmm0, [a]
  movaps xmm1, [b]
  addps xmm0, xmm1
  movaps [@result], xmm0
end;
Run Code Online (Sandbox Code Playgroud)

它提供了对movaps的访问冲突,据我所知,如果内存位置为16对齐,则可以信任movaps.如果movups(不需要对齐),它没有问题.

所以我的问题是,在Delphi XE3中,{$ CODEALIGN}在这种情况下似乎不起作用.

编辑

很奇怪......我尝试了以下几点.

program Project3;

{$APPTYPE CONSOLE}

uses
  windows;  // if not using windows, no errors at all

type
  Vector = array [1..4] of Single;

function add4(const a, b: Vector): Vector;
asm
  movaps xmm0, [a]
  movaps xmm1, [b]
  addps …
Run Code Online (Sandbox Code Playgroud)

delphi assembly sse basm

7
推荐指数
1
解决办法
1697
查看次数