2013-06-25 306 views
3

我会列出我不明白的东西,并向您展示我无法理解的部分。“.align”x86汇编程序指令是做什么的?

首先,

.align伪指令

  1. .align伪整数,垫。 .align指令导致生成的下一个数据以整数个字节对齐

1.〜? :“”隐含的原因导致生成的下一个数据以模数整数字节对齐?“我可以推测,生成的下一个数据是内存到内存的转移,不是吗? Modulo意味着一个部门的其余部分。我不明白“对齐模整数字节” .......

这将是一个简单的数据声明的剩余部分,以及如何将在未来产生的数据被一个余数排列有用吗?如果下一个数据是模对齐的,那就是说下一个生成的数据,无论如何意味着,是整数的余数?这绝对没有意义。

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

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

+2

这只是表示汇编器会将下一个字节放在一个可以被* integer *整除的地址上,所以如果这样的话。最后一个字节放在'0x0eda',那么通常下一个字节将放在'0x0edb',但有一个'.align 8'指令,下一个字节将放在'0x0ec0',下一个地址这是可以被8整除的 – microtherion

+0

请注意.align适用于汇编程序输出的任何内容,例如机器代码,而不仅仅是您在C中称为“数据” – nos

回答

5

正如在注释中提到的那样,这意味着编译器将添加足够的填充字节,以便下一个数据位于“偶数”位置(可通过对齐值整除)。这很重要,因为对齐的内存访问比未对齐的内存访问快得多。 (从0x10000加载双字要比从0x10001加载双字更好)。如果您与其他组件进行接口连接,并且需要使用给定的填充/对齐方式发送/接收数据结构,那么它可能也很有用。

0

Modulo指算术中的模运算,即c中的%符号或换句话说“余数”。

“modulo n”通常意味着n表达式的模数等于0.如果您想放置地址“模4”,这意味着(地址%4)== 0,这对于以下示例:0,4,8,0xC,0x10等

硬件限制要求某些数据类型由大整数对齐。例如,某些DMA引擎可能需要模64。

0

align指令的主要原因是加速执行。如果calljmp目标处于奇数地址,则可能需要额外的总线传输和/或前进到确切的字节。数据也是一样。在旧的80386手册中,当目标错位时,某些操作码会受到处罚。

我发现它在手册中(从http://css.csail.mit.edu/6.858/2011/readings/i386.pdf)第24页:

Such misaligned data transfers reduce performance by requiring extra memory 
cycles. For maximum performance, data structures (including stacks) should 
be designed in such a way that, whenever possible, word operands are aligned 
at even addresses and doubleword operands are aligned at addresses evenly 
divisible by four. Due to instruction prefetching and queuing within the 
CPU, there is no requirement for instructions to be aligned on word or 
doubleword boundaries. (However, a slight increase in speed results if the 
target addresses of control transfers are evenly divisible by four.) 
0

首先,请注意.align它不是一个具体的x86概念,而是一个GAS指令记录here。它也可以用于其他架构。 x86不指定指令,仅指示指令。

现在让我们玩它,了解它:a.S

.byte 1 
.align 16 
sym: .byte 2 

编译和反编译:

as -o a.o a.S 
objdump -Sd a.o 

输出:

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 

所以sym被转移到字节16,在第一个.byte 1 we'v后的第一个倍数16放置,以16字节对齐。

使用0102之间填充的字节气选择垃圾

不是让我们尝试不同的输入(TODO怎么样?):

.skip 5 
.align 4 
sym: .byte 2 

给出:

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 

所以这一次sym被移至8,这是4的第一个倍数,后面是5

相关问题