8

Word変数のバイト(低/高)を交換するこの手順があります(これはSystem.Swap関数と同じことを行います)。この手順は、コンパイラの最適化がオフの場合は機能しますが、オンの場合は機能しません。誰かがこれを手伝ってくれますか?

procedure SwapWord(VAR TwoBytes: word);   
asm
  Mov EBX, TwoBytes
  Mov AX, [EBX]
  XCHG AL,AH
  Mov [EBX], AX
end;
4

5 に答える 5

11

最速:

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;
于 2011-02-27T17:41:26.097 に答える
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;
于 2011-02-27T15:33:35.387 に答える
7

10 年以上前からある「ハッキング」について誰も言及しなかったことに少し驚いてい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;
于 2011-02-28T01:01:52.510 に答える
5

コンパイラのSwap機能を使用することを検討しましたか?

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;

また

procedure MySwap(var a: word);
begin
  a := lo(a) shl 8 + hi(a);
end;
于 2011-02-27T15:20:35.860 に答える
1

Sergの答えは確かに正しいですが、Sergの答えへのコメントで指摘されているように、効率的ではありません。最速は明らかに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 呼び出し規約 (@TwoBytesを介して渡される場所) を使用する計画 (Allen Bauer のどこかで言及) に固執すると仮定するとRCX、この回答で提供されるバージョンは x64 でも動作するはずです。

于 2011-06-20T06:51:03.953 に答える