".align"x86汇编程序指令到底做了什么?

Sin*_*ock 5 x86 assembly gnu-assembler

我将准确列出我不理解的内容,并向您展示我无法理解的部分.

首先,

.Align指令

  1. .align整数,pad..align指令使生成的下一个数据以模整数字节对齐

1.~?:隐含的" 导致生成的下一个数据以模整数字节对齐?" 我猜想下一个生成的数据是内存到寄存器的传输,不是吗?Modulo意味着分裂的其余部分.我不明白" 要对齐模数整数字节 ".......

什么是简单数据声明的剩余部分,以及由余数对齐生成的下一个数据如何有用?如果下一个数据以模数对齐,那就说下一个生成的数据,无论这意味着什么,是整数的余数?这绝对没有意义.

具体而言,.align 8在x86中为从C编译的数据字节发出的.align 指令是什么char,即char CHARACTER = 0;用于?或者直接用该指令编码,而不是编译C后的初步汇编代码?我已经在调试大会和发现任何C/C++数据声明,如chars,ints,floats,等会插入指令,.align 8他们每个人,并添加其他指令一样.bss,.zero,.globl,.text,.Letext0,.Ltext0.

所有这些指令是什么,或者至少是我的主要要求?我已经学习了很多主要的x86汇编指令,但从未被引入或指向所有这些奇怪的指令.它们如何影响操作码,并且都是必要的?

Cir*_*四事件 7

首先,请注意.align它不是特定于 x86 的概念,而是此处记录的 GNU GAS 指令。它也可以用于其他架构。x86 不指定指令,只指定指令。

现在让我们玩弄它来理解它:

作为

.byte 1
.align 16
sym: .byte 2
Run Code Online (Sandbox Code Playgroud)

编译和反编译:

as -o a.o a.S
objdump -Sd a.o
Run Code Online (Sandbox Code Playgroud)

输出:

0000000000000000 <a-0x10>:
   0:   01 0f                   add    %ecx,(%rdi)
   2:   1f                      (bad)  
   3:   44 00 00                add    %r8b,(%rax)
   6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
   d:   00 00 00 

0000000000000010 <sym>:
  10:   02                      .byte 0x2
Run Code Online (Sandbox Code Playgroud)

所以sym被移到第.byte 116 个字节,即我们放置的第一个之后的第一个 16 的倍数,以使其与 16 个字节对齐。

用于填充的字节0102由 GAS 选择的垃圾(TODO 如何?)

不要让我们尝试不同的输入:

.skip 5
.align 4
sym: .byte 2
Run Code Online (Sandbox Code Playgroud)

给出:

0000000000000000 <sym-0x8>:
   0:   00 00                   add    %al,(%rax)
   2:   00 00                   add    %al,(%rax)
   4:   00 0f                   add    %cl,(%rdi)
   6:   1f                      (bad)  
    ...

0000000000000008 <sym>:
   8:   02                      .byte 0x2
Run Code Online (Sandbox Code Playgroud)

所以这一次sym被转移到8,这是第一多个4自带之后5

  • 我认为在某些 ISA 中,“.align”是“.p2align”(2 的幂)的同义词,而不是“.balign”(字节)。在 x86 上,它是“.balign”,就像大多数其他汇编器(如 MASM 和 NASM)中的“align”指令一样。 (2认同)

faf*_*aff 6

正如评论中所提到的,这意味着编译器将添加足够的填充字节,以便下一个数据落在"偶数"位置(可被对齐值整除).这很重要,因为对齐的内存访问比未对齐的内存访问快得多.(从0x10000加载双字比从0x10001加载双字更好).如果您与其他组件连接并且需要使用给定的填充/对齐发送/接收数据结构,它也可能很有用.

  • *从 0x10000 加载双字比从 0x10001 加载双字更好* 更好的例子是缓存行或页面分割,例如“0xffff”比“0x10000”差得多,因为这在所有 CPU 上都是如此。在大多数现代 x86 CPU 上,假设正常(可缓存)内存,高速缓存行内(或高速缓存行的 16 字节块内)的未对齐实际上几乎为零额外成本。 (2认同)