• ARM 汇编与C之间 的调用


    一. 汇编调用 C

      1. 初始化栈

      2. 初始化BSS段 (BSS 段是C语言存放未初始化的全局变量,或者初始化为0 的全局变量) 

      3 .使用 r0 ,r1, r2, r3 给函数传参,如果多于  4 个参数使用栈的方式传参

      4. 返回值放在 r0, r1 中,最大32位数据, 一般使用 r0 就可以满足要求

    例子: 汇编文件 start.s

    .text  @ 表示汇编文件开始
    
    /****初始化栈*****/
    ldr sp, =0x40000100
    mov r0, #0x5
    mov r1, #0x6
        
    /***初始化bss段***/
    @ bss段地址由链接时编译器分配
    ldr r2, =__bss_start         @ BSS 起始地址
    ldr r3, =__bss_end__         @ BSS 结束地址
    mov r4, #0x00000000     
    
    clbss_l:  
        teq r2, r3         @ r2, r3 中存放的是BSS段起始和结束地址
        strne r4, [r2]    @ 把r4 中的数据写入 r2中存放的地址中,teq结果不成立写入,也就是把bss段写0
        addne r2, r2, #1  @ 起始地址开始偏移一个字节,teq不成立的清苦下
        bne clbss_l   @ teq 不成立,表示还没有清除完bss 段,
        
        bl _main   @ 跳转到执行的C 函数名
    
    .end @ 伪操作 , 表示汇编文件结束

    main.c

    int aa;
    int _main(int a, int b)
    {
    	int t=0;
    	t = a+ b;
    	return t;
    }

    链接文件: map.lds

    OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
    /*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
    OUTPUT_ARCH(arm)
    ENTRY(_start)
    SECTIONS
    {
        . = 0x00000000;
        . = ALIGN(4);
        .text      :
        {
            ./Objects/start.o(.text)
            *(.text)
        }
        . = ALIGN(4);
        .rodata : 
        { *(.rodata) }
        . = ALIGN(4);
        .data : 
        { *(.data) }
        . = ALIGN(4);
        __bss_start = .; 
        .bss :
         { *(.bss) }
        __bss_end__ = .;
    }

    测试: 申请一个全局变量,int aa; 占4字节的BSS 段所以起始和结束地址相差4 字节,所以会在清楚BSS 执行循环4次

    二. C调用汇编

    C 语言调用 汇编时 只要汇编实现的函数通过 .global 声明成全局函数即可在 C语言中调用

    关于参数的传递:

      C 函数的参数,传递给汇编放在寄存器 r0,r1,r2,r3 中;汇编会使用 寄存器 r0 接受调用汇编函数的返回值

      

    例子: start.s汇编文件

    .text
    
    /****初始化栈*****/
    ldr sp, =0x40000100
    mov r0, #0x5
    mov r1, #0x6
    
    /*   汇编跳转到 C 中   */
    /*    初始化bss段    */
    @ bss段地址由链接时编译器分配
    ldr r2, =__bss_start         @ BSS 起始地址
    ldr r3, =__bss_end__         @ BSS 结束地址
    mov r4, #0x00000000     
    
    clbss_l:  
        teq r2, r3         @ r2, r3 中存放的是BSS段起始和结束地址
        strne r4, [r2]    @ 把r4 中的数据写入 r2中存放的地址中,teq结果不成立写入,也就是把bss段写0
        addne r2, r2, #1  @ 起始地址开始偏移一个字节,teq不成立的清苦下
        bne clbss_l   @ teq 不成立,表示还没有清除完bss 段,
        
        bl _main   @ 跳转到执行的C 函数名 , lr 中会保存下一条指令的地址, 也就是
        b loop
    
    /*    汇编函数, 在C 中调用   */
    .global add_fun @ 声明为全局函数,使外部可调用
    add_fun:
        add r2, r1, r0   @ 把 r1和r0中的数据相加 放在r2 中
        mov r0, r2    @ 使用寄存器 r0 存放调用汇编函数时返回的结果
        mov pc, lr    @ lr 寄存器中保存 C 跳转到汇编时的下一条指令地址 , 重新付给 PC 继续执行loop:
        b loop
    
    .end

    测试:

  • 相关阅读:
    IFRAME自适应高度
    项目支出数据产生过程
    hbase体系结构以及说明
    PLSQL 设置
    hadoop编程模型
    捕捉桌面上的窗口信息
    在不修改代码的情况下无限扩展应用项目
    跟我一起玩Win32开发(25):监视剪贴板
    跟我一起玩Win32开发(24):计时器
    跟我一起玩Win32开发(23):渐变颜色填充
  • 原文地址:https://www.cnblogs.com/electronic/p/11021763.html
Copyright © 2020-2023  润新知