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


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

    #include<stdio.h>
    
    void swap(int *p1,int *p2)
    {
        int temp;
        temp = *p1;
        *p1 = *p2;
        *p2= temp;
        //printf("p1=%d,p2=%d,temp=%d
    ",p1,p2,temp);
    }
    
    void main(){
        int a=0;
        int b=0;
        char *str1="a=%d,b=%d
    ";
        printf("++++++
    ");
    
        a=2;
        b=3;
    
        printf(str1,a,b);
        
        swap(&a,&b);
    
        printf(str1,a,b);
    } 

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

    #include<stdio.h>
    
    void swap(int *p1,int *p2)
    {
        int temp;
        temp = *p1;
        *p1 = *p2;
        *p2= temp;
        //printf("p1=%d,p2=%d,temp=%d
    ",p1,p2,temp);
    }
    
    main(){
        int a=0;
        int b=0;
        char *str1="a=%d,b=%d
    ";
        printf("++++++
    ");
        _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 *p1,int *p2)
    {
        int temp;
        temp = *p1;
        *p1 = *p2;
        *p2= 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

    PS:这里为什么要删掉

    swap:
       
        ret

    因为不删除swap:和ret,那这个汇编表示就是一个函数,而我们知道

    #include<stdio.h>
    
    void main(){
        void swap(int *p1,int *p2)
        {
            //xxxx;
        }
    } 

    这个定义是非法的,即错误的函数定义。

    所以删除swap:和ret后,main里面不再是一个完整的函数,但是又保留了该swap函数的基本功能(即,把下个地址压入堆栈,然后参数入栈,然后把所有寄存器压入堆栈,分配空间,空间清C然后变量赋值开始程序然后做堆栈平衡清理堆栈)。

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

    #include<stdio.h>
    
    main(){
        int a=0;
        int b=0;
        char *str1="a=%d,b=%d
    ";
        printf("++++++
    ");
        _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
    ";
        printf("++++++
    ");
        _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+4h]    //取p1的值,即a的地址  edp+4h,此时不能再使用a这个变量的汇编地址了,因为此时的ebp已经不再是main的ebp
            mov         ecx,dword ptr [eax]        //将a的值赋给ecx
            mov         dword ptr [ebp-4],ecx    //temp=a=2
            mov         edx,dword ptr [ebp+4h]    //取p1的值,即a的地址
            mov         eax,dword ptr [ebp+8h]    //取p2的值,即b的地址
            mov         ecx,dword ptr [eax]        //取b的值3
            mov         dword ptr [edx],ecx        //a=b=3
            mov         edx,dword ptr [ebp+8h]    //取p2的值,即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
        }
    }

     完成!

  • 相关阅读:
    左边菜单导航
    css3实现轮播
    js-统计选项个数
    空间评论。回复。点赞功能
    简单的购物车功能
    字符串常用的几种方法
    React,js实现分页的案列
    python2的cgi程序
    开发环境和工具
    github入门
  • 原文地址:https://www.cnblogs.com/little-kwy/p/12267261.html
Copyright © 2020-2023  润新知