编写一个两数交换函数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. CentOS7利用docker安装MySQL5.7

    CentOS7利用docker安装MySQL5.7 前提条件 centos7 且内核版本高于3.10, 可通过以下命令查看内核版本 uname -r 利用yum 安装docker 安装一些必要的系统工 ...

  2. C语言输入一个整数转化为字符串

    将数字转化为对应的字符,可以通过n%10+48来实现,也可以通过n%10+'0'来实现,因为‘0’的ASCII码的数值就是48 因为字符串‘0’ 对应的10进制 整数是48 字符串'9'对应的10进制 ...

  3. C#源码转PlantUml

    1.下载编译开源工程PlantUmlClassDiagramGenerator 2.使用PlantUmlClassDiagramGenerator生成PlantUml文件 3.配置Vscode的Pla ...

  4. StringBuilder与String的区别

    String 在进行运算时(如赋值.拼接等)会产生一个新的实例,而 StringBuilder 则不会.所以在大量字符串拼接或频繁对某一字符串进行操作时最好使用 StringBuilder,不要使用  ...

  5. 普及C组第四题(8.18)

    1574. [提高]X-因子链 (File IO): input:factor.in output:factor.out 时间限制: 1000 ms  空间限制: 131072 KB 题目描述 给一个 ...

  6. C++-POJ1067-取石子游戏

    //(ak,bk)=([k*(1+sqrt(5))/2],[k*(1+sqrt(5))/2]+k)=(ak,ak+k) #include <cstdio> double sqrt5=2.2 ...

  7. 「模板」Splay

    代码说明 对于一些变量进行说明: 变量名 说明 rt 树根 ff[u] 点 \(u\) 的父节点,特别地, ff[rt]=0 ch[u][0|1] 点 \(u\) 的 左/右儿子 siz[u] 点 \ ...

  8. requests.packages.urllib3.exceptions.ProxySchemeUnknown: Not supported proxy scheme

    python3 -m pip install -U requests[socks]

  9. Django_第三方

    1. 验证码 2. 绘制过程 加一个随机数用于更新验证码 不加,图片的src不会更新,图片也不会更新 加了,url也能匹配上,去执行视图函数 3. 富文本 就是带着样式的文本 3.1 使用

  10. 配置yum仓库:yum install 软件

    1.一个重要模板: 进入/etc/yum.repos.d文件夹,新建一个xiaoxu.repo文件,其中xiaoxu可以根据需要来取名. [模板] vim  xiaoxu.repo [rhel]    ...