2016-05-09 99 views
0

我知道内存寻址可以用字大小的倍数进行,以便为英特尔32位,在装配上堆栈中分配内存可以与内存adressing英特尔IA 32

//pseudo code 
    sub , esp ,4 // so for allocating for a integer on stack 
    sub esp, 8 // for a buffer of size 5 for example b[5] 

所以做寻址完成与4的倍数。因此,也指对堆栈的当地人和参数与

 // referring to variable --ebp-4 

但有时在拆卸我看到这样

 movb $0x41, 0xffffffff(%ebp) ,// refer to ebp-1 for example 

一些指令,以便它是指在1个字节的内存中完成。

所以它指的是一个字节,而不是4个字节的倍数。4个字节的倍数仅适用于esp?或者它与每个寄存器有关?

+1

_“我看到一些指令,比如'ins 0xffffffff,ebp'”_。你能举一个实际反汇编的具体例子吗? – Michael

+0

@ Michael,.edited – barp

+0

单个字节不一定与4对齐,它不会是当它是数组的元素或结构的成员时。这将是浪费,处理器不需要它。 –

回答

2

4个字节的倍数仅适用于esp?或者它与每个寄存器有关?

注意

sub esp, N

不访问任何内存位置,使用关系到内存对齐但指令本身是一个简单的寄存器立即减法,它可以使用任何值。

出于性能原因,如果你读16位它们应该在的2的地址的多个,32位应该是对的4
这一个地址的多个被称为自然边界对齐

32位系统只能push/pop 16或32位值,如果我们只在指令使用4的倍数等sub esp, N,在它们的自然边界对齐的push/pop访问数据(请注意,图4是2的倍数) 。

堆栈上的数据也可以直接与指令访问像

mov [ebp-04h], eax

这里的原则是一样的,EBP是4的倍数(请注意,它的价值是老ESP值,在减法之前),所以32位数据存储在4的地址倍数(自然对齐)中。

字节的自然对齐方式是...... 1.这意味着它们应该位于1的地址倍数,即无处不在。
这就是为什么mov [ebp-01h], 'A'执行mov [ebp-04h], 'A'


琐事

作为大拇指 IA32E 通用的规则指令可以在每个地址读取字节四字/写。
整个对齐故事主要是出于性能原因,与RISC机器不同,它们不能从结构上访问未对齐的数据。

当最初引入SSE指令带着相同指令的快“对齐”(如movaps)和慢“未对齐”(如movups)版本。

现在,64位系统明确需要128位对齐堆栈以更好地执行向量指令(和加宽寄存器)。

该CPU已在EFLAGS寄存器位,该位AC,可以让一个程序启用或禁用了严格的比对政策(点菜RISC),认为该操作系统已经启用此功能(设定AM in CR0)。

更严格地将数据对准CPU数据总线(无论现代集成DRAM控制器上的定义如何)是毫无意义的。
这就是为什么即使CPU可以有512位寄存器,新的ABI在128位上对齐的原因。每个指令

对齐要求可以在Manual 2 (the complete set)找到。

+0

一个小增加:在EFLAGS.AC位[这里]有一个SO回答(http://stackoverflow.com/a/548411/1305969)。根据“AMD64架构程序员手册卷2:系统编程”[摘自bytes.com]的另一摘录(https://bytes.com/topic/c/answers/744294-structure-size-directives/2 ),EFLAGS.AC标志仅在用户模式(CPL = 3)下有效:_当启用自动对齐检查并且CPL = 3时,对未对齐操作数的内存引用会导致对齐检查异常(#AC)._ – zx485

0

对于80x86(所有模式);寻址总是以字节粒度完成的。

对于所有常规指令(不包括SSE等扩展),CPU不需要对齐,任何对齐仅仅出于性能原因。