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 程序集,调用子程序时遇到总线错误的主要内容,如果未能解决你的问题,请参考以下文章