64位等效于x86图像处理程序中的BSWAP 我在例行程序中使用的Delphi Firemonkey Exif实现来加载图像文件。 我正在尝试确定图像是否已旋转,因此我可以纠正

问题描述 投票:0回答:2
当该应用程序是为32位窗口构建时,该应用程序正常,但是在64位窗口下的Swaplong呼叫中失败。 我不知道有关汇编语言的第一件事,因此我正在寻找如何在构建程序的64位版本时处理相同功能。 正如注意到的那样,在两个版本中,IDF.Offset值传递给Swaplong函数的值为134217728($ 08000000)。 在32位版本中,Swaplong返回8个值,但是64位版本的值返回2694969615的值,给定似乎是相同的输入。 我需要使用相同代码的64位MAC OSX来瞄准64位版本。 任何帮助将不胜感激。

The issue exists because the inline assembly assumes the first argument as well as the return value to be using register 
eax

, which is true for Delphi in 32-bit mode as per Delphi's

calling convention

(and although the

inline assembly documentation
delphi assembly x86-64
2个回答
10
投票
ebp

and

esp
, this always held true even inside of inline assembly statements when they were placed at the top of a function). 否,64位模式使用一个不同的呼叫惯例,其中第一个参数在
rcx
中,返回值正在使用
rax
。因此,在这里,您将随机的非初始化垃圾作为恰好在该寄存器中的返回值(与其字节交换),因为它从未明确设置。

最好的便携式解决方案是在没有内联装配的情况下实现纯Pascal的字节交换:

function SwapLong(Value: Cardinal): Cardinal; begin Result := Swap(Value shr 16) or (Cardinal(Swap(Value)) shl 16); end;

使用数十年的
Swap
函数

换了值的较低2个字节。这本身就不再有用了,但是可以使用两次(以及一些位移和掩盖)来缩短代码以换成所有4个字节32位值的代码。

具有更多源代码但可能会产生较少复杂的装配代码的Another Way将是访问the in中的单个字节:

使用字节指针:
Cardinal

64位组件通过与32位不同的寄存器中的参数传递。在这种情况下,参数将在ECX寄存器中,返回值必须在EAX中。
对于32位和64位组件需要不同的代码。

function SwapLong(Value: Cardinal): Cardinal; inline; begin PByte(@Result)^ := PByte(NativeUInt(@Value) + 3)^; PByte(NativeUInt(@Result) + 1)^ := PByte(NativeUInt(@Value) + 2)^; PByte(NativeUInt(@Result) + 2)^ := PByte(NativeUInt(@Value) + 1)^; PByte(NativeUInt(@Result) + 3)^ := PByte(@Value)^; end;

由于仅在Windows上可用,因此其他平台需要纯Pascal代码,如
Cherrydt的答案

    

3
投票
function SwapLong(Value: Cardinal): Cardinal; {$IFDEF ASSEMBLER} {$IFDEF CPUX86} asm bswap eax end; {$ENDIF CPUX86} {$IFDEF CPUX64} asm mov eax, ecx bswap eax end; {$ENDIF CPUX64} {$ELSE} begin // pascal version end; {$ENDIF}

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.