【问题标题】:Assembly infinite loop with printf function [duplicate]带有printf函数的装配无限循环[重复]
【发布时间】:2017-01-08 08:35:56
【问题描述】:

谁能解释为什么这段代码 sn-p 进入无限循环?

我认为这与 printf 函数有关。

q1: .asciz "Hello World\n"

.global main

main:

    movq    %rsp, %rbp

    movq    $3, %rcx
    jmp     bottom

loop:
    movq    $0, %rax
    movq    $q1, %rdi
    call    printf

bottom:
    decq    %rcx
    cmpq    $0, %rcx
    jne     loop

end:
    movq    $0, %rdi
    call    exit

【问题讨论】:

  • 你在使用什么汇编程序....我不确定你在使用什么调用约定'陷入无限循环
  • 我正在编译:as hello.s -o hello.o,然后:gcc -o power power.o
  • RCX 根据en.wikipedia.org/wiki/X86_calling_conventionsideone.com/fork/LKBgUL 销毁。推送 RCX 以保留它并稍后弹出以恢复它。
  • 哦好的谢谢现在明白了
  • 不要使用可以被破坏的 RCX,而是使用函数保留的非易失性寄存器之一(根据 System V 64 位 ABI)。同样decq %rcx根据减1的结果设置Z标志。cmpq $0, %rcx是不必要的。如果针对 C 运行时进行编译(似乎是这种情况),则不需要调用 exit。将返回值放入eax 并使用ret。您还可以利用 CPU 自动更新 32 位寄存器零扩展到整个 64 位寄存器这一事实。

标签: assembly x86-64 att


【解决方案1】:

被调用函数需要保留的唯一寄存器是:rbp、rbx、r12、r13、r14、r15。所有其他的都可以被调用的函数随意更改。

因此,printf 可能正在修改 rcx 寄存器,因此它永远不会变为 0。

如果你推送 rcx 并稍后弹出它,那将阻止它被修改。

请注意,您似乎没有为 printf 推送 args。我认为 printf 需要 2 个参数。

【讨论】:

  • printf 至少需要一个参数:格式字符串。
  • movq $q1, %rdi 传递格式字符串。 x86-64 SysV 在 rdi、rsi、rdx、rcx、r8、r9、IIRC 中传递了 args。
  • 或者更好的是,使用不同的寄存器来代替 RCX,它是保留调用的寄存器之一。
猜你喜欢
  • 2016-05-06
  • 1970-01-01
  • 2017-05-15
  • 2012-03-06
  • 2016-07-29
  • 1970-01-01
  • 2017-03-15
  • 2021-12-06
  • 1970-01-01
相关资源
最近更新 更多