Assembly 向整数寄存器的每个位置重复/广播一个字节

Assembly 向整数寄存器的每个位置重复/广播一个字节,assembly,x86,bit-manipulation,Assembly,X86,Bit Manipulation,我在汇编中遇到了一个问题,我必须获取十六进制代码的第一个字节(FF)并将其复制到整个值上: 0x045893FF input 0xFFFFFFFF output 我所做的是: movl $0x04580393FF, %eax shl $24, %eax # to get only the last byte 0xFF000000 现在我想将这个字节复制到寄存器的其余部分。例如,您可以这样做: mov %al, %ah #0x0458FFFF mov %ax,

我在汇编中遇到了一个问题,我必须获取十六进制代码的第一个字节(FF)并将其复制到整个值上:

0x045893FF      input
0xFFFFFFFF      output
我所做的是:

movl $0x04580393FF, %eax
shl $24, %eax     # to get only the last byte 0xFF000000

现在我想将这个字节复制到寄存器的其余部分。

例如,您可以这样做:

mov %al, %ah    #0x0458FFFF
mov %ax, %bx    #0xFFFF
shl $16, %eax   #0xFFFF0000
mov %bx, %ax    #0xFFFFFFFF
另一种方法是:

movzx %al, %eax
imul $0x1010101, %eax

在现代体系结构上,最后一个可能更快。

我已经习惯了NASM汇编语法,但这应该相当简单

; this is a comment btw
mov eax, 0x045893FF ; mov to, from

mov ah, al
mov bx, ax
shl eax, 16
mov ax, bx

; eax = 0xFFFFFFFF

仅使用一个寄存器(EAX)的另一个解决方案:


不过,这比上面的解决方案慢了一点。

您的系统真的有4位字节吗?您使用的是
%eax
,这让我想到x86(有8位字节),但您说
FF
是两个字节。
FF
是一个字节,而不是两个字节。你是什么意思?@Carl:没有规定一个字节必须有8位:)我没说有这样的规定,是吗?我只是很惊讶。而且
0x04580393FF
不适合
%eax
。回答得好,这正是我想要的!非常感谢您为什么没有
movsx%al,%eax
-毕竟,
0xff
被视为已签名,将直接扩展到
0xffffff
。不需要“通过乘法复制字节”技巧。同意,但这当然只适用于字节为
0xff
@FrankH的特殊情况。作为汇编程序员,您有权随意进行代码混淆。因此,我利用这一点,为一个无辜的移动操作插入了一个乘法,在这个操作中,它出乎意料,对读卡器的伤害最大。乘法方式在Intel P6系列上快得多(部分寄存器暂停),在现代x86上可能更好。当然是为了吞吐量,特别是考虑到在
mov%ax,%bx
中写入免费的部分寄存器,而不是
mov%eax,%ebx
。(合并到EAX时需要在末尾写入AX,或者使用BMI2和fast SHLD,您可以用
rorx$16、%EAX、%edx
+
SHLD$16、%ebx、%EAX
替换最后3个INSN。但这样您仍然可以
            (reg=dcba)
mov ah, al  (reg=dcaa)
ror eax, 8  (reg=adca)
mov ah, al  (reg=adaa)
ror eax, 8  (reg=aada)
mov ah, al  (reg=aaaa)