ARMv8 程序集,调用子程序时遇到总线错误

Posted

技术标签:

【中文标题】ARMv8 程序集,调用子程序时遇到总线错误【英文标题】:ARMv8 Assembly, Run into bus error when calling a subroutine 【发布时间】:2020-12-06 11:22:49 【问题描述】:

每次我尝试使用奇怪的命令行参数运行程序时,程序都会遇到总线错误。

./test 4 5
bus error (core dumped)

./test 7 13
bus error (core dumped)

但是当我使用命令行参数运行它时,它工作得很好。

./test 12 12

这是我的代码:

    .balign 4
    .global main

main:   
        
    stp x29,    x30,    [sp, -48]!  //save fp and link register to stack
    mov x29,    sp      //update fp register
    
    mov w28,    w0      //move argc to w28
    mov x27,    x1  //move argv to counter2
    
    //load argv[1]
    mov x19, 1          
    ldr x0, [x27, w19, sxtw 3]
    bl  atoi
    mov x21,    x0
    
    //load argv[2]
    mov x19, 2  
    ldr x0, [x27, w19, sxtw 3]
    bl  atoi
    mov x22,    x0
    
    //store argc, argv[1], argv[2] in memory
    str w28,    [x29, 16]
    str x21,    [x29, 20]
    str x22,    [x29, 28]
    
    //allocate memory for an array
    mul x24,    x21,    x22
    lsl x24,    x24,    #2
    sub x24,    xzr,    x24
    add sp, sp, x24
    
    //call function initializeRandom
    ldr x0, [x29, 20]
    ldr x1, [x29, 28]
    mov x2, sp
    bl initializeRandom
    
    //deallocate memory
    ldr x21,    [x29, 20]
    ldr x22,    [x29, 28]
    mul x24,    x21,    x22
    lsl x24,    x24,    #2
    add sp, sp, x24
    
mainEnd:    //End of main() function
    ldp x29,    x30,    [sp],   48  //restore fp and link registers
    ret



////////initializeRandom(int x, int y, int* table) function////////

    .balign 4
initializeRandom:
    stp x29,    x30,    [sp, -64]!
    mov x29,    sp
    
    //end of subroutine
    ldp x29,    x30,    [sp],   64
    ret     

子程序 initializeRandom 的目的是用随机数填充在主函数中创建的数组。但是当子程序基本上为空时,程序甚至都不会运行。 为什么会发生总线错误以及如何解决?

【问题讨论】:

【参考方案1】:

不同之处在于行为可能是因为,根据代码中x24 中计算的值,sp 的值在执行add sp, sp, x24 后将或不会在 16 字节边界上对齐第 33 行。 这当然等同于说sp 在使用sp 引用内存之前总是包含一个是0x10 倍数的值。

这将在第一次尝试使用sp 访问内存时引发异常,即initializeRandom()line stp x29, x30, [sp, -64]!

gdb --args ./program 7 13

Reading symbols from ./program...
(gdb) b 33
Breakpoint 1 at 0x7b4: file program.s, line 33.
(gdb) run
Starting program: /home/user/***/65167437/program 7 13

Breakpoint 1, main () at program.s:33
33          add sp, sp, x24
(gdb) p/x $sp
$1 = 0xfffffffff300
(gdb) p/x $x24
$2 = 0xfffffffffffffe94
(gdb)


gdb --args ./program 22 22

Reading symbols from ./program...
(gdb) b 33
Breakpoint 1 at 0x7b4: file program.s, line 33.
(gdb) run
Starting program: /home/user/***/65167437/program 22 22

Breakpoint 1, main () at program.s:33
33          add sp, sp, x24
(gdb) p/x $sp
$1 = 0xfffffffff300
(gdb) p/x$x24
$2 = 0xfffffffffffff870
(gdb)

请参考文章Using the Stack in AArch32 and AArch64:

Rules Specific to AArch64

For AArch64, sp must be 16-byte aligned whenever it is used to access memory. This is enforced by AArch64 hardware.

    This means that it is difficult to implement a generic push or pop operation for AArch64. There are no push or pop aliases like there are for ARM and Thumb.
    The hardware checks can be disabled by privileged code, but they're enabled in at least Linux and android.

如果您添加代码以将在x24 中计算的值向上舍入为最接近的16/0x10 倍数,您的程序应该可以使用任意参数值。

【讨论】:

@Z Han:作为新用户,如果这个或任何答案解决了您的问题,请点击复选标记考虑accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。

以上是关于ARMv8 程序集,调用子程序时遇到总线错误的主要内容,如果未能解决你的问题,请参考以下文章

总线错误:Mac OS X 上带有 GCC 的内联 x86 程序集

使用 ARMv8 程序集和 Uinput 模拟击键

使用 scanf 读取时产生总线错误的程序 - C 程序

GCC 生成的程序集 - C 函数调用时的段错误

使用ARMv8程序集和Uinput模拟击键

armv7 的引导加载程序是不是适用于 armv8?