【问题标题】:What's the best way to shift characters in a string using assembly?使用汇编移动字符串中字符的最佳方法是什么?
【发布时间】:2016-12-24 06:17:42
【问题描述】:

我在问使用 Irvine 库在 x86 程序集中将字符串中的字符向右或向左移动的最佳方法是什么。 有一个例子: ABCD --> DABC 等等

我已经编写了这段代码,但它给出了错误的结果。

r1:
push ecx
mov ecx,lengthof arr
mov al,[esi+lengthof arr]
mov bl,[esi]
mov [esi],al
mov [esi+1],bl
inc esi
innr1:
mov al,[esi]
mov bl,[esi+1]
mov [esi],al
inc esi
loop innr1
pop ecx
loop r1

【问题讨论】:

  • 循环 innr1: 什么都不做,只是加载 al 并将其存储在它的来源处,而 bl 被忽略。
  • 另外(除非 lengthof arr 是最后一个 index 而不是 length),您在第一次加载时都分别,并在循环计数器中。
  • 如果innr1 会执行类似str[esi+1] = str[esi] 的操作,它会覆盖整个字符串,或者至少覆盖第二个字符,因为mov [esi+1],bl 会覆盖尚未读取的字符=> 永远丢失.顺便说一句,您使用什么调试器?如果第一个 mov al,[esi+...] 加载最后一个字符,你真的写了这么多代码吗?必须很难在汇编中这样编码,尊重,看起来有点像受虐狂。但是您也没有显示arr 的定义。 IMO 误解了 Assembly 编程的工作原理。数据第一,代码第二。

标签: assembly irvine32


【解决方案1】:

在像您的示例这样的 4 字节字符串的特殊情况下,使用 rol dword ptr [arr], 8 进行您描述的旋转。

(请记住,x86 是 little-endian,因此多字节操作数内的左移会将字节移动到更高的地址)。

在非特殊情况下,只需使用正常的复制循环实现memmove() 来移动字节,并复制必须环绕的字节。 (您可能希望在进入复制循环之前加载回绕的字节,以便覆盖它的存储位置。)


最好的方法(为了性能)可能是使用 SSE movupsrep movsb 具有较高的启动开销,并且在未对齐的数据上速度较慢。并且可能不适用于重叠的目的地,但我不记得提到过。

如果这不是您所说的“最佳”,请更具体并说“最容易理解”之类的。

【讨论】:

  • MOVS设计通过添加 DF 来处理重叠数据,因此在 OP ABCD -> DABC 的情况下,他必须将 esi/edi 设置为 end缓冲区和STD 使MOVS 倒退。 80386 次高度优化的memmove(medium/large_size) 包括将几个字节移动到4B 对齐的序言,然后MOVSD 完成工作,以及完成剩余的%4 个字节的尾声。另外,它当然有两个分支,具体取决于重叠的方向。
  • @Ped7g:感谢您描述如何使用movsb / movsd 实现正确性。不过,当 dest 在源的 16B 范围内时,我不想打赌它是高性能的。当它们距离较远时,优化的微码实现一次复制 16B 个。除非您旋转 16,否则 src 或 dst 必须不对齐,这是rep movsb 不喜欢的(英特尔实施的吞吐量较低以及启动开销较高。)
  • @Ped7g:为了使用 SSE 实现正确性和高性能,我想你可以确保你朝着让重叠按照你想要的方式前进的方向前进。我还没有考虑清楚,但是您可能需要在复制循环期间将“环绕”的部分保存在 regs 或 tmp 缓冲区中。或者您可以将复制循环的加载/存储流水线化,这样您就可以一次至少有几个数据寄存器在运行。这使您可以从尚未被(对齐)存储触及的缓冲区部分执行 16B 未对齐加载。在环绕点退出循环,并存储飞行中的向量。
  • @Ped7g:顺便说一句,我不认为rep movsd 与附近的 src/dst 高效工作的主要原因之一是英特尔的实现 uses a cache protocol that avoids RFO for the stores,因此它针对写入每个字节进行了优化在缓存行中而不先读取它。 (这是从原始 P6 开始,而不仅仅是 IvyBridge 弱排序存储 ERMSB 增强)。
猜你喜欢
  • 1970-01-01
  • 2011-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-04
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多