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=;
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中模拟函数的调用(两数交换)的更多相关文章
- C语言与汇编的嵌入式编程:求100以内素数
写汇编之前,需要搞清楚C语言代码的写法,这里以最简单的算法举例说明 C代码如下: #include <stdio.h> void main(){ int i,j; ; ;i<=;i+ ...
- C语言与汇编的嵌入式编程:统计字符串中各字符出现的次数
原始C语言: #include<stdio.h> void main(){ ]; char pipei[] = "abcdefghijklmnopqrstuvwxyz" ...
- c语言实现两数交换的三种方法
实现变量的值互相交换的三种不同方法 方法一:利用第三个变量来实现数值的交换 int tmp; tmp = a; a = b; b = tmp; 此方法直观,简易.不易出错,推荐使用 方法二:利用两个变 ...
- 不用局部变量实现C语言两数交换算法
关于交换算法,我想非常简单,所以,这次不做分析,直接上代码: #include <stdio.h> #include <stdlib.h> //用异或方式实现 void swa ...
- Shell编程-09-Shell中的函数
目录 基本语法 函数执行 函数示例 函数可以简化程序的代码量,达到更好的代码复用度,因此会让程序变得更加易读.简洁和易修改.其作用就是将需要多次使用的代码整合到一块,使其成为一个整体,然后通过 ...
- 关于main与wmain函数
最近写一个控制台程序,并且希望该控制台程序运行时不显示控制台窗口,于是在程序include语句下面加入如下代码 #pragma comment (linker,"/subsystem:\&q ...
- Serverless 在编程教育中的实践
说起Serverless这个词,我想大家应该都不陌生,那么Serverless这个词到底是什么意思?Serverless到底能解决什么问题?可能很多朋友还没有深刻的体会和体感,这篇文章我就和大家一起聊 ...
- c语言环境初始化&c语言和汇编混合编程
bootloader通常会分为两个阶段:第一阶段采用汇编语言来编写,主要是一些核心的初始化工作(内存,时钟的初始化),第二阶段使用C语言来编写,主要是它会完成一些板载硬件的初始化(串口,网口)然后其启 ...
- 【C/C++】C语言嵌入式编程修炼·背景篇·软件架构篇·内存操作篇
C 语言嵌入式系统编程修炼之一:背景篇 不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力.无疑,汇编语言具备这样的特质.但是,归因于汇编语言 ...
随机推荐
- vue小例子-01
1.在components下建一个 2.代码如下: <template> <!--1.业务是开始有一组数据,序号,姓名,性别,年龄,操作(删除) 2.有三个输入框输入姓名,性 ...
- PP: Overviewing evolution patterns of egocentric networks by interactive construction of spatial layouts
Problem: get an overall picture of how ego-networks evolve is a common challenging task. Existing te ...
- Windows7自定义主题
一.破解主题限制 Windows系统默认只能允许用户使用系统自带主题(非壁纸),即使用户安装了第三方主题,Windows也会限制很多地方,导致第三方主题用起来怪怪的. 故此,想要一个可以自定义主题的W ...
- appium---webview(H5)元素定位
我们在做UI自动化的时候,肯定需要元素定位,那么webview(H5)的元素怎么定位呢? webview定位方法 方法一: 1.打开chrome浏览器,输入chrome://inspect 2.连接手 ...
- 2.springboot------微服务
什么是微服务? 微服务是一种架构风格,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合:可以通过http的方式进行互通.要说微服务架构,先得说说过去我们的单体应用架构. 单体应用架 ...
- javaFx中Image的路径问题
网络图像文件前面加“http://”,而本地文件则要加“file:”.将源代码改为: Image image = new Image("file:image/qq.jpg"); I ...
- Hdu6586 String 字符串字典序贪心
Hdu6586 字符串字典序贪心 题意 给出一个只包含26个字符的字符串(|S|<=1e5),要求从中取出长度为k的字典序最小的组序列,满足所给的26个字母的限制条件,例如\([l_i,r_i] ...
- Go_Redis
Redis介绍 Redis是一个开源的内存数据库,Redis提供了多种不同类型的数据结构,很多业务场景下的问题都可以很自然地映射到这些数据结构上.除此之外,通过复制.持久化和客户端分片等特性,我们可以 ...
- 【Python】摄氏度与华氏度互相转化
Python入门程序,大家可以举一反三,进行各种转换,比如单位转化,货币转化等等,自行发挥即可! 原理: 代码: Tempstr=input("请输入带有符号的温度值:\n")# ...
- [HDU5382]GCD?LCM!
Description HDU5382 会吗?不会! 设\(F(n)=\sum\limits_{i = 1}^{n}\sum\limits_{j=1}^{n}[lcm(i,j)+gcd(i,j)\ge ...