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 语言嵌入式系统编程修炼之一:背景篇 不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力.无疑,汇编语言具备这样的特质.但是,归因于汇编语言 ...
随机推荐
- 第一篇 网站基础知识 第3章 DNS的设置
第3章 DNS的设置 3.1 DNS解析 3.2 Windows 7设置DNS服务器 3.3Windows设置本机域名和IP的对应关系 在自己的电脑里也可以设置域名和IP的对应关系,具体设置是在C:\ ...
- ubuntu安装搜狗输入
百度搜索搜狗输入ubuntu找到官网地址 下载deb包 sogoupinyin_2.3.1.0112_amd64.deb 上传 dkpkg -i sogoupinyin_2.3.1.0112_a ...
- Educational Codeforces Round 76 (Rated for Div. 2) C. Dominated Subarray
Let's call an array tt dominated by value vv in the next situation. At first, array tt should have a ...
- DFA 简易正则表达式匹配
一个只能匹配非常简单的(字母 . + *)共 4 种状态的正则表达式语法的自动机(注意,仅限 DFA,没考虑 NFA): 好久之前写的了,记得有个 bug 一直没解决... #include < ...
- spring cloud config 连接GitHub访问 报错 Cannot clone or checkout repository
原因是建立仓库的时候将仓库私有化了,将仓库公有 或者 设置账号密码即可!
- c#项目调用Python模块的方法
将Python模块用pyinstaller打包成exe程序 下载安装UPX((http://upx.sourceforge.net/)) ,并把路径加到环境变量中. UPX是开源的加壳和压缩exe的程 ...
- 计算机网络 - TCP_NODELAY 和 TCP_CORK, TCP_NOPUSH
参考 https://www.cnblogs.com/biyeymyhjob/p/4670502.html https://stackoverflow.com/questions/3761276/wh ...
- PHP正则表达式常用例子
"^[0-9]*[1-9][0-9]*$" //正整数"^((-\d+)|(0+))$" //非正整数(负整数 + 0)"^-[0-9]*[1-9][ ...
- 网页域名在QQ内被多人投诉举报拦截的解决方案
背景 相信大家经常会遇到一个头疼的问题就是,明明自己的网页没有违规内容(比如线下活动的推广),但链接在QQ内转发分享会被QQ管家拦截,导致用户无法访问. 那么当大家遇到这个问题的时候应该怎么办呢?不用 ...
- Logarithmic-Trigonometric积分系列(一)
\[\Large\displaystyle \int_{0}^{\frac{\pi }{2}}x^{2}\ln\left ( \sin x \right )\ln\left ( \cos x \rig ...