Assembly 如何定义可在C中使用的ARM汇编函数
我已经学了几个月的C语言,现在我开始更深入地研究底层语言——ARM汇编,因此,我决定从一个非常基础的项目开始,制作一个定义阶乘函数的汇编文件.S,然后在C中调用和使用它。所以我想问一下汇编是否可以用来定义这样一个复杂的函数,是否可以用作C中的另一个函数?如果您不介意的话,请给我一个简单的.S文件示例,其中一个函数从标准输入num1和num2加载2个数字到寄存器,计算num1*num2并返回定义的结果,并且可以在C源文件中使用Assembly 如何定义可在C中使用的ARM汇编函数,assembly,arm,gnu-toolchain,Assembly,Arm,Gnu Toolchain,我已经学了几个月的C语言,现在我开始更深入地研究底层语言——ARM汇编,因此,我决定从一个非常基础的项目开始,制作一个定义阶乘函数的汇编文件.S,然后在C中调用和使用它。所以我想问一下汇编是否可以用来定义这样一个复杂的函数,是否可以用作C中的另一个函数?如果您不介意的话,请给我一个简单的.S文件示例,其中一个函数从标准输入num1和num2加载2个数字到寄存器,计算num1*num2并返回定义的结果,并且可以在C源文件中使用 谢谢你的阅读。如果这个问题是愚蠢的,至少,请给我一个方向,这样我就可以
谢谢你的阅读。如果这个问题是愚蠢的,至少,请给我一个方向,这样我就可以按照自己的思路去做并找出答案。要使用C汇编语言编写的函数,您主要需要:
int add(int a, int b);
它是一个声明,因为它不包含函数体。当然,名称(在本例中添加)必须匹配
如果在C++中使用,则必须添加<代码>外部“C”<代码>:
呼叫约定 调用约定定义了如何向函数传递参数和从函数返回参数,以及必须保存哪些寄存器。你需要熟悉细节。有关简化的概述,请访问 超短且非常简化的版本是:- 前四个参数在R0到R3中传递,其余参数在堆栈中传递
- 返回值在R0中返回
- 必须保存和还原R0到R3以外的寄存器
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函数的调试版本:在堆栈上分配空间以将
a
和b
存储为局部变量,帧指针寄存器(fp)指向局部变量。最后,一切都恢复了。大多数健全的编译器编译成汇编,然后调用汇编程序将其转换为对象
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-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
arm none eabi as so.s-o so.o
arm none eabi objdump-D so.o
so.o:文件格式elf32 littlearm
第节的分解。正文:
00000000 :
0:e22110ff提高采收率r1,r1,#255;0xff
4:e0810080添加r0、r1、r0、lsl#1
8:E12FF1E 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
。全球乐趣
乐趣:
提高采收率r1,r1,#255
加上r0,r1,r0,lsl#1
bx-lr
臂无eabi as so.s-o so.o
arm none eabi objdump-D so.o
第节的分解。正文:
00000000 :
0:e22110ff提高采收率r1,r1,#255;0xff
4:e0810080添加r0、r1、r0、lsl#1
8:E12FF1E bx lr
关于从C调用asm函数的问题并不愚蠢(但是,如果您尝试的话,您可能会发现有大量关于这方面的信息)。这里通常不欢迎向你提供几乎所有东西的请求——首先展示你的努力,你到目前为止做了什么,你被困在哪里。在汇编语言中进行输入是一个非常不切实际的想法——在C语言中进行输入要容易得多,那么有什么意义呢?你会得到什么?在C中进行输入,将其作为参数传递到asm函数中进行处理,并将结果返回到C程序中。这更有意义。您可能需要检查编译器生成的assemply代码。如果使用“-s”标志,gcc将生成.s输出。汇编语言是由汇编程序、工具而不是目标定义的。但在gas中,除非声明为全局,否则标签是局部的并不少见,而不像C,在C中,标签(变量/函数名)是全局的,除非声明为局部的(静态)。有些编译器会损坏标签,有些则不会。因此,主要的练习是针对您的工具链/汇编器。您是否需要将标签声明为全局的,以及是否需要将其损坏。另外请注意,如果要执行thumb操作,则最好在函数标签之前使用.thumb\u func(将应用于它看到的下一个标签,而不必是下一行代码)。
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
.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