23. 减小代码尺寸(所有处理器)

优质
小牛编辑
127浏览
2023-12-01

像第七章描述的,指令cache是8k或16k。
如果代码的要害部位无法完全放进指令cache,那么可以考虑减小代码尺寸。

一般32位代码比16位代码大,因为32位代码的地址和数据常量是4个字节,16位代码是2个字节。
然而,16位代码有一些其它的惩罚诸如前缀的惩罚,同时访问邻近的字带来的问题(前述10.2章)。
减小代码尺寸的其它方法在下面讨论。

如果跳转地址,数据地址和数据常量在-128到127范围内,那么表示成一个带符号的字节可以节省空间。

对于跳转地址,近跳转被编码为2个字节。但是超过127字节的跳转,如果是非条件的编码为5个字节,如果是条件的编码为6个字节

同样地,数据地址如果可以被表达成一个指针和一个在-128到127范围的偏移,能节省空间。比如:

MOV EBX,DS:[100000] / ADD EBX,DS:[100004] ; 12字节

减少为:

MOV EAX,100000 / MOV EBX,[EAX]
/ ADD EBX,[EAX+4] ; 10字节

如果多次这样使用指针,好处就明显体现出来了。
倘若你的数据在指针偏移的-128~127范围内,那么用EBP或ESP在栈中存储数据,较之用静态内存地址和绝对地址可以减小代码长度。
用PUSH和POP读写临时数据甚至可以使代码更短。

如果数据常量在-128~127范围内,也能花费更少的空间。
当立即操作数是一个带符号的字节时,大多数指令有一种短的形式,比如:

PUSH 200 ; 5字节

PUSH 100 ; 2字节

ADD EBX,128 ; 6字节

SUB EBX,-128 ; 3字节

最重要的MOV指令带立即操作数,却不具备这种短形。

比如:

MOV EAX, 0 ; 5字节

或许可改为:

XOR EAX,EAX ; 2字节

还有

MOV EAX, 1 ; 5字节

或许可改为:

XOR EAX,EAX / INC EAX ; 3字节

或者:

PUSH 1 / POP EAX ; 3字节

还有

MOV EAX, -1 ; 5字节

或许可改为:

OR EAX, -1 ; 3字节

如果同一个地址常量或数据常量将使用多次,那么最好把它放进寄存器。
一个带有4字节立即操作数的MOV指令有时候可以替换成算术指令——如果在MOV之前目的寄存器的值已知的话。 比如:

MOV [mem1],200 ; 10字节

MOV [mem2],200 ; 10字节

MOV
[mem3],201 ; 10字节

MOV EAX,100 ; 5字节

MOV EBX,150 ; 5字节

假定mem1和mem3都在mem2的-128~127的范围内,这片代码可以改为:

MOV EBX, OFFSET mem2 ; 5字节

MOV EAX,200 ; 5字节

MOV [EBX+mem1-mem2],EAX ; 3字节

MOV [EBX],EAX ; 2字节

INC EAX ; 1字节

MOV [EBX+mem3-mem2],EAX ; 3字节

SUB EAX,101 ; 3字节

LEA EBX,[EAX+50] ; 3字节

但在PPlain和PMMX上,要注意到LEA指令带来的AGI延迟。

应该注意到不同的指令有不同的长度。这些指令只有一个字节,十分“诱人”:PUSH reg, POP reg, INC
reg32, DEC reg32。 操作数是8位寄存器的INC\DEC指令是2个字节,因此INC EAX比INC AL短。

XCHG EAX,reg也是一条单字节指令,比MOV
EAX。reg短,但比较慢。

有些指令使用累加器可以比使用其它寄存器节省一个字节:

比如:

MOV EAX,DS:[100000] 比MOV
EBX,DS:[100000]短

ADD EAX,1000 比ADD EBX,1000短

带指针的指令,当它们只有基址指针(不是ESP)和一个偏移时,比带有比例变址寄存器,或基址变址寻址,或ESP作为基址指针的长度短一个字节:

比如:

MOV EAX,[array][EBX] 比MOV EAX,[array][EBX*4]短

MOV EAX,[EBP+12] 比MOV EAX,[ESP+12]短

没有偏移,没有变址寄存器的指令,如果用EBP作为基址指针比用其它寄存器长一个字节:

MOV EAX,[EBX] 比MOV EAX,[EBP] 短,但是 MOV EAX,[EBX+4] 和MOV EAX,[EBP+4]一样长。

不带基址指针,只有一个比例变址指针的指令会被强加一个4字节的偏移,哪怕偏移是0,因此:

LEA EAX,[EBX+EBX] 比LEA
EAX,[2*EBX]短。