历史上的今天
返回首页

历史上的今天

今天是:2025年01月03日(星期五)

正在发生

2020年01月03日 | ARM C内嵌asm写法

2020-01-03 来源:eefocus

最近在玩E2手机,想把C/Invoke(http://www.nongnu.org/cinvoke/)移植到E2上,它的CPU是arm的,系统是Linux,下了源代码,按照说明自已添了一个gcc_arm_linux的arch文件,可是在修改时发现里边还有asm代码,以前没弄过,开始完全看不懂,于是呼!在网上找来《ARM指令集》找到要用到的指令,指令到是简单,可是asm内嵌c的写法把我搞晕了,又找来《AT&T ASM参考》,这才把代码中的几个内嵌ARM汇编的宏对付上。部分代码:

/////////////////////////////////////
// macros
/////////////////////////////////////

// the following examples are given
// for x86 in MASM syntax.  Some of these
// macros might not need to be implemented
// in inline assembly, depending on the arch,
// but likely most of them will.

// this macro stores the values in the input
// registers in the ArchRegParms structure passed as 'regparms'.
// In the example below we store ecx and edx because
// they are used in the fastcall convention to pass
// parameters.

// 存储“输入寄存器”中的值到regparms中。

#define ARCH_SAVE_REGPARMS(regparms) 
    __asm__("str %%r0, %0; 
        str %%r1, %1; 
        str %%r2, %2; 
        str %%r3, %3; 
        str %%r4, %4; 
        str %%r5, %5; 
        str %%r6, %6; 
        str %%r7, %7;" : 
            "=m" ((regparms).a1), 
            "=m" ((regparms).a2), 
            "=m" ((regparms).a3), 
            "=m" ((regparms).a4), 
            "=m" ((regparms).d0), 
            "=m" ((regparms).d1), 
            "=m" ((regparms).d2), 
            "=m" ((regparms).d3) :: );

// this macro does two things: copies the values
// stored in regparms into the input registers,
// and calls the function pointed to by the pointer
// ep.

// 复制regparms中的值到“输入寄存器”中,并调用指针ep指向的函数。

#define ARCH_CALL(regparms, ep) 
    __asm__("ldr %%r0, %0; 
        ldr %%r1, %1; 
        ldr %%r2, %2; 
        ldr %%r3, %3; 
        ldr %%r4, %4; 
        ldr %%r5, %5; 
        ldr %%r6, %6; 
        ldr %%r7, %7; 
        ldr %%r8, %8; 
        bx %%r8;" :: 
            "m" ((regparms).a1), 
            "m" ((regparms).a2), 
            "m" ((regparms).a3), 
            "m" ((regparms).a4), 
            "m" ((regparms).d0), 
            "m" ((regparms).d1), 
            "m" ((regparms).d2), 
            "m" ((regparms).d3), 
            "m" (ep) : 
            "r0", 
            "r1", 
            "r2", 
            "r3", 
            "r4", 
            "r5", 
            "r6", 
            "r7", 
            "r8");



// saves any possible return values in the ArchRetValue
// structure given by archvalue.

// 保存archvalue中任何可能的返回值。

#define ARCH_SAVE_RETURN(archvalue, type) 
    __asm__("str %%r0, %0; 
        str %%r1, %1; 
        str %%r4, %2;" : 
            "=m" ((archvalue).a1), 
            "=m" ((archvalue).a2), 
            "=m" ((archvalue).d0) :: );


// stores the return values in the ArchRetValue structure
// into any place where a caller might expect to find them

// 存储archvalue中的值到“调用者”能找到的地方(寄存器)。

#define ARCH_SET_RETURN(archvalue, type) 
    __asm__("ldr %%r0, %0; 
        ldr %%r1, %1; 
        ldr %%r4, %2;" :: 
            "m" ((archvalue).a1), 
            "m" ((archvalue).a2), 
            "m" ((archvalue).d0) : 
            "r0", 
            "r1", 
            "r4");



// increases the stack size by bcount bytes
#define ARCH_PUT_STACK_BYTES(bcount) 
    __asm__("ldr %%r8, %0; 
                sub %%sp, %%sp, %%r8;" :: 
                    "m" (bcount) : 
                    "r8", 
                    "sp");

// decreases the stack size by bcount bytes
#define ARCH_REMOVE_STACK_BYTES(bcount) 
    __asm__("ldr %%r8, %0; 
                add %%sp, %%sp, %%r8;" :: 
                    "m" (bcount) : 
                    "r8", 
                    "sp");

// copies the current stack pointer into the pointer variable
// stackp
#define ARCH_GET_STACK(stackp) 
    __asm__("str %%r13, %0;" : "=m" (stackp) :: );


// copies the current frame pointer into the pointer variable
// framep
#define ARCH_GET_FRAME_PTR(framep)     
    __asm__("str %%r11, %0;" : "=m" (framep) :: );


主要说一下AT&T ASM内嵌的写法,格式如下:
__asm__("指令" : "操作约束” (输出参数) : (输入参数) : 寄存器约束);

指令:当然就是ARM的汇编指令了,但要注意的是寄存器要用%%来约束,以防与参数%冲突。


操作约束(OperationConstraint):我个人理解为参数传递方式,如:"=m",中“=”表示输出,还可以不写表示输入,"+"表示输 入和输出, “m”表示使用内存,在x86中,还可以是“a”、“b”、“c”等,表示使用什么样的寄存器。

推荐阅读

史海拾趣

问答坊 | AI 解惑

现在貌似找工作时都没要求同时得会arm和fpga

如果同时掌握了arm和cpld会不会有所帮助? 来自EEWORLD合作群:arm linux fpga 嵌入0(49900581)群主:wangkj…

查看全部问答>

记录波形

1、  想把一个时间段的波形录制下来再看,或者传到电脑上进一步分析,有没有这样的示波器?或者有这样功能的仪器叫什么,大家有用到的介绍下…

查看全部问答>

求ADC0809资料,电路图或小程序

那位大哥有的话发一个到我邮箱行吗?谢谢! sodik@126.com…

查看全部问答>

sigmatel 9200 HD 声卡没有混音功能怎么办

能够记录机器里面播放的声音,或者使用麦克可以录音,但就是不能同时实现卡拉ok混音功能。怎么办,网上找到的补丁都用过了,就是不能用混音。 高手在哪里?…

查看全部问答>

NDIS的一点疑问?

我的是一个协议层驱动,有个疑问就是 A.使用CreateService,OpenService,QueryServiceStatus及StartService等一系列API安装起来的驱动 B.使用Inf文件及INetCfg的COM接口安装的驱动 问题是 1.这两种方式有什么不同? 2.为什么A安装后\"本地连接\" ...…

查看全部问答>

【招兵买马】响应论坛活动

随着论坛LM811的开发板的活动,先前我也在论坛发过一些关于DIY机器人的意见贴!~ 随着我实习已经快接近尾声了,在论坛活动结束之后,召集申请到得开发板的童鞋,当然没有申请到得童鞋也是可以的啦,一起来DIY机器人,如果我没有申请到我会自己出钱 ...…

查看全部问答>

全国电子设计竞赛A题交流群101126312

本帖最后由 paulhyde 于 2014-9-15 04:03 编辑 全国电子设计竞赛A题交流群101126312  …

查看全部问答>

【TI课程ppt】开关电源组件选择

开关电源组件选择 开关电源组件选择 (Switch-Power-Supply-Component-Selection) 开关电源深入浅出之设计选型篇,作为能量转换的装置-电源,此篇告诉你想了解的储能元器件类型和如何选择,理解并能优化选择电容和电感 课程大纲: 拓扑敏感回路 ...…

查看全部问答>

中秋节,晒福利

如题,晒晒你们公司的中秋福利吧…

查看全部问答>

msp430f5418的DCO最高倍频是多少

msp430f5418的DCO最高倍频多少?能不能倍到40MHz或以上?尝试过没成功…

查看全部问答>