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

WeG*_*ars 7 delphi assembly basm

我有这个过程交换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)

gab*_*abr 10

最快的:

function ReverseWord(w: word): word;
asm
   {$IFDEF CPUX64}
   mov rax, rcx
   {$ENDIF}
   xchg   al, ah
end;
Run Code Online (Sandbox Code Playgroud)

如果你想要反转DWORD:

function ReverseDWord(dw: cardinal): cardinal;
asm
  {$IFDEF CPUX64}
  mov rax, rcx
  {$ENDIF}
  bswap eax
end;
Run Code Online (Sandbox Code Playgroud)


klu*_*udg 8

如果不保存/恢复,则不能在ASM代码中使用EBX寄存器.您的代码的更正版本是

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

  • 或者,您可以使用ECX或EDX,您不需要保留它们. (5认同)

Com*_*sNo 7

我有点惊讶没有人提到这个absolute"黑客"已经存在了十多年但却没有得到太多的关注......反正这里是我的两分钱

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

  • `绝对`在这里不仅仅是十多年,但对于Delphi本身而言,我记得在Turbo Pascal 6或7中使用它!不确定版本,强硬,并希望我的记忆不会与此开玩笑.:) (2认同)

And*_*and 5

您是否考虑过使用编译器的Swap功能?

procedure TForm1.FormCreate(Sender: TObject);
var
  a: word;
begin
  a := $1234;
  a := Swap(a);
  Caption := IntToHex(a, 4)
end;
Run Code Online (Sandbox Code Playgroud)

如果没有,您不需要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;
Run Code Online (Sandbox Code Playgroud)

当然,这个主题有"一百万"的变化.

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

而且,非常简短,

procedure MySwap(var a: word);
begin
  a := word(a shl 8) + byte(a shr 8);
end;
Run Code Online (Sandbox Code Playgroud)

要么

procedure MySwap(var a: word);
begin
  a := lo(a) shl 8 + hi(a);
end;
Run Code Online (Sandbox Code Playgroud)

  • FWIW Allen Bauer发布了x64内联汇编程序的截图.它还没有确认,但似乎很有可能在产品中. (2认同)