Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 如何定义可在C中使用的ARM汇编函数_Assembly_Arm_Gnu Toolchain - Fatal编程技术网

Assembly 如何定义可在C中使用的ARM汇编函数

Assembly 如何定义可在C中使用的ARM汇编函数,assembly,arm,gnu-toolchain,Assembly,Arm,Gnu Toolchain,我已经学了几个月的C语言,现在我开始更深入地研究底层语言——ARM汇编,因此,我决定从一个非常基础的项目开始,制作一个定义阶乘函数的汇编文件.S,然后在C中调用和使用它。所以我想问一下汇编是否可以用来定义这样一个复杂的函数,是否可以用作C中的另一个函数?如果您不介意的话,请给我一个简单的.S文件示例,其中一个函数从标准输入num1和num2加载2个数字到寄存器,计算num1*num2并返回定义的结果,并且可以在C源文件中使用 谢谢你的阅读。如果这个问题是愚蠢的,至少,请给我一个方向,这样我就可以

我已经学了几个月的C语言,现在我开始更深入地研究底层语言——ARM汇编,因此,我决定从一个非常基础的项目开始,制作一个定义阶乘函数的汇编文件.S,然后在C中调用和使用它。所以我想问一下汇编是否可以用来定义这样一个复杂的函数,是否可以用作C中的另一个函数?如果您不介意的话,请给我一个简单的.S文件示例,其中一个函数从标准输入num1和num2加载2个数字到寄存器,计算num1*num2并返回定义的结果,并且可以在C源文件中使用


谢谢你的阅读。如果这个问题是愚蠢的,至少,请给我一个方向,这样我就可以按照自己的思路去做并找出答案。

要使用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