【发布时间】:2020-07-21 22:47:48
【问题描述】:
我正在尝试在 x86-64 asm 中围绕 pcmpestri 编写一个最小循环(实际上是使用 GDC 编译器嵌入到 Dlang 中的内联 asm)。有几件事我不明白
- 我使用 pcmpestri 和两个指向字符串的指针,rax 和 rdx 中的字符串长度是多少?
- 如果有,单位是什么?总是以字节为单位计数,还是以字符为单位计数,其中 1 个计数 = 2 个字节(对于 uwords)?
- pcmpestri 是否检查短字符串?即 len str1 or str2
- pcmpestri 是否将每个块的 rax 和 rax 计数减少 n 还是我必须这样做?总是减去 16 还是(16 或 8,取决于字节/uwords)?
- 我是否需要担心下面 fetch 的 128 位对齐?如果它更快,我可以预先检查字符串是否为 128 位对齐,但那样会变得非常混乱。如果我使用不需要 128 位对齐的指令,那会慢多少?见下文
- 在 ja 之前使用 lea %[offset], [ %[offset] - 16 ] 会慢吗? (选择它是因为它不设置标志)
- 值得循环展开吗?还是一个糟糕的主意?
- 我需要将哪些信息传递回高级语言代码? rcx 我知道一件事,标志也是,还是我可以忘记它们? (在较早的例程中,如果未采用 final ja,我将 true if cond 'na' 传回。)
- 最后一个问题:传回更新的偏移量怎么样?
省略我必须的序言:
; having reserved say xmm1 as a working variable
loop: add %[offset], 16 ; 16 bytes = nbytes of chunk of string
; do I need to count lengths of strings down ? by 16 per chunk or by (8 or 16) per chunk ?
movdqa xmm1, [ %[pstr1] + %[offset] - 16 ] ; -16 to compensate for pre-add
pcmpestri xmm1, [ %[pstr1] + %[offset] - 16 ], 0 ; mode=0 or 1 for uwords
ja loop
;我该怎么做才能将信息传回主代码? ;我已经传回 rcx = offset-in-chunk,我还需要传回标志吗 ;我通过将 rcx 声明为输出来保留它 ;传递 %[offset] 的值怎么样?还是通过倒计时的长度?
我还没有找到以单词而不是字节为特征的示例。
对于 1 字符串的使用模式,我保留了 xmm1 作为输入参数 xmm reg :
loop: add %[offset], 16 ; 16 bytes = nbytes of chunk of string
pcmpestri xmm1, [ %[pstr1] + %[offset] - 16 ], 0 ; mode=0 or 1 for uwords
ja loop
【问题讨论】:
-
我决定在 asm 代码中做尽可能少的工作,并让逻辑在它之外完成。已经有一个单独围绕 pcmpestri 的单行 asm 包装器,但我们需要在 asm 中包含一条 jna 指令以提高速度,因为 D 代码必须处理传递标志状态的笨重机制是很尴尬的在这样一个热循环中。所以我包含了几个场景,它们使用 jna 指令完成循环 - 一个用于两个指针用例,另一个用于 xmm reg 中的一个 ptr 和一个固定参数。
标签: string assembly optimization x86-64 inline-assembly