我已经学习C几个月了,现在我开始更深入地研究低级语言-ARM汇编,因此,我决定从一个非常基本的项目开始,制作一个汇编文件.S。定义阶乘函数,然后在C中调用它并使用它。因此,我想问一下汇编程序是否可以用于定义这种复杂函数,并且可以用作C中的另一个函数?如果您不介意,请给我一个.S文件的简单示例,其中一个函数将2个数字从标准输入num1和num2加载到寄存器中,计算num1 * num2并返回定义的结果,并且可以在C源代码中使用文件?
感谢您的阅读。如果这个问题很愚蠢,至少请给我一个方向,以便我可以自己跟踪并找出来。
答案 0 :(得分:0)
要使用用C用汇编语言编写的函数,您主要需要做的事情:
声明
声明起来很容易,例如:
int add(int a, int b);
这是一个声明,因为它不包含函数的主体。当然,名称(在这种情况下为 add )必须匹配。
如果在C ++中使用它,则必须添加extern "C"
:
extern "C" int add(int a, int b);
通话约定
调用约定定义如何将参数传递给函数以及从函数返回参数,以及必须保存哪些寄存器。您需要熟悉这些细节。可以在ARM (A32) calling convention上找到简化的概述。
一个超短而且非常简化的版本是:
上述功能的简单实现是:
add:
add r0, r0, r1
bx lr
a
在R0中传递,b
在R1中传递。结果在R0
中返回。 R3以上的寄存器不会被保存,因为它们未被触摸。
更广泛的版本如下:
add:
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #12
str r0, [fp, #-8]
str r1, [fp, #-12]
ldr r2, [fp, #-8]
ldr r3, [fp, #-12]
add r3, r2, r3
mov r0, r3
add sp, fp, #0
ldr fp, [sp], #4
bx lr
这基本上是 add 函数的 debug 版本:在堆栈上分配了空间,用于存储a
和b
作为局部变量,帧指针寄存器(fp)指向局部变量。最后,一切都将恢复。
答案 1 :(得分:0)
大多数理智的编译器都会编译为汇编,然后调用汇编器将其转换为对象。
unsigned int fun ( unsigned int a, unsigned int b)
{
return((a<<1)+(b^0xFF));
}
arm-none-eabi-gcc -O2 -c so.c -o so.o
arm-none-eabi-objdump -D so.o
00000000 <fun>:
0: e22110ff eor r1, r1, #255 ; 0xff
4: e0810080 add r0, r1, r0, lsl #1
8: e12fff1e bx lr
即使允许组装输出,我仍然认为这是读取输出的最简单方法。
但是你可以做到
arm-none-eabi-gcc -O2 -S so.c -o so.s
或
arm-none-eabi-gcc -O2 -c -save-temps so.c -o so.o
然后看
cat so.s
.cpu arm7tdmi
.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, 0
.eabi_attribute 18, 4
.file "so.c"
.text
.align 2
.global fun
.arch armv4t
.syntax unified
.arm
.fpu softvfp
.type fun, %function
fun:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
eor r1, r1, #255
add r0, r1, r0, lsl #1
bx lr
.size fun, .-fun
.ident "GCC: (GNU) 8.2.0"
您可以自己组装的
arm-none-eabi-as so.s -o so.o
arm-none-eabi-objdump -D so.o
so.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <fun>:
0: e22110ff eor r1, r1, #255 ; 0xff
4: e0810080 add r0, r1, r0, lsl #1
8: e12fff1e bx lr
并获得相同的对象,就像您没有单独执行步骤一样。这也意味着您可以只用汇编语言编写自己的函数,然后将其链接到项目中,就像使用C编译对象一样。
.global fun
fun:
eor r1, r1, #255
add r0, r1, r0, lsl #1
bx lr
arm-none-eabi-as so.s -o so.o
arm-none-eabi-objdump -D so.o
Disassembly of section .text:
00000000 <fun>:
0: e22110ff eor r1, r1, #255 ; 0xff
4: e0810080 add r0, r1, r0, lsl #1
8: e12fff1e bx lr