C语言与汇编的嵌入式编程:汇编调用函数(两数交换)

编写一个两数交换函数swap,具体代码如下:

#include<stdio.h>

void swap(int *a,int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b= temp;
    //printf("a=%d,b=%d,temp=%d\n",a,b,temp);
}

void main(){
    int a=0;
    int b=0;
    char *str1="a=%d,b=%d\n";
    printf("++++++\n");

    a=2;
    b=3;

    printf(str1,a,b);

    swap(&a,&b);

    printf(str1,a,b);
} 

首先对main函数进行汇编转换:

#include<stdio.h>

void swap(int *a,int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b= temp;
    //printf("a=%d,b=%d,temp=%d\n",a,b,temp);
}

main(){
    int a=0;
    int b=0;
    char *str1="a=%d,b=%d\n";
    printf("++++++\n");
    _asm{
        //a=2
        mov        a,2

        //b=3
        mov        b,3

        //printf(str1,a,b);
        mov        ecx,b
        push    ecx
        mov        eax,a
        push    eax
        mov        edx,str1
        push    edx
        call    printf
        add        esp,12

        //swap(&a,&b);
        lea         eax,b
        push        eax
        lea         ecx,a
        push        ecx
        call        swap
        add         esp,8

        //printf(str1,a,b);
        mov        ecx,b
        push    ecx
        mov        eax,a
        push    eax
        mov        edx,str1
        push    edx
        call    printf
        add        esp,12
    }
}

现在需要将swap也转化为汇编,并放入main函数中,具体思路如下:

1、先对swap函数反汇编,并删除ret指令,

注明:swap函数大致处理过程为:把下个地址压入堆栈,然后参数入栈,然后把所有寄存器压入堆栈,分配空间,空间清C然后变量赋值开始程序然后做堆栈平衡清理堆栈

void swap(int *a,int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b= temp;
}

swap:
    push        ebp
    mov         ebp,esp
    sub         esp,44h
    push        ebx
    push        esi
    push        edi
    lea         edi,[ebp-44h]
    mov         ecx,11h
    mov         eax,0CCCCCCCCh
    rep stos    dword ptr [edi]
    mov         eax,dword ptr [ebp+8]
    mov         ecx,dword ptr [eax]
    mov         dword ptr [ebp-4],ecx
    mov         edx,dword ptr [ebp+8]
    mov         eax,dword ptr [ebp+0Ch]
    mov         ecx,dword ptr [eax]
    mov         dword ptr [edx],ecx
    mov         edx,dword ptr [ebp+0Ch]
    mov         eax,dword ptr [ebp-4]
    mov         dword ptr [edx],eax
    pop         edi
    pop         esi
    pop         ebx
    mov         esp,ebp
    pop         ebp
    ret

2、将1中的汇编代码替换掉call swap,

#include<stdio.h>

main(){
    int a=0;
    int b=0;
    char *str1="a=%d,b=%d\n";
    printf("++++++\n");
    _asm{
        //a=2
        mov        a,2

        //b=3
        mov        b,3

        //printf(str1,a,b);
        mov        ecx,b
        push    ecx
        mov        eax,a
        push    eax
        mov        edx,str1
        push    edx
        call    printf
        add        esp,12

        //swap(&a,&b);
        lea         eax,b
        push        eax
        lea         ecx,a
        push        ecx
        //call        swap
        push        ebp
        mov         ebp,esp
        sub         esp,44h
        push        ebx
        push        esi
        push        edi
        lea         edi,[ebp-44h]
        mov         ecx,11h
        mov         eax,0CCCCCCCCh
        rep stos    dword ptr [edi]
        mov         eax,dword ptr [ebp+8]
        mov         ecx,dword ptr [eax]
        mov         dword ptr [ebp-4],ecx
        mov         edx,dword ptr [ebp+8]
        mov         eax,dword ptr [ebp+0Ch]
        mov         ecx,dword ptr [eax]
        mov         dword ptr [edx],ecx
        mov         edx,dword ptr [ebp+0Ch]
        mov         eax,dword ptr [ebp-4]
        mov         dword ptr [edx],eax
        pop         edi
        pop         esi
        pop         ebx
        mov         esp,ebp
        pop         ebp
        add         esp,8

        //printf(str1,a,b);
        mov        ecx,b
        push    ecx
        mov        eax,a
        push    eax
        mov        edx,str1
        push    edx
        call    printf
        add        esp,12
    }
}

3、调整替换的swap汇编

#include<stdio.h>

main(){
    int a=0;
    int b=0;
    char *str1="a=%d,b=%d\n";
    printf("++++++\n");
    _asm{
        //a=2
        mov        a,2

        //b=3
        mov        b,3

        //printf(str1,a,b);
        mov        ecx,b
        push    ecx
        mov        eax,a
        push    eax
        mov        edx,str1
        push    edx
        call    printf
        add        esp,12

        //swap(&a,&b);
        lea         eax,b
        push        eax
        lea         ecx,a
        push        ecx
        //call        swap
        push        ebp
        mov         ebp,esp
        sub         esp,44h
        push        ebx
        push        esi
        push        edi
        lea         edi,[ebp-44h]
        mov         ecx,11h
        mov         eax,0CCCCCCCCh
        rep stos    dword ptr [edi]
        mov         eax,a                    //取a地址
        mov         ecx,dword ptr [eax]        //将a的值赋给ecx
        mov         dword ptr [ebp-4],ecx    //temp=*a=2
        mov         edx,a                    //取a地址
        mov         eax,b                    //取b地址
        mov         ecx,dword ptr [eax]        //取b的值3
        mov         dword ptr [edx],ecx        //a=b=3
        mov         edx,b                    //取b地址
        mov         eax,dword ptr [ebp-4]    //取temp的值2
        mov         dword ptr [edx],eax        //b=temp=2
        pop         edi
        pop         esi
        pop         ebx
        mov         esp,ebp
        pop         ebp
        //add         esp,8

        //printf(str1,a,b);
        mov        ecx,b
        push    ecx
        mov        eax,a
        push    eax
        mov        edx,str1
        push    edx
        call    printf
        add        esp,12
    }
}

原文地址:https://www.cnblogs.com/little-kwy/p/12267261.html

时间: 2024-08-01 12:09:06

C语言与汇编的嵌入式编程:汇编调用函数(两数交换)的相关文章

编程题:求两数之和

#include<stdio.h>       /*包含输入输出头文件*/ main()                            /*定义主函数*/ {  int a,b,sum;                /*定义整数变量a.b.sum*/ a=123;                        /*给a赋值*/ b=456;                        /*给b赋值*/ sum=a+b;                  /*令sum=a+b*/ p

今日头条 2018 AI Camp 6 月 2 日在线笔试编程题第二道——两数差的和

题目 给 n 个实数 a_1, a_2 ... a_n, 要求计算这 n 个数两两之间差的绝对值下取整后的和是多少. 输入描述 第一行为一个正整数 n 和一个整数 m.接下来 n 行,第 i 行代表一个整数 b_i.a_i = b_i / m, i = 1...n.n <= 1000: 5分n <= 100000且 a_i 均为整数: 15分n <= 100000 1 <= m <= 10^9 0 <= b_i <= 10^18: 25分 输出描述 一个整数 示例

汇编与JIT编程

读懂汇编 1 什么是汇编? ??计算机能运行的是二进制的指令,如00000011,为了解决可读性和方便编辑的问题,就诞生了汇编语言,所以汇编语言是二进制指令的文本形式,与二进制指令一一对应,如00000011代表ADD,二进制与汇编语言都是最底层的低级语言. 由CPU指令和指令对应的运算子构成一条汇编语句,如: mov %ebx, [%esp+12] add %eax, %ebx ?? 汇编 assembling 的过程,是由汇编器将汇编语言 assembly language (asm) 编译

嵌入式C语言自我修养 11:有一种函数,叫内建函数

11.1 什么是内建函数 内建函数,顾名思义,就是编译器内部实现的函数.这些函数跟关键字一样,可以直接使用,无须像标准库函数那样,要 #include 对应的头文件才能使用. 内建函数的函数命名,通常以 __builtin 开头.这些函数主要在编译器内部使用,主要是为编译器服务的.内建函数的主要用途如下. 用来处理变长参数列表: 用来处理程序运行异常: 程序的编译优化.性能优化: 查看函数运行中的底层信息.堆栈信息等: C 标准库函数的内建版本. 因为内建函数是编译器内部定义,主要由编译器相关的

linux平台学x86汇编(十四):函数的使用

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 和高级语言一样,汇编语言在多个项目之间可能会编写相同的过程和处理,如果使用函数的话就可以不必每次需要时都重复编写实用程序代码,从而在需要它的时候调用它. 函数包含完成特定功能所需的代码,数据从主程序传递给函数,然后结果返回给主程序.调用函数时,程序执行路径被改变,切换到函数代码的第一条指令.处理器从这个位置开始执行指令,直到函数表明它可以把控制返回到主程序中的原始位置. 在汇

16位汇编第六讲汇编指令详解第二讲

16位汇编第六讲汇编指令详解第二讲 1.比较指令 CMP指令 1.CMP指令是将目的操作数减去源操作数,按照定义相应的设置状态标志 2.CMP指令执行的功能与SUB指令(相减指令)一样,但是不同的是CMP指令之根据结果设置标志位 而不修改值 可以操作的指令格式 CMP reg,imm/reg/mem CMP mem,imm/reg 上面是CMP指令的语法,具体的也可以查询帮助文档,inter手册 inter手册查的办法 第一个框代表了CMP指令的所有语法 比如 reg,reg 表示可以比较寄存器

16位汇编第六讲汇编指令详解第第三讲

                                          16位汇编第六讲汇编指令详解第第三讲 1.十进制调整指令 1. 十进制数调整指令对二进制运算的结果进行十进制调整,以得到十进制的运算结果 2.分成压缩BCD码和非压缩BCD码调整 简而言之: 以前的时候你有个手表,里面的数字是九,如果加一个1就是0了,就会产生进位, 不过这个是10进制进位的,所以应该是 a了,但是a的话就出错了.所以我们就出来了这个调整指令直接变为零,然后进位,也就是16进制码当做10进制使用

《C嵌入式编程设计模式》

第一章 什么是嵌入式编程 嵌入式系统的基本知识 面向对象编程与结构化编程 使用C语言实现类.继承.状态机 第二章 嵌入式实时过程Harmony的嵌入式编程 嵌入式应用开发中的敏捷过程原理和工作流程 设计的三个层次 架构的五个关键试图 进行方案设计 什么是设计模式 如何运用设计模式 设计模式实例 第三章 访问硬件的设计模式 硬件代理模式--将硬件封装到类或者结构体 硬件适配器模式--使需要的和提供的接口相适应 中介者模式--协调复杂的交互 观察者模式--支持高效传感器数据分布 去抖模式--抑制间歇

Go语言面组合式向对象编程基础总结

Go语言的面向对象编程简单而干净,通过非侵入式接口模型,否定了C/C++ Java C#等传统面向对象编程语言的复杂度的必要性,我们发现在Go中即使简单的组合也能达到传统面向对象语言的效果,而且耦合度非常低,按照Go的作者之一也就是C语言的作者之一说的一句话:Go是更好的C语言. 1.Go中任意类型Any即  interface{}类型,也就是空接口,可以赋值为任意类型 2.可以为其他类型 内置类型 不包括指针类型添加相应的方法 但是注意的一点是一定要用别名..进行包装 记住想要 为类型 添加新