编写一个两数交换函数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=;
int b=;
char *str1="a=%d,b=%d\n";
printf("++++++\n"); a=;
b=; 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=;
int b=;
char *str1="a=%d,b=%d\n";
printf("++++++\n");
_asm{
//a=2
mov a, //b=3
mov b, //printf(str1,a,b);
mov ecx,b
push ecx
mov eax,a
push eax
mov edx,str1
push edx
call printf
add esp, //swap(&a,&b);
lea eax,b
push eax
lea ecx,a
push ecx
call swap
add esp, //printf(str1,a,b);
mov ecx,b
push ecx
mov eax,a
push eax
mov edx,str1
push edx
call printf
add esp,
}
}

现在需要将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+]
mov ecx,dword ptr [eax]
mov dword ptr [ebp-],ecx
mov edx,dword ptr [ebp+]
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-]
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=;
int b=;
char *str1="a=%d,b=%d\n";
printf("++++++\n");
_asm{
//a=2
mov a, //b=3
mov b, //printf(str1,a,b);
mov ecx,b
push ecx
mov eax,a
push eax
mov edx,str1
push edx
call printf
add esp, //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+]
mov ecx,dword ptr [eax]
mov dword ptr [ebp-],ecx
mov edx,dword ptr [ebp+]
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-]
mov dword ptr [edx],eax
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
add esp, //printf(str1,a,b);
mov ecx,b
push ecx
mov eax,a
push eax
mov edx,str1
push edx
call printf
add esp,
}
}

3、调整替换的swap汇编

#include<stdio.h>

main(){
int a=;
int b=;
char *str1="a=%d,b=%d\n";
printf("++++++\n");
_asm{
//a=2
mov a, //b=3
mov b, //printf(str1,a,b);
mov ecx,b
push ecx
mov eax,a
push eax
mov edx,str1
push edx
call printf
add esp, //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-],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-] //取temp的值2
mov dword ptr [edx],eax //b=temp=2
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
add esp, //printf(str1,a,b);
mov ecx,b
push ecx
mov eax,a
push eax
mov edx,str1
push edx
call printf
add esp,
}
}

完成!

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

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

    写汇编之前,需要搞清楚C语言代码的写法,这里以最简单的算法举例说明 C代码如下: #include <stdio.h> void main(){ int i,j; ; ;i<=;i+ ...

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

    原始C语言: #include<stdio.h> void main(){ ]; char pipei[] = "abcdefghijklmnopqrstuvwxyz" ...

  3. c语言实现两数交换的三种方法

    实现变量的值互相交换的三种不同方法 方法一:利用第三个变量来实现数值的交换 int tmp; tmp = a; a = b; b = tmp; 此方法直观,简易.不易出错,推荐使用 方法二:利用两个变 ...

  4. 不用局部变量实现C语言两数交换算法

    关于交换算法,我想非常简单,所以,这次不做分析,直接上代码: #include <stdio.h> #include <stdlib.h> //用异或方式实现 void swa ...

  5. Shell编程-09-Shell中的函数

    目录 基本语法 函数执行 函数示例     函数可以简化程序的代码量,达到更好的代码复用度,因此会让程序变得更加易读.简洁和易修改.其作用就是将需要多次使用的代码整合到一块,使其成为一个整体,然后通过 ...

  6. 关于main与wmain函数

    最近写一个控制台程序,并且希望该控制台程序运行时不显示控制台窗口,于是在程序include语句下面加入如下代码 #pragma comment (linker,"/subsystem:\&q ...

  7. Serverless 在编程教育中的实践

    说起Serverless这个词,我想大家应该都不陌生,那么Serverless这个词到底是什么意思?Serverless到底能解决什么问题?可能很多朋友还没有深刻的体会和体感,这篇文章我就和大家一起聊 ...

  8. c语言环境初始化&c语言和汇编混合编程

    bootloader通常会分为两个阶段:第一阶段采用汇编语言来编写,主要是一些核心的初始化工作(内存,时钟的初始化),第二阶段使用C语言来编写,主要是它会完成一些板载硬件的初始化(串口,网口)然后其启 ...

  9. 【C/C++】C语言嵌入式编程修炼·背景篇·软件架构篇·内存操作篇

    C 语言嵌入式系统编程修炼之一:背景篇 不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力.无疑,汇编语言具备这样的特质.但是,归因于汇编语言 ...

随机推荐

  1. 是未来还是“有毒”?紧抓球鞋风口的毒APP机遇与危机并存

    编辑 | 于斌 出品 | 于见(mpyujian) 新一代的"潮流"之风正在席卷新生代消费市场,从去年开始,国内二手球鞋交易领域突然开始火爆,大有成为新一轮"风口&quo ...

  2. nginx location匹配及rewrite规则

    location匹配规则 1. 实例 server{ location = \ { [配置A] } location / { [配置B] } location = /images/ { [配置C] } ...

  3. mybatis-plus 错误

    错误:java.lang.NoClassDefFoundError: org/apache/velocity/context/Context 原因: 缺少velocity的依赖 解决方案: <d ...

  4. dfs题型二(迷宫问题)

    取自:<王道论坛计算机考研机试指南>6.5节 例 6.7 Temple of the bone(九度 OJ 1461)时间限制:1 秒 内存限制:32 兆 特殊判题:否题目描述:The d ...

  5. Tinyhttp源码分析

    简介 Tinyhttp是一个轻量型Http Server,使用C语言开发,全部代码只500多行,还包括一个简单Client. Tinyhttp程序的逻辑为:一个无线循环,一个请求,创建一个线程,之后线 ...

  6. 8.7-Day1T1

    题目大意: T组测试数据,每组测试数据给出一个n,求[0,n-1]所有逆元的和.(n可能不为质数) 题解: 我的想法: 求出每一个数的逆元,再相加.由于有n为质数的时候,所以,我将它分为两种情况:(1 ...

  7. Lenet 神经网络-实现篇(1)

    Lenet 神经网络结构为: ①输入为 32*32*1 的图片大小,为单通道的输入: ②进行卷积,卷积核大小为 5*5*1,个数为 6,步长为 1,非全零填充模式: ③将卷积结果通过非线性激活函数: ...

  8. L3-010 是否完全二叉搜索树 (30分)

    题解 判断一棵树是否是完全二叉树: 取队列的头,将头的左右孩子入队,循环每次判断是否为空,如果为空节点,此时退出循环. 然后检查队列中的元素是否全部为空,如果是则说明是完全二叉树,否则不是. 代码 # ...

  9. AcWing 850. Dijkstra求最短路 II 堆优化版 优先队列 稀疏图

    //稀疏图 点和边差不多 #include <cstring> #include <iostream> #include <algorithm> #include ...

  10. springboot 整合GuavaCache缓存

    Guava Cache是一种本地缓存机制,之所以叫本地缓存,是因为它不会把缓存数据放到外部文件或者其他服务器上,而是存放到了应用内存中. Guava Cache的优点是:简单.强大.轻量级. Guav ...