您确实需要获取 arm 文档并学习指令集。
你应该反汇编你的程序来确认。第一个问题是您是否在 x86 上交叉编译它,然后尝试在 x86 上运行 ARM?我想你会得到一个不同的错误。接下来是 a.out 文件格式问题,这可能是原始的,因此尝试在 aarch64 模式下运行 aarch32 并且会是错误的指令或......
对于 64 位 arm (armv8...) 上的 armv7-a 兼容模式,如果被告知或为此构建,gcc 编译器将默认为 thumb/thumb2 模式。
int mult(int);
int fun ( void )
{
return(mult(5)+1);
}
00000000 <fun>:
0: e96d 3e02 strd r3, lr, [sp, #-8]!
4: f04f 0005 mov.w r0, #5
8: f7ff fffe bl 0 <mult>
c: f100 0001 add.w r0, r0, #1
10: bd08 pop {r3, pc}
12: bf00 nop
然后写成
.global mult
mult:
mov r1,r0
lsl r0,r0,#4
add r0,r1,r0
bx lr
除非在命令行上另有指定(不是),否则将默认为 arm
00000000 <mult>:
0: e1a01000 mov r1, r0
4: e1a00200 lsl r0, r0, #4
8: e0810000 add r0, r1, r0
c: e12fff1e bx lr
因为 mult 在 gnu 链接器眼中没有被标记为函数标签,所以当你链接它时
00002000 <fun>:
2000: e96d 3e02 strd r3, lr, [sp, #-8]!
2004: f04f 0005 mov.w r0, #5
2008: f000 f804 bl 2014 <mult>
200c: f100 0001 add.w r0, r0, #1
2010: bd08 pop {r3, pc}
2012: bf00 nop
00002014 <mult>:
2014: e1a01000 mov r1, r0
2018: e1a00200 lsl r0, r0, #4
201c: e0810000 add r0, r1, r0
2020: e12fff1e bx lr
繁荣,有你的错。bl to mult without a trampoline 意味着它处于拇指模式,现在它正试图将这些字节作为拇指指令而不是 arm 来执行。它可能会存活一段时间,但最终会出现故障。
(弗兰特已经为您确认了这一点,假设这是您解决此特定故障的路径)
所以你有几个选择,可以阅读弗兰特的回答:
.global mult
.type mult, %function
mult:
mov r1,r0
lsl r0,r0,#4
add r0,r1,r0
bx lr
告诉工具mult是一个函数标签,重新组装重新链接:
00002000 <fun>:
2000: e96d 3e02 strd r3, lr, [sp, #-8]!
2004: f04f 0005 mov.w r0, #5
2008: f000 e804 blx 2014 <mult>
200c: f100 0001 add.w r0, r0, #1
2010: bd08 pop {r3, pc}
2012: bf00 nop
00002014 <mult>:
2014: e1a01000 mov r1, r0
2018: e1a00200 lsl r0, r0, #4
201c: e0810000 add r0, r1, r0
2020: e12fff1e bx lr
因为它是一个 armv7,所以我们得到了 blx thumb2 扩展,如果我在整个项目中指定 armv4t,那么我们就会得到我所期待的蹦床。两者都很好,取决于指令集,armv4t 将在 64 位处理器的 aarch32 兼容模式端工作。
00002000 <fun>:
2000: b510 push {r4, lr}
2002: 2005 movs r0, #5
2004: f000 f80c bl 2020 <__mult_from_thumb>
2008: 3001 adds r0, #1
200a: bc10 pop {r4}
200c: bc02 pop {r1}
200e: 4708 bx r1
00002010 <mult>:
2010: e1a01000 mov r1, r0
2014: e1a00200 lsl r0, r0, #4
2018: e0810000 add r0, r1, r0
201c: e12fff1e bx lr
00002020 <__mult_from_thumb>:
2020: 4778 bx pc
2022: e7fd b.n 2020 <__mult_from_thumb>
2024: eafffff9 b 2010 <mult>
链接器添加 mult_from_thumb trampoline 以在拇指模式和手臂模式之间进行转换。bx lr 可以处理模式切换,因此您在出去的时候不需要蹦床,只在进来的时候。
您的另一个选择是构建 mult as thumb
.thumb
.global mult
mult:
mov r1,r0
lsl r0,r0,#4
add r0,r1,r0
bx lr
00002000 <fun>:
2000: b510 push {r4, lr}
2002: 2005 movs r0, #5
2004: f000 f804 bl 2010 <mult>
2008: 3001 adds r0, #1
200a: bc10 pop {r4}
200c: bc02 pop {r1}
200e: 4708 bx r1
00002010 <mult>:
2010: 1c01 adds r1, r0, #0
2012: 0100 lsls r0, r0, #4
2014: 1808 adds r0, r1, r0
2016: 4770 bx lr
但是,如果从 arm 模式代码调用,这会出错。
使用 gnu 汇编器,您可以使用 .type...function 或 .thumb_func 来使其更正确。
.thumb
.global mult
.thumb_func
mult:
mov r1,r0
lsl r0,r0,#4
add r0,r1,r0
bx lr
00002000 <fun>:
2000: b510 push {r4, lr}
2002: 2005 movs r0, #5
2004: f000 f804 bl 2010 <mult>
2008: 3001 adds r0, #1
200a: bc10 pop {r4}
200c: bc02 pop {r1}
200e: 4708 bx r1
00002010 <mult>:
2010: 1c01 adds r1, r0, #0
2012: 0100 lsls r0, r0, #4
2014: 1808 adds r0, r1, r0
2016: 4770 bx lr
相同的机器代码,因此 .thumb 会使其工作很糟糕,但是将标签声明为函数与将其声明为全局一样重要。使用 .type 您可以像使用 .globl 一样将其放在任何位置,但 .thumb_func 必须在标签之前,而不是立即,但基本上它找到的下一个标签将标记为函数。
所以之后
arm-linux-gnueabihf-gcc 9-main.c 9-mult.s -o myprog.elf
当你在学习 asm 时,甚至有时不是时,当然,如果你正在混合语言,你应该始终遵循:
arm-linux-gnueabihf-objdump -D myprog.elf
并检查输出。
可以仅对代码使用小写 -d,大写 -D 还将包括数据部分,这些部分通常对于查看它构建了您想要构建的内容同样重要。
为了完成你的问题,我建议你反汇编并发布 main 函数和 mult 函数,看看它是否是一个互通问题。或者您是否尝试在 x86 或类似的东西上运行 arm 二进制文件?
如果您检查编译器的完整输出,Frant 已经展示了一组更详细的指令
.cpu cortex-a72
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 2
.eabi_attribute 34, 1
.eabi_attribute 18, 4
.file "so.c"
.text
.align 1
.p2align 2,,3
.global fun
.arch armv8-a
.arch_extension crc
.syntax unified
.thumb
.thumb_func
.fpu softvfp
.type fun, %function
fun:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
strd r3, lr, [sp, #-8]!
mov r0, #5
bl mult
add r0, r0, #1
pop {r3, pc}
.size fun, .-fun
.ident "GCC: (GNU) 10.2.0"
除其他外,您将看到 .type 函数。他们在这里双浸并做了 .type 和 .thumb_func 这很有意义,这是一个算法驱动的输出。