专栏首页m0w3nC语言与汇编的嵌入式编程:main中模拟函数的调用(两数交换)

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\n",p1,p2,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 *p1,int *p2)
{
    int temp;
    temp = *p1;
    *p1 = *p2;
    *p2= temp;
    //printf("p1=%d,p2=%d,temp=%d\n",p1,p2,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 *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\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,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
    }
}

 完成!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C语言与汇编的嵌入式编程:求100以内素数

     由于C语言中使用的是for进行循环,使用VC调试汇编时,发现for汇编的jmp需要具体地址才可以进行,对于程序来讲不方便

    墨文
  • C语言与汇编的嵌入式编程:统计字符串中各字符出现的次数

    墨文
  • python3升级pip报错ImportError: cannot import name 'main'

    墨文
  • Tree - 226. Invert Binary Tree

    用户5705150
  • Golang Leetcode 226. Invert Binary Tree.go

    版权声明:原创勿转 https://blog.csdn.net/anakinsun/article/details/89043397

    anakinsun
  • 开源信息:欢迎使用支持12种数据库的自动分页插件

    MyBatis-Pageable是一款自动化分页的插件,基于MyBatis内部的插件Interceptor拦截器编写完成,拦截Executor.query的两个...

    恒宇少年
  • 8 比对及找变异步骤的质控

    完成后会生成SRR8517856_bqsr_stats类似的文件夹 现在建立一个qualimap文件夹,把上面这种文件夹都移动到里面

    Y大宽
  • Python图形编程探索系列-02-框架

    py3study
  • Python开发环境搭建

    地址  https://github.com/yyuu/pyenv-installer

    py3study
  • Swift - 网页控件(UIWebView)加载本地数据,文件

    使用UIWebView加载本地数据或资源有如下三种方式: 1,使用 **loadHTMLString **方法加载HTML内容 2,使用 **loadReq...

    Python疯子

扫码关注云+社区

领取腾讯云代金券