x86机器码,14个字节
(相同的机器码可在16位,32位和64位上工作。在16位模式下,它在32和64位模式下使用AX和DI而不是EAX和EDI。)
算法:使用来检查低5位x & 31 == 4,然后右移5位,如果移位结果为非零,则重复该操作。
可char isrude(unsigned n);根据x86-64 System V调用约定从C 调用。0是真实的,非0是虚假的(这是asm,而不是C 1)。
line addr code bytes
num
1 ; input: number in EDI
2 ; output: integer result in AL: 0 -> rude, non-zero non-rude
3 ; clobbers: RDI
4 isrude:
5 .check_low_bitgroup:
6 00000000 89F8 mov eax, edi
7 00000002 241F and al, 31 ; isolate low 5 bits
8 00000004 2C04 sub al, 4 ; like cmp but leaves AL 0 or non-zero
9 00000006 7405 jz .rude ; if (al & 31 == 4) return 0;
10
11 00000008 C1EF05 shr edi, 5
12 0000000B 75F3 jnz .check_low_bitgroup
13 ;; fall through to here is only possible if AL is non-zero
14 .rude:
15 0000000D C3 ret
16 0E size: db $ - isrude
这利用op al, imm8了AND和SUB 的简短格式编码。我本来可以XOR al,4在等式上产生0,但是SUB更快,因为它可以与JZ宏融合到Sandybridge-family上的单个子分支uop中。
有趣的事实:对于P6系列车来说,将换档的标志结果使用大于1的速度会很慢(前端档位直到换档退休),但这很好。
脚注1:这是一种汇编语言函数,而x86 asm具有jz和jnz,因此根据元数据,我可以选择其中一种方式。我不希望这与C真/假匹配。
可以使用AL而不是EFLAGS方便地返回AL,因此我们可以在不使用包装器的情况下将函数描述为C编译器,但是我对true / falsy的选择不受使用C调用程序进行测试的限制。
assume we continue with a third hand,当谈到粗鲁时,团队合作使梦想成真。