对齐给定指令,但将对齐填充放在指令之前的某处

时间:2018-06-18 23:06:16

标签: assembly x86 alignment nasm micro-optimization

是否有可能在nasm(并且通过扩展,yasm)编写宏或以其他方式使用预处理器功能将某个特定指令与给定的2的幂对齐(或者可能是2的给定幂加上一些偏移) ,但是在指令之前不是立即插入对齐填充,而是在某些任意较早的地方插入?

例如,假设您有一个函数,您希望将函数内部的循环顶部对齐32,您可以这样做:

function:
  xor eax, eax
  mov ecx, 1
ALIGN 32
.top:
  add eax, ecx
  inc ecx
  cmp ecx, rdi
  jne .top

这将是nop指令点上的一堆ALIGN 32指令,它们将在进入循环之前执行(或者你可以跳过它们,但这仍然按顺序执行跳过填充物。

你不想在函数本身内部添加填充,而是在函数之前永远不会执行填充。例如,如果循环条目之前有10个字节,那么将函数的顶部对齐到32N - 10就可以了。像这样:

padding_magic .top 32
function:
  xor eax, eax
  mov ecx, 1
ALIGN 32
.top:
  add eax, ecx
  inc ecx
  cmp ecx, rdi
  jne .top

有没有办法在nasm中完成它,即实现padding_magic

1 个答案:

答案 0 :(得分:3)

好吧,我设法弄清楚了这样做的方法。诀窍是在函数之后组装对齐填充,并依靠分段顺序将所有内容放置在正确的顺序中。

^([0-9]{1,2})(\.[0-9]{0,8})?$

上面的宏将像这样使用:

%macro BEGIN_PADDED_FUNC 0-1 16
%define _func_name %00
%define _align %1
%define _section_base .text.%[_func_name].

        [SECTION %[_section_base]1 progbits alloc exec nowrite align=_align]
        [SECTION %[_section_base]2 progbits alloc exec nowrite align=1]

_func_name:
%endmacro

%macro ALIGN_PADDED_FUNC 0
%[_func_name].align_point:
%endmacro

%macro END_PADDED_FUNC 0
        [SECTION %[_section_base]1]
        TIMES ((_align - (%[_func_name].align_point - _func_name) % _align) \
               % _align) nop
        __SECT__
%endmacro

此代码假定使用ELF和合理的链接器和/或链接器脚本,如果这是它们首先出现在目标文件中的顺序,则会在function BEGIN_PADDED_FUNC 32 xor eax, eax mov ecx, 1 ALIGN_PADDED_FUNC .top: add eax, ecx inc ecx cmp ecx, edi jne .top END_PADDED_FUNC 之前放置名为.text.function.1的部分。可以将其修改为与PECOFF一起使用,但是我还没有尝试过。我只在NASM上进行过测试,不知道它是否可以在YASM中使用。