gpt4 book ai didi

assembly - 为什么 linux nasm 即使没有 16 字节堆栈对齐也能工作

转载 作者:行者123 更新时间:2023-12-01 21:23:43 24 4
gpt4 key购买 nike

我尝试遵循 https://cs.lmu.edu/~ray/notes/nasmtutorial/ 提供的一个非常简单的示例.我故意在下面注释行以确保堆栈未按照 x64 调用约定的要求与 16 字节边界对齐。但程序仍然继续工作。请有人回答为什么调用约定不被尊重,我期待某种段错误。

;       sub     rsp, 8                  ; must align stack before call

为了运行这个程序:(Ubuntu 20.04 lts,gcc 9.3.0)

nasm -felf64 echo.asm && gcc echo.o && ./a.out 123ABC
; -----------------------------------------------------------------------------
; A 64-bit program that displays its command line arguments, one per line.
;
; On entry, rdi will contain argc and rsi will contain argv.
; -----------------------------------------------------------------------------

global main
extern puts
section .text
main:
push rdi ; save registers that puts uses
push rsi
; sub rsp, 8 ; must align stack before call

mov rdi, [rsi] ; the argument string to display
call puts WRT ..plt ; print it

; add rsp, 8 ; restore %rsp to pre-aligned value
pop rsi ; restore registers puts used
pop rdi

add rsi, 8 ; point to next argument
dec rdi ; count down
jnz main ; if not done counting keep going

ret

最佳答案

运气好

要求堆栈对齐的主要原因之一是函数可以安全地使用 SSE 对齐的数据指令,例如 movaps ,如果与未对齐的数据一起使用会出错。但是,如果 puts 碰巧没有使用任何此类指令,或者执行任何其他真正需要堆栈对齐的操作,则不会发生错误(尽管可能仍然会降低性能)。

编译器有权假设堆栈是对齐的,并且它可以使用这些指令,如果它觉得这样的话。所以在任何时候,如果你的 libc 被升级或重新编译,新版本的 puts 可能会使用这样的指令,你的代码会莫名其妙地开始失败。

显然你不想这样,所以按照你应该的方式对齐该死的堆栈。

在 C 或汇编编程中,违反此类规则的情况相对较少,保证会发生段错误或以任何其他可预测的方式失败;相反,人们会说“行为未定义”之类的话,这意味着它可能以您能想象到的任何方式失败,但也可能不会。因此,您真的不能从非法代码碰巧似乎有效的实验中得出任何结论。反复试验并不是学习汇编编程的好方法。

关于assembly - 为什么 linux nasm 即使没有 16 字节堆栈对齐也能工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63440410/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com