-1

在这段代码中:

#define G(gi1, gi2, x, t0, t1, t2, t3) \
lookup_32bit(t0, t1, t2, t3, ##gi1, RGS1, shr_next, ##gi1);  \
lookup_32bit(t0, t1, t2, t3, ##gi2, RGS3, shr_next, ##gi2);  \
\
lookup_32bit(t0, t1, t2, t3, ##gi1, RGS2, dummy, none);      \
shlq $32,   RGS2;                                        \
orq     RGS1, RGS2;                                  \
lookup_32bit(t0, t1, t2, t3, ##gi2, RGS1, dummy, none);      \
shlq $32,   RGS1;                                        \
orq     RGS1, RGS3;

#define lookup_32bit(t0, t1, t2, t3, src, dst, interleave_op, il_reg) \
movzbl      src ## bl,        RID1d;     \
movzbl      src ## bh,        RID2d;     \
shrq $16,   src;                         \
movl        t0(CTX, RID1, 4), dst ## d;  \
movl        t1(CTX, RID2, 4), RID2d;     \
movzbl      src ## bl,        RID1d;     \
xorl        RID2d,            dst ## d;  \
movzbl      src ## bh,        RID2d;     \
interleave_op(il_reg);               \
xorl        t2(CTX, RID1, 4), dst ## d;  \
xorl        t3(CTX, RID2, 4), dst ## d;

“gi1”一开始就变成了RDX,但此外,关于它在“movzbl”指令中的用法,我无法翻译它。基本上我无法弄清楚 movzbl ??? ???, RID1d 我是 NASM 用户

完整代码在这里:https ://github.com/torvalds/linux/blob/master/arch/x86/crypto/twofish-avx-x86_64-asm_64.S

4

1 回答 1

1

我仍然对##in的使用感到有些困惑G。我找到了GNU cpp 手册的一部分,它在逗号后提到##,但它是用于可变参数宏的,而这不是其中之一。

但无论如何,我还是会继续进行解释,基于那些##没有做任何事情的假设。

另一方面, in 是完全正常且必要的##lookup_32bit

让我们从宏上上一层G,看看它是怎么调用的。它的一个调用看起来像这样:

G(RGI1, RGI2, x1, s0, s1, s2, s3)

它的第一个参数 ,RGI1成为gi1展开式。G宏的第一部分:

lookup_32bit(t0, t1, t2, t3, ##gi1, RGS1, shr_next, ##gi1)

扩展lookup_32bit##gi1第 5 个和第 8 个参数。我假设##gi1工作方式与 相同gi1,因此第 5 和第 8 个参数将是RGI1

lookup_32bit宏内部,第 5 和第 8 个参数被称为srcand il_reg,因此在这种情况下,这两个参数都将扩展为RGI1。中的第一条指令lookup_32bit

movzbl      src ## bl,        RID1d;

src参数 ( RGI1) 与bl(它不是宏或宏参数,因此它只代表它自己) 一起粘贴,从而得到粘贴的标记RGI1bl。指令现在看起来像这样:

movzbl      RGI1bl,        RID1d;

第一次扩展lookup_32bit完成后,预处理器会再次寻找要扩展RGI1bl的宏,宏定义如下:

#define RGI1bl %dl

另外,RID1d是这样定义的宏:

#define RID1d %ebp

所以指令最终是:

movzbl      %dl,        %ebp;

这只是从 8 位寄存器%dl到 32 位寄存器 `%ebp.

查看其他宏,您可以看到其中有很多以RGI1全部解析%rdx或部分解析开始。有了这些宏,选择 64 位寄存器的低 8 位部分可以通过粘贴bl到末尾来完成,##直接使用本机寄存器名称是不可能的(没有像“r从这个标记的前面删除 并将最后的更改xl)。

具体名称RGI1,RID1等对我来说并不熟悉。我猜它们是从 twofish 规范派生的。

令牌粘贴参考: http: //gcc.gnu.org/onlinedocs/cpp/Concatenation.html#Concatenation

于 2013-08-08T17:26:40.267 回答