为什么只有当我存储和加载这些寄存器时 Printf 才工作? aarch64

Why Does Printf Work Only When I Store and Load These Registers? aarch64

我正在尝试打印数组中的所有双字。但是,执行时出现错误“Segmentation fault”。在尝试了很多事情之后,我终于通过存储和加载寄存器 x8、x9 和 x10 使其工作(我测试了许多寄存器并不断消除寄存器直到程序与这三个一起工作并且我不能错过其中一个).

我不知道为什么我什至需要存储和加载这些寄存器,难道 printf 不应该这样做吗?为什么 printf 甚至会弄乱这些寄存器?我很困惑,因为参数和 return 寄存器是 x0-x7。如果 printf 使用其他寄存器,它应该存储和加载。

这是我的代码。 (这是 armv8 aarch64)

.text
    .equ ELEM, 10
    .extern printf
    .global _start
_start:
    .global selec_start
selec_start:
    ldr x0, =stack
    mov sp, x0
    sub sp, sp, #16

    ldr x8, =vec    // address of vec (first element)

    mov x9, #ELEM   // index of last element in vec
    sub x9, x9, #1

    mov x10, #0     // increment i
print:
    cmp x10, x9     // compare i with index of last element in vec
    bgt end         // branch to end if we hit end of loop

    lsl x11, x10, #3    // multiply i by 8
    add x12, x8, x11    // x12 = address of vec + i*8
    // x12 is address of index i in vec

    str x8, [sp, #-8]!
    str x9, [sp, #-8]!
    str x10, [sp, #-8]!

    ldr x0, =string
    ldr x1, [x12]
    bl printf

    ldr x10, [sp], #8
    ldr x9, [sp], #8
    ldr x8, [sp], #8

    add x10, x10, #1    // i++
    b print
end:
  mov w8, #93
  svc #0

    .data
string:
    .ascii "%d\n[=10=]"
vec:
    .quad 1,2,3,4,5,6,7,8,9,10
    .bss
    .align 8
    .space 4096
stack:
    .space 16
.end

x8、x9、x10 都是 AARCH64 上的 caller-save 寄存器,所以如果你关心它们里面的值,你需要在任何函数调用(比如到 printf)周围保存和恢复它们,因为被调用的函数可能会破坏它们。

只有 x19-x29 和 x31 (sp) 是被调用者保存的并且将(必须)被任何函数调用保留。