Word変数のバイト(低/高)を交換するこの手順があります(これはSystem.Swap関数と同じことを行います)。この手順は、コンパイラの最適化がオフの場合は機能しますが、オンの場合は機能しません。誰かがこれを手伝ってくれますか?
procedure SwapWord(VAR TwoBytes: word);
asm
Mov EBX, TwoBytes
Mov AX, [EBX]
XCHG AL,AH
Mov [EBX], AX
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;
保存/復元せずに 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;
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;
コンパイラの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;
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 でも動作するはずです。