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

时间:2017-01-14 00:53:42

标签: assembly x86 nasm intel

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

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

没有收到“未指定尺寸”错误。

1 个答案:

答案 0 :(得分:5)

我将在评论中添加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模式下,您只能访问两种大小的内存,而且只能访问其中一些内存:1,2和4,使用通用整数运算。

用FPU 8或10。哦,是的,10不是两个的力量,我知道,它只是一些FP事物的特殊之处。

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

然后非算术特殊指令有时可以使用额外的额外大小,比如5或6可能(我甚至不确定)有一些远跳等等...一般我都不会计算它们例外,因为整个x86指令解码使用的是可变字节数量的方法,并且命名大小是1B,所以它不是关于该部分的2的幂。

无论如何,几乎没有人只在汇编中使用3个字节,这"不正确"诅咒大小并给用户带来很多不幸,你应该尽可能避免它。

有时人们将它拉伸到目前为止,即使是由RGB数据组成的视频ram也是每像素32位对齐,浪费每4字节为#34;没有&#34;只有像填充一样(25%的VRAM被浪费掉了,而且它的时间又回来了,当RAM <昂贵时)。

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

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

对于必须始终有效的通用3B负载:

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

当你知道3B值不在内存页面的末尾,后面是受限制的内存页面时(因此值在地址上由4对齐,或者在它之后总是有另一个合法的内存页面):< / p>

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

(当下一个内存页面被限制时,这会在读取内存页边界时崩溃,例如&#34; inbuf&#34;是地址4093,地址4096仅限于此进程=&gt;非法内存访问崩溃,但这通常不是你所拥有的&#34; inbuf&#34;定义的,所以这个较短的变体通常显示为正确的解决方案,没有这个愚蠢的长解释,当它实际可能崩溃)。