gpt4 book ai didi

linux - 如何在 x86 程序集中使用 "nanosleep"?

转载 作者:太空宇宙 更新时间:2023-11-04 10:12:02 25 4
gpt4 key购买 nike

我在使用 Linux 的 nanosleep 系统调用时遇到了一些问题。这段代码应该在退出前等待 2 秒,但它并没有:

.text
.globl _start
_start:
pushq %rbp
movq %rsp,%rbp

pushq $0 #0 nanoseconds
pushq $2 #2 seconds

leaq (%rbp),%rdi #the time structure on the stack
movq $35,%rax #nanosleep syscall
movq $0,%rsi #disable useless parameter
syscall
leave

最佳答案

push 之后把东西放在堆栈上,使用 mov %rsp, %rdi . RSP(当前堆栈指针)指向您新推送的结构,而不是 RBP(帧指针)lea (%rsp), %rdi是一种效率较低的写法,但也可以。

您正在通过 RBP作为指针,但它仍然指向制作“堆栈框架”时保存的 RBP 值。注意是_start ,不是一个函数,所以你实际上只是终止了保存的 RBP 值的链表。 System V ABI 建议通过将 RBP 显式设置为零来执行此操作,但 Linux 会在进程启动时将寄存器(RSP 除外)置零,因此这是有效的。

无论如何,在 _start , (rsp)argc , 然后你推 0 (保存的 RBP)并将 RBP 设置为指向那里。所以你传递给 sys_nanosleep 的结构是{0, argc} .或者 argc纳秒。 (使用 strace 进行测试,看看我是否做对了;我没有尝试。)


这是你应该做的:

pushq $0    #0 nanoseconds
pushq $2 #2 seconds

### RSP instead of RBP in the next instruction:
mov %rsp, %rdi #the time structure we just pushed
mov $35, %eax #SYS_nanosleep
xor %esi, %esi #rem=NULL, we don't care if we wake early
syscall
# RSP is 16 bytes lower than it was before this fragment, in case that matters for later code.

我还通过在不需要时不使用 64 位操作数大小进行了优化(因为写入 32 位寄存器会将高 32 位归零)。我喜欢让寄存器大小暗示操作数大小而不是使用 movq ,就像在 Intel 语法中一样。我还使用惯用的方式将寄存器归零,并改进了评论。


您建议的答案已损坏:subq $16, %rbp之前leave这是的主意。

如果您想相对于 RBP 栈帧寻址新插入的结构,您可以 lea -16(%rbp), %rdi .

但修改%rbp将使 leave 设置 RSP到更新的RBP然后将结构的低 qword 弹出到 RBP ,而不是调用者保存的 RBP . RSP 将指向结构的高位 qword,而不是函数返回地址。

这可能只有效,因为你只使用 sys_exitleave 之后,因为你不在一个函数中,所以你不能 ret反正。使用 leave 没有意义在 _start ,因为它不是函数。你只需要 sys_exitsys_exit_group .

但是如果您在实际函数中使用此片段,它会破坏堆栈。

关于linux - 如何在 x86 程序集中使用 "nanosleep"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48489860/

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