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=0; int b=0; char *str1="a=%d,b=%d\n"; printf("++++++\n"); a=2; b=3; 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=0; int b=0; char *str1="a=%d,b=%d\n"; printf("++++++\n"); _asm{ //a=2 mov a,2 //b=3 mov b,3 //printf(str1,a,b); mov ecx,b push ecx mov eax,a push eax mov edx,str1 push edx call printf add esp,12 //swap(&a,&b); lea eax,b push eax lea ecx,a push ecx call swap add esp,8 //printf(str1,a,b); mov ecx,b push ecx mov eax,a push eax mov edx,str1 push edx call printf add esp,12 } }
现在需要将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+8] mov ecx,dword ptr [eax] mov dword ptr [ebp-4],ecx mov edx,dword ptr [ebp+8] 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-4] 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=0; int b=0; char *str1="a=%d,b=%d\n"; printf("++++++\n"); _asm{ //a=2 mov a,2 //b=3 mov b,3 //printf(str1,a,b); mov ecx,b push ecx mov eax,a push eax mov edx,str1 push edx call printf add esp,12 //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+8] mov ecx,dword ptr [eax] mov dword ptr [ebp-4],ecx mov edx,dword ptr [ebp+8] 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-4] mov dword ptr [edx],eax pop edi pop esi pop ebx mov esp,ebp pop ebp add esp,8 //printf(str1,a,b); mov ecx,b push ecx mov eax,a push eax mov edx,str1 push edx call printf add esp,12 } }
3、调整替换的swap汇编
#include<stdio.h> main(){ int a=0; int b=0; char *str1="a=%d,b=%d\n"; printf("++++++\n"); _asm{ //a=2 mov a,2 //b=3 mov b,3 //printf(str1,a,b); mov ecx,b push ecx mov eax,a push eax mov edx,str1 push edx call printf add esp,12 //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-4],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-4] //取temp的值2 mov dword ptr [edx],eax //b=temp=2 pop edi pop esi pop ebx mov esp,ebp pop ebp add esp,8 //printf(str1,a,b); mov ecx,b push ecx mov eax,a push eax mov edx,str1 push edx call printf add esp,12 } }
完成!