Assembly 向整数寄存器的每个位置重复/广播一个字节
我在汇编中遇到了一个问题,我必须获取十六进制代码的第一个字节(FF)并将其复制到整个值上: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,
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)