以前故障不对齐的电话现在可以正常工作吗?

时间:2019-02-10 20:30:07

标签: linux gcc assembly x86-64

我不确定我是否有妄想,但我确定几乎可以确定的调用如果在输入时未对齐,则会在System V Linux x86_64上失败(例如,您故意在call之前对齐堆栈,以便在进入时对齐)。

例如(现在可以使用):

.data
str: .asciz "string literal"

.text
.globl main
main:
    lea str(%rip), %rdi
    call puts@plt
    xor %eax, %eax
    ret

我几乎可以肯定这曾经失败过,有人可以解释一下我是否:妄想(即一直有效),误解堆栈对齐的语义,不知道(某事是最近的吗?)某处某处的变化? / p>

以前,我总是故意使用push(按照通用序言)或仅仅使用sub $8, %rsp来迷失方向,但是现在我写的没有这样做的代码似乎还行得通?

这是个细微差别还是这种行为现在可以接受吗?

1 个答案:

答案 0 :(得分:4)

你不是妄想。 x86-64 SysV ABI要求在调用外部函数之前将栈对齐为16,这意味着在进入函数时栈指针值mod 16为8,并且必须将其调整为8的奇数倍才能重新对齐。它在调用另一个函数之前。但是,这不是严格执行的。调用本身不会出错,用于访问堆栈的大多数类型的指令也不会出错。仅当被调用函数使用要求对齐的指令(例如某些SSE指令(包括SSE扩展名和AVX))访问堆栈上的值时,才会引起错误。

某些库函数的实现始终执行此类访问,因此它们将始终在未对齐的堆栈上出错。其他一些库函数可能会根据传递的数据来执行对堆栈的此类访问,而某些库函数则永远不会使用此类访问,并且无论堆栈对齐如何都不会出错。但是,依靠任何一种方法都是不明智的,因为实现可能会改变。拨打电话之前,请始终对齐堆栈。