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 语言嵌入式系统编程修炼之一:背景篇 不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力.无疑,汇编语言具备这样的特质.但是,归因于汇编语言 ...
随机推荐
- SQL With As的用法
WITH AS,也叫子查询部分(subquery factoring),可以定义一个SQL片断,该SQL片断会被整个SQL语句用到.可以使SQL语句的可读性更高,也可以在UNION ALL的不同部分, ...
- (转)数据索引BTree
.B-tree 转自:http://blog.csdn.net/hbhhww/article/details/8206846 B-tree又叫平衡多路查找树.一棵m阶的B-tree (m叉树)的特性如 ...
- mac环境下,pycharm2018 配置 anaconda。
2018版的pycharm与之前的版本在配置anaconda上流程略有不同.直接上图 1.新建工程,展开会看到系统默认的编译环境名叫virtualenv,是基于python3.5的环境(如果没有安装过 ...
- DoS攻击种类
DoS攻击有许多种类,主要有Land攻击.死亡之ping.泪滴.Smurf攻击及SYN洪水等. 据统计,在所有黑客攻击事件中,syn洪水攻击是最常见又最容易被利用的一种DoS攻击手法. 1.攻击原理 ...
- dict 字典合并
实例 1 : 使用 update() 方法,第二个参数合并第一个参数 def Merge(dict1, dict2): return(dict2.update(dict1)) 实例 2 : 使用 ...
- QT离线安装包
各个版本下载链接http://mirrors.ustc.edu.cn/qtproject/archive/qt http://www.qtcn.org/bbs/i.php
- 使用 NuGet 包管理器在 Visual Studio 中安装和管理包
https://docs.microsoft.com/zh-cn/nuget/consume-packages/install-use-packages-visual-studio 通过 Window ...
- 2.10 webdriver中 js 使用
来源: 使用Webdriver执行JS小结 http://lijingshou.iteye.com/blog/2018929 selenium常用的js总结 http://www.cnblogs. ...
- 计划任务:at和crontab
一.概述 作为一名运维人员,你经常需要将某些命令或脚本放入计划任务中去执行.例如,服务器在白天的访问量一般较大,而服务器在承受巨大访问压力的同时对其进行全备份是不合适的,这时候就可以考虑将备份工作放入 ...
- EAC3 enhanced channel coupling
Enhanced channel coupling是一种spatial coding 技术,在传统的channel coupling的基础上添加了phase compensation, de-corr ...