Delphi 交换字变量字节(低/高)的过程
我有一个交换单词变量字节(低/高)的过程(它的功能与System.Swap函数相同)。该过程在编译器优化关闭时工作,但在打开时不工作。 有人能帮我吗Delphi 交换字变量字节(低/高)的过程,delphi,assembly,basm,Delphi,Assembly,Basm,我有一个交换单词变量字节(低/高)的过程(它的功能与System.Swap函数相同)。该过程在编译器优化关闭时工作,但在打开时不工作。 有人能帮我吗 procedure SwapWord(VAR TwoBytes: word); asm Mov EBX, TwoBytes Mov AX, [EBX] XCHG AL,AH Mov [EBX], AX end; 你考虑过使用编译器的函数吗 procedure TForm1.FormCreate(Sender: TObject
procedure SwapWord(VAR TwoBytes: word);
asm
Mov EBX, TwoBytes
Mov AX, [EBX]
XCHG AL,AH
Mov [EBX], AX
end;
你考虑过使用编译器的函数吗
procedure TForm1.FormCreate(Sender: TObject);
var
a: word;
begin
a := $1234;
a := Swap(a);
Caption := IntToHex(a, 4)
end;
如果不是,您就不需要ASM(而且ASM可能在64位Delphi中不可用)。你可以这么做
procedure MySwap(var a: word);
var
tmp: byte;
begin
tmp := PByte(@a)^;
PByte(@a)^ := PByte(NativeUInt(@a) + sizeof(byte))^;
PByte(NativeUInt(@a) + sizeof(byte))^ := tmp;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
a: word;
begin
a := $123456;
MySwap(a);
Caption := IntToHex(a, 4)
end;
当然,在这个主题上有“一百万”种变体
procedure MySwap(var a: word);
var
tmp: byte;
type
PWordRec = ^TWordRec;
TWordRec = packed record
byte1, byte2: byte;
end;
begin
with PWordRec(@a)^ do
begin
tmp := byte1;
byte1 := byte2;
byte2 := tmp;
end;
end;
简单地说
procedure MySwap(var a: word);
begin
a := word(a shl 8) + byte(a shr 8);
end;
或
如果不保存/还原EBX寄存器,则无法在ASM代码中使用它。您的代码的更正版本为
procedure SwapWord_Working(VAR TwoBytes: word);
asm
PUSH EBX // save EBX
Mov EBX, TwoBytes
Mov AX, [EBX]
XCHG AL,AH
Mov [EBX], AX
POP EBX // restore EBX
end;
最快:
function ReverseWord(w: word): word;
asm
{$IFDEF CPUX64}
mov rax, rcx
{$ENDIF}
xchg al, ah
end;
如果您也要反转DWORD,请执行以下操作:
function ReverseDWord(dw: cardinal): cardinal;
asm
{$IFDEF CPUX64}
mov rax, rcx
{$ENDIF}
bswap eax
end;
我有点惊讶,没有人提到“黑客”这个词,这个词已经存在了十多年,但没有引起太多的关注。。。不管怎样,这是我的两分钱
function SwapWordBytes(const Value: Word): Word;
var
// shares memory with Value parameter
LMemValue: array[0..1] of Byte absolute Value;
// shares memory with Result
LMemResult: array[0..1] of Byte absolute Result;
begin
LMemResult[0] := LMemValue[1];
LMemResult[1] := LMemValue[0];
end;
尽管塞尔格的答案肯定是正确的,正如对塞尔格答案的评论中所指出的那样,它并不高效。最快的显然是Gabr答案中提供的代码,但由于您明确想要的是一个过程,而不是一个函数,下面是Serg例程的首选版本:
procedure SwapWord_Working2 (VAR TwoBytes: word);
asm
mov dx, [TwoBytes] ;//[TwoBytes] = [eax] on x86 *[Note1]
xchg dl, dh
mov [TwoBytes], dx
end;
[注1:]Serg版本的函数很可能不适用于即将推出的x64 Delphi编译器。假设Embarcadero坚持他们使用Win64调用约定的计划(Allen Bauer在某个地方提到过)(其中
@TwoBytes
将通过RCX
传递),那么这个答案中提供的版本应该仍然可以在x64上使用。我的第一个猜测是,它可以完美地工作,也许优化导致了您意想不到的调试结果。你能为我们提供一个最低限度的复制案例吗?或者,你可以使用ECX或EDX,你不需要保存。我看到你在几秒钟内就打败了我。我将删除我的(几乎相同的)答案。当然还有+1。@Andreas:对不起。你的详细答案是+1。嗨,安德烈亚斯。你为什么说在Delphi 64下不能使用ASM?Embarcadero的一名员工巴里·凯利(Barry Kelly)写道。首先,他写道“几乎肯定没有内置汇编程序,但可能支持在与其他东西组合的对象文件中链接。”但现在我看到他编辑了他的文本:FWIW Allen Bauer发布了x64内联汇编程序的屏幕截图。它还没有确认,但似乎很有可能在产品中。非常感谢Andreas的链接@祭坛:“需要”是一个非常强的词,尤其是因为您总是可以执行过程Proc(var w:word)begin w:=Func(w);结束代码>。但这肯定不会比编译器的Swap
函数快吗?不会快,但不是每个Delphi都实现Swap。@gabr反转字在Win64上不再工作。知道如何修复它吗?@祭坛-我已经编辑了答案,以包括X64支持。absolute
不仅在这里存在了十多年,而且比Delphi本身还存在很多年,我记得在Turbo Pascal 6或7中使用过它!不确定版本,很难,希望我的记忆不是在开玩笑。:)@jachguate你是对的,absolute关键字早在几年前就用于快速视频内存访问,我记得我的一个朋友几年前跟我谈过这件事,但我只在Delphi中使用过它…我以前使用指针访问视频内存。。。但是,使用不同的变量访问同一地址而不进行类型转换非常方便,如您的示例所示:
procedure SwapWord_Working2 (VAR TwoBytes: word);
asm
mov dx, [TwoBytes] ;//[TwoBytes] = [eax] on x86 *[Note1]
xchg dl, dh
mov [TwoBytes], dx
end;