如何在汇编的 XOR 语句中指定 3 字节存储的大小?

How do you specify the size of a 3 Byte storage in XOR statement in Assembly?

在我的 Linux IA-32 处理器汇编程序中,我有两个存储空间。

inbuf: resb 3
outbuf: resb 4

inbuf 真的只需要 3 个字节,我不想浪费任何内存。现在,假设我想用这样的零覆盖它们:

xor [inbuf], inbuf
xor [outbuf], outbuf

nasm说我需要指定运算大小,可以理解。现在 outbuf 这没问题,因为我可以写

xor dword [outbuf], outbuf

相反,但显然,对于 3 字节的任意大小没有大小关键字。如何指定 inbuf 的大小?

我并不是真的在寻找用零覆盖存储的解决方案,我想还有其他方法也能正常工作,但这也可以解决我的问题,如何使用

mov eax, inbuf

没有收到 "size not specified" 错误。

Jester 的正确答案我会在评论中加上。

如果您坚持 "xor-ing" 内存(对于归零没有意义,但对于其他值可能值得),那么 "xor 3B [inbuf],3B [inbuf]" 可以在 x86 汇编中完成,如下所示:

mov  eax,[inbuf]   ; loads value from inbuf + 1B undef
xor  [inbuf],ax    ; word
shr  eax,16        ; al = b16..b23 of value @inbuf
xor  [inbuf+2],al  ; byte

4B 双字变体:

mov  eax,[outbuf]
xor  [outbuf],eax

所有这些对于归零来说都是可怕的,对于归零来说这更好:

mov word [inbuf],0
mov byte [inbuf+2],0
mov dword [outbuf],0

或者最终,如果您在某些 32b 寄存器中已经为零:

xor eax,eax
mov [inbuf],ax
mov [inbuf+2],al
mov [outbuf],eax

在 32b 模式下,您只能访问 power-of-two 大小的内存,并且只能访问其中的一些内存:使用通用整数运算的 1、2 和 4。

FPU 为 8 或 10。哦,是的,10 不是 2 的幂,我知道,它只是一些 FP 东西的特殊值。

然后是各种SIMD指令,甚至可以访问128/256/512位(16,32和64字节)。

然后非算术特殊指令有时可以使用额外的额外大小,比如 5 或 6 可能(我什至不确定)和一些远跳等等......通常我不会把它们算作例外,因为整个 x86 指令解码都使用 variable-byte-amount 方法并且命名大小为 1B,所以这部分与 2 的幂无关。

无论如何,几乎没有人只在 Assembly 中使用 3 个字节,那是 "incorrect" 十六进制大小,会给用户带来很多不幸,你应该尽可能避免它。

有时人们会把它拉长,甚至由 RGB 数据组成的视频 ram 也是 32-bit-per-pixel 对齐的,每 4 个字节浪费一次 "nothing" 就像填充一样(浪费了 25% 的 VRAM 和回到过去,那时 RAM 昂贵)。

(早期的 SVGA VESA 模式也有 memory-efficient 24 位模式,但由于每个像素的寻址是 *3,在代码中使用非常烦人,甚至是硬件加速器......现在它有助于大部分视频内存用于纹理,其中第 4 个字节可以存储 alpha 或像素着色器的其他附加信息,因此不再浪费内存,但大小为 32 位)


以及如何从内存中加载 3B 值:

对于必须一直工作的通用 3B 负载:

movzx eax,byte [inbuf+2]
shl   eax,16
mov   ax,[inbuf]

并且当您知道 3B 值不在内存页末尾后跟受限内存页时(因此该值要么在按 4 对齐的地址上,要么在它之后总是有另一个合法内存页):

mov  eax,[inbuf]      ; loads desired 3B + 1B garbage
and  eax,0x00FFFFFF   ; truncate it to 3B only

(当下一个内存页面被限制时,这会在读取内存页面边界时崩溃,就像如果 "inbuf" 是地址 4093,地址 4096 被限制到这个进程 => 非法内存访问崩溃,但是这通常不是你定义 "inbuf" 的地方,所以这个较短的变体通常显示为正确的解决方案,没有这个愚蠢的长解释,当它实际上 可能 崩溃时)。 =16=]