首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在将此汇编代码移植到x64时会出现访问冲突?

为什么在将此汇编代码移植到x64时会出现访问冲突?
EN

Stack Overflow用户
提问于 2013-06-10 20:25:25
回答 1查看 639关注 0票数 3

我正在使用这个组件http://sourceforge.net/projects/tponguard/,现在我需要在64位编译。我被困在这里了。

它是这样的:

代码语言:javascript
复制
  push esi
  push edi

  mov  esi, eax         //esi = Mem1
  mov  edi, edx         //edi = Mem2

  push ecx              //save byte count
  shr  ecx, 2           //convert to dwords
  jz   @Continue

  cld
@Loop1:                 //xor dwords at a time
  mov  eax, [edi]
  xor  [esi], eax
  add  esi, 4
  add  edi, 4
  dec  ecx
  jnz  @Loop1

@Continue:              //handle remaining bytes (3 or less)
  pop  ecx
  and  ecx, 3
  jz   @Done

@Loop2:                 //xor remaining bytes
  mov  al, [edi]
  xor  [esi], al
  inc  esi
  inc  edi
  dec  ecx
  jnz  @Loop2

@Done:
  pop  edi
  pop  esi

然后我改成了这个:

代码语言:javascript
复制
  push rsi
  push rdi

  mov  rsi, rax         //esi = Mem1
  mov  rdi, rdx         //edi = Mem2

  push rcx              //save byte count
  shr  rcx, 2           //convert to dwords
  jz   @Continue

  cld
@Loop1:                 //xor dwords at a time
  mov  rax, [rdi]
  xor  [rsi], rax
  add  rsi, 4
  add  rdi, 4
  dec  rcx
  jnz  @Loop1

@Continue:              //handle remaining bytes (3 or less)
  pop  rcx
  and  rcx, 3
  jz   @Done

@Loop2:                 //xor remaining bytes
  mov  al, [rdi]
  xor  [rsi], al
  inc  rsi
  inc  rdi
  dec  rcx
  jnz  @Loop2

@Done:
  pop  rdi
  pop  rsi

但是现在我在xor rsi,rax中遇到访问冲突。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-10 21:14:00

您正在查看的函数是

代码语言:javascript
复制
procedure XorMem(var Mem1; const Mem2; Count : Cardinal); register;

ogutil单位。

就我个人而言,我不会费心将其转换为x64汇编程序。为了做到这一点,您需要正确地处理一些棘手的细节。对我来说,移植到Pascal并让编译器处理细节更有意义。最简单、最幼稚的翻译如下所示:

代码语言:javascript
复制
procedure XorMem(var Mem1; const Mem2; Count: Cardinal);
var
  p1, p2: PByte;
begin
  p1 := PByte(@Mem1);
  p2 := PByte(@Mem2);
  while Count>0 do
  begin
    p1^ := p1^ xor p2^;
    inc(p1);
    inc(p2);
    dec(Count);
  end;
end;

如果这是性能关键型的,那么您可能希望稍微展开循环以对大操作数进行操作。比如x86上的32位操作数和x64上的64位操作数。

对32位操作数进行操作的版本可能如下所示:

代码语言:javascript
复制
procedure XorMem(var Mem1; const Mem2; Count: Cardinal);
var
  p1, p2: PByte;
begin
  p1 := PByte(@Mem1);
  p2 := PByte(@Mem2);
  while Count>3 do
  begin
    PCardinal(p1)^ := PCardinal(p1)^ xor PCardinal(p2)^;
    inc(p1, 4);
    inc(p2, 4);
    dec(Count, 4);
  end;
  while Count>0 do
  begin
    p1^ := p1^ xor p2^;
    inc(p1);
    inc(p2);
    dec(Count);
  end;
end;

实际上,您可以很容易地编写一个由编译目标确定的自动使用32或64位操作数的版本。诀窍是使用NativeUInt类型,它是机器字大小。

代码语言:javascript
复制
procedure XorMem(var Mem1; const Mem2; Count: Cardinal);
var
  p1, p2: PByte;
begin
  p1 := PByte(@Mem1);
  p2 := PByte(@Mem2);
  while Count>SizeOf(NativeUInt)-1 do
  begin
    PNativeUInt(p1)^ := PNativeUInt(p1)^ xor PNativeUInt(p2)^;
    inc(p1, SizeOf(NativeUInt));
    inc(p2, SizeOf(NativeUInt));
    dec(Count, SizeOf(NativeUInt));
  end;
  while Count>0 do
  begin
    p1^ := p1^ xor p2^;
    inc(p1);
    inc(p2);
    dec(Count);
  end;
end;

这个最终版本在启用优化的情况下编译时效率非常高。我不会把目光投向最终的Pascal版本。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17023838

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档