我已被指派将此程序转换为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的信息。
发布于 2022-03-28 00:07:33
神奇的命令是arm-linux-gnueabi-gcc -S -O2 -march=armv8-a power.c
。
arm-linux-gnueabi-gcc
,因为我在X86-64机器上工作,而gcc
没有可用的ARM目标。如果您使用的是arm系统,则应该能够使用常规的gcc
。如果没有,就会出错,但不会造成伤害。-S
告诉gcc输出程序集。-O2
是可选的,只有助于稍微优化代码,并减少结果中的调试杂乱。-march=armv8-a
告诉它在编译时使用ARM v8目标。我有点武断地选择了armv8-a
。根据这些文档,所有的ARM v8都是armv8-a
、armv8.1-a
、armv8.2-a
、armv8.3-a
、armv8.4-a
、armv8.5-a
、armv8.6-a
、armv8-m.base
、armv8-m.main
和armv8.1-m.main
。我不知道有什么不同,所以你可以选择另一个。power.c
只是告诉它要编译哪个文件。因为我们没有指定输出文件(Ex:-o output.asm
),所以程序集将输出到power.s
。如果没有在提供常规arm
目标的gcc
机器上进行编译,则可以使用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
我怎么才能开始。
这是我如何解决这个问题的思考过程。看一下这个问题,我可以看出它可能分为两部分:
gcc -S -fverbose-asm -O2 foo.c
命令。经过测试,我决定删除-fverbose-asm
,因为它似乎只为这么小的程序提供了混乱。gcc
允许您使用-march=xxx
指定目标体系结构。我的下一步是找到一个ARM架构列表,我可以从中选择。在找到gcc.gnu.org/onlinedocs/gcc/ARM-Options.html之后,我选择了armv8-a
,因为它听起来最正确。当我尝试时,gcc
告诉我,无法找到目标体系结构。这并不令人惊讶,因为我在x86-64上,编译器通常会附带兼容的目标,以减少所需的空间。我知道这可能意味着我需要识别提供arm目标的apt
包,所以我四处搜索,直到找到了这个答案,它填充了我需要的其余信息。发布于 2022-03-28 00:19:24
在这样一个简单的例子中,编译器资源管理器就是朋友。
ARMv8 8-具有编译器选项-O1的Clang程序集,用于保持递归:
# 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
ARM GCC (linux)程序集具有编译器选项-O1,用于保持递归:
# 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 (无)装配与编译器选项-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
ARM64 GCC程序集具有编译器选项-O1,用于保持递归:
# 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
https://stackoverflow.com/questions/71641153
复制相似问题