是否有可能消除这些冗余的尾随零?

时间:2017-05-29 01:17:23

标签: assembly compiler-construction x86 nasm opcodes

我正在编写一些非常严格的ASM代码。

请注意由NASM生成的这组操作码:

Intent intent = new Intent(getApplicationContext(), scoreKeeper.class);
            intent.putExtra("score", score);
            startActivity(intent);

类似的:

8AA4241C020000    mov ah,[esp+0x21c]

有没有办法与处理器通信,你打算将一个15位偏移应用于32位寄存器,让它为自己找出0填充?

我一直在梳理https://c9x.me/x86/html/file_module_x86_id_176.html以寻求指导。额外的2个字节在这里或那里真的会拯救我的生命!

也接受:

重写语句以使其变小的替代方法,最终我在这个例子中的目的是:

051C020000 add eax,0x21c ; 4 extra 0's! 
8D84241C020000    lea eax,[esp+0x21c] ; Brutal! 

如果有办法对其进行手工编码以使其超小,我很乐意看到这种技术。

2 个答案:

答案 0 :(得分:0)

  

有没有办法与处理器通信,你打算将一个15位偏移应用于32位寄存器,让它为自己找出0填充?

没有。可用的指令编码记录在英特尔手册中(其在线版本可在线提供各种位置;请参阅标签wiki中的链接)。对于MOV,偏移大小与寄存器大小匹配。当您MOV进入16位寄存器时,处理器仅使用16位偏移。无法获得15位偏移量。

正如雷蒙德·陈所说,"它不像你可以只编造[你自己的自定义编码]"。

  

在某些模式下,某些指令有一个符号扩展位。

当然可以,但我不知道这对你有什么帮助。您的目标是减小指令的大小:添加额外的16位操作数大小前缀以更改偏移大小的解释并不会帮助您这样做。

通常,如果对指令编码的编码方式较短,则汇编器将为您发出该编码。 当然 NASM将使用multi-pass optimization option(默认启用)。

  

这里或那里额外的2个字节真的可以挽救我的生命!

这不是您可以有效保存的地方之一。

正如David Wohlferd已经建议的那样,如果您反复这样做,您可以通过预先清除寄存器(XOR reg, reg; 2个字节)来稍微压缩代码大小,使用此作为reg寄存器MOV的源寄存器(每个只有2个字节),然后将16位MOV写入已经清除其高16位的寄存器中。

在处理具有大量寄存器的ISA时,相对常见的做法是在特定过程的上下文中将一个用于包含0。许多ISA通过具有专用的零寄存器来进一步实现这一点。您也可以使用x86执行此操作,但考虑到ISA的寄存器约束,它通常是一种悲观。但是,如果您的尺寸优先于其他所有尺寸,那么它有时可能会有意义。 (然后,它可能不会,因为它可能会迫使你溢出到内存中,并且每个存储和加载会使代码膨胀至少 2个字节。)

实际上,我打赌你的代码中有很多其他地方你可以通过指令大小进行挥霍,并且可以实现更大幅度的降低。如果您希望审核代码并着眼于缩小代码,请考虑在Code Review上发布一个问题(假设您当前有工作代码)。

我不确定在什么情况下你会编写代码,节省2个字节会很重要。也许您正在编写一个需要在512字节以内的引导加载程序?在这种情况下,大多数人所做的是编写一个多阶段引导加载程序,其中第一阶段,即仅限制为512字节的阶段,只调用第二阶段,在那里你没有这样的限制。

答案 1 :(得分:0)

如果你有一些归零的高位24位,那么例如(对于eax归零)可以关闭2个字节:

; additional 2 bytes ruining the saving, if you don't have zero reg.
; b0 87                   mov    al,0x87

; 5 byte fetch of value
b0 87                   mov    al,0x87
8a 24 84                mov    ah,BYTE PTR [esp+eax*4] 

或者,如果您知道某些其他寄存器中有一些低值104..540(其中只有一些适合),您可以稍微降低偏移量,例如假设你知道ebx == 104

8a 64 9c 7c             mov    ah,BYTE PTR [esp+ebx*4+(0x21C-104*4)]

如果这是真正的大小挑战,你必须发布整个代码,因为可能(并且经常是)疯狂的方式以非常意外和几乎难以想象的方式保存大小。