将我的C++程序转换为ARM程序集



我被指派将此程序转换为臂组件v8。

int power(int x, int y){
if (x == 0){
return 0;
}
else if (y < 0){
return 0;
}
else if (y == 0){
return 1;

}
else {
return x * power(x, y - 1);
}
}

虽然我对ARM汇编语言不是很熟悉,但我想知道从哪里开始。

我试图对此进行一些研究,但最终在互联网上发现的关于ARM的信息很少。

魔术命令是arm-linux-gnueabi-gcc -S -O2 -march=armv8-a power.c

  • 我使用了arm-linux-gnueabi-gcc,因为我在X86-64机器上工作,而gcc没有可用的ARM目标。如果你在手臂系统上,你应该能够使用常规的gcc。否则,它会出错,但不会造成伤害
  • -S告诉gcc输出程序集
  • -O2是可选的,只是有助于稍微优化代码,并减少结果中的调试混乱
  • -march=armv8-a告诉它在编译时使用ARMv8目标。我有点武断地选择了armv8-a。根据文档,所有ARM v8都是armv8-aarmv8.1-aarmv8.2-aarmv8.3-aarmv8.4-aarmv8.5-aarmv8.6-aarmv8-m.basearmv8-m.mainarmv8.1-m.main。我不知道有什么不同,所以你可能想选择一个不同的
  • power.c只是告诉它要编译哪个文件。由于我们没有指定输出文件(例如:-o output.asm(,因此程序集将输出到power.s

如果您不是在使用常规gcc提供所需目标的arm计算机上进行编译,则可以使用arm-linux-gnueabi-gcc。如果你没有安装,你可以用安装

sudo apt-get update
sudo apt-get install gcc-arm-linux-gnueabi binutils-arm-linux-gnueabi

输出

如果有人好奇,这是我在机器上试用时收到的输出。

.arch armv8-a
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 2
.eabi_attribute 34, 1
.eabi_attribute 18, 4
.file   "testing.c"
.text
.align  2
.global power
.syntax unified
.arm
.fpu softvfp
.type   power, %function
power:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
clz     r2, r0
mov     r3, r0
lsr     r2, r2, #5
orrs    r2, r2, r1, lsr #31
bne     .L4
cmp     r1, #0
mov     r0, #1
bxeq    lr
.L3:
subs    r1, r1, #1
mul     r0, r3, r0
bne     .L3
bx      lr
.L4:
mov     r0, #0
bx      lr
.size   power, .-power
.ident  "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
.section        .note.GNU-stack,"",%progbits

我该怎么开始呢

以下是我如何解决这个问题的思考过程。看看这个问题,我可以看出它可能分为两部分:

  1. 如何将该代码编译为程序集

    对于第一部分,我找到了这个答案,它提供了命令gcc -S -fverbose-asm -O2 foo.c。测试后,我决定删除-fverbose-asm,因为它似乎只会给这么小的程序带来混乱。

  2. 如何将编译器目标设置为ARM v8

    在谷歌上快速搜索后,我发现gcc允许您使用-march=xxx指定目标体系结构。我的下一步是找到一个可以从中选择的ARM体系结构列表。在找到gcc.gnu.org/onlinedocs/gcc/ARM-Options.html后,我选择了armv8-a,因为它听起来最正确。当我尝试它时,gcc告诉我找不到目标架构。这并不奇怪,因为我使用的是x86-64,而且编译器通常带有兼容的目标,以减少所需的空间。我知道这可能意味着我需要识别提供手臂目标的apt包,所以我四处搜索,直到找到这个答案,这个答案填补了我需要的其余信息。

编译器资源管理器就是这种简单情况下的朋友。

ARMv8-Clang汇编,带有编译器选项-O1,用于保持递归:

# Compilation provided by Compiler Explorer at https://godbolt.org/
power(int, int):                             // @power(int, int)
stp     x29, x30, [sp, #-32]!           // 16-byte Folded Spill
str     x19, [sp, #16]                  // 8-byte Folded Spill
mov     x29, sp
mov     w19, w0
mov     w0, wzr
cbz     w19, .LBB0_5
tbnz    w1, #31, .LBB0_5
cbz     w1, .LBB0_4
sub     w1, w1, #1
mov     w0, w19
bl      power(int, int)
mul     w0, w0, w19
b       .LBB0_5
.LBB0_4:
mov     w0, #1
.LBB0_5:
ldr     x19, [sp, #16]                  // 8-byte Folded Reload
ldp     x29, x30, [sp], #32             // 16-byte Folded Reload
ret

带有编译器选项-O1的ARM GCC(linux(程序集,用于保持递归:

# Compilation provided by Compiler Explorer at https://godbolt.org/
power(int, int):
push    {r4, lr}
mov     r4, r0
clz     r0, r0
lsrs    r0, r0, #5
orrs    r3, r0, r1, lsr #31
it      ne
movne   r0, #0
beq     .L6
.L1:
pop     {r4, pc}
.L6:
movs    r0, #1
cmp     r1, #0
beq     .L1
subs    r1, r1, #1
mov     r0, r4
bl      power(int, int)
mul     r0, r4, r0
b       .L1

ARM GCC(none(带有编译器选项-O1的程序集,用于保持递归:

# Compilation provided by Compiler Explorer at https://godbolt.org/
power(int, int):
push    {r4, lr}
mov     r4, r0
rsbs    r0, r0, #1
movcc   r0, #0
orrs    r3, r0, r1, lsr #31
movne   r0, #0
beq     .L6
.L1:
pop     {r4, lr}
bx      lr
.L6:
cmp     r1, #0
moveq   r0, #1
beq     .L1
sub     r1, r1, #1
mov     r0, r4
bl      power(int, int)
mul     r0, r4, r0
b       .L1

带有编译器选项-O1的ARM64 GCC程序集,用于保持递归:

# Compilation provided by Compiler Explorer at https://godbolt.org/
power(int, int):
cmp     w1, 0
ccmp    w0, 0, 4, ge
bne     .L9
mov     w0, 0
ret
.L9:
stp     x29, x30, [sp, -32]!
mov     x29, sp
str     x19, [sp, 16]
mov     w19, w0
mov     w0, 1
cbnz    w1, .L10
.L1:
ldr     x19, [sp, 16]
ldp     x29, x30, [sp], 32
ret
.L10:
sub     w1, w1, #1
mov     w0, w19
bl      power(int, int)
mul     w0, w19, w0
b       .L1

最新更新