assembly - 对齐给定的指令,但将对齐填充放在指令之前以外的其他位置

标签 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

这将是 ALIGN 32 指令处的一堆 nop 指令,这些指令将在进入循环之前执行(或者您可以跳过它们,但这仍然会执行一些操作以跳过填充。

您不想在函数本身内添加填充,而是在永远不会执行的函数之前添加填充。例如,如果在循环入口之前有 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

最佳答案

好吧,我想出了一个不太老套的方法来做到这一点。诀窍是在函数之后组装对齐填充,并依靠段排序将所有内容放在正确的顺序中。

%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

上面的宏可以这样使用:

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

此代码采用 ELF 和合理的链接器和/或链接器脚本,如果这是它们在目标文件中首次出现的顺序。它可能可以修改为与 PECOFF 一起使用,但我还没有尝试过。我只用 NASM 测试过这个,我不知道这是否适用于 YASM。

关于assembly - 对齐给定的指令,但将对齐填充放在指令之前以外的其他位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50918578/

相关文章:

python - PyQt:更改 QTableView 中复选框的对齐方式

frameworks - 在 Bulma 中改变方向到 rtl 的问题

html - 为什么一个带有 float 的div : right does not respect the margin of the hr tag below?

x86 - 进程内存中的 Unicode 字符串

performance - 现代 x86 实现是否可以从多个先前存储进行存储转发?

assembly - 在仅读取ZMM寄存器并写入k掩码的512位指令之后,Skylake是否需要vzeroupper来使turbo时钟恢复?

assembly - 将寄存器加载到自身的指令的目的是什么?

c++ - 如何做类似 "is_atomically_assignable"的事情?

assembly - 难倒在 LC-3 组装的扩展乘法上

assembly - MIPS:不使用伪代码的 la 指令的等价物?