Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 交换字变量字节(低/高)的过程_Delphi_Assembly_Basm - Fatal编程技术网

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

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

我有一个交换单词变量字节(低/高)的过程(它的功能与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);
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;