寫匯編之前,需要搞清楚C語言代碼的寫法,這里以最簡單的算法舉例說明
C代碼如下:
#include <stdio.h> void main(){ int i,j; int count=1; for(i=2;i<=100;i++) { for(j=2;j<i/2;j++) { if(i%j==0) { count=0; break; } } if(count == 1) { printf("%d\n",i); } count = 1; } }
由於C語言中使用的是for進行循環,使用VC調試匯編時,發現for匯編的jmp需要具體地址才可以進行,對於程序來講不方便
然后查找資料,匯編中可以使用loop循環,因此,先實現一個loop循環
#include <stdio.h> void main(){ //test loop _asm{ mov ax,2 mov cx,11 s:add ax,ax loop s }; }
進一步,我們在loop循環里面加上printf輸出語句
#include <stdio.h> void main(){ int i=0xA; // dword ptr [ebp-4],0Ah int j=0xB; // dword ptr [ebp-8],0Bh int count=0; // dword ptr [ebp-0Ch],1 //第一個循環start _asm{ mov eax,2 // i=2 mov ecx,9 // i<100 loop1: // 開始循環1 mov i,eax // 保存i push eax // push eax和ecx到堆棧,是因為程序調用printf函數后,會改變ecx的值,所以需要先記錄下來,再通過pop ecx和eax還原原來的eax和ecx的值 push ecx }; printf("\n\n第一層循環i=%d\n",i); //第一個循環end _asm{ pop ecx pop eax add eax,1 // i++ loop loop1 }; printf("ssssssssss"); }
在此基礎上,我們
再實現一個loop循環里面嵌入一個loop循環,即可達到for循環里面嵌套for循環的目的
#include <stdio.h> void main(){ int i=0xA; // dword ptr [ebp-4],0Ah int j=0xB; // dword ptr [ebp-8],0Bh int count=0; // dword ptr [ebp-0Ch],1 //第一個循環start _asm{ mov eax,2 // i=2 mov ecx,9 // i<100 loop1: // 開始循環1 mov i,eax // 保存i push eax // push eax和ecx到堆棧,是因為程序調用printf函數后,會改變ecx的值,所以需要先記錄下來,再通過pop ecx和eax還原原來的eax和ecx的值 push ecx }; printf("\n\n第一層循環i=%d\n",i); //第二個循環start _asm{ mov eax,2 // j=2 mov ecx,i // j<i sub ecx,1 // j=i-2 loop2: // 開始循環2 mov j,eax // 保存j push eax // push eax和ecx到堆棧,是因為程序調用printf函數后,會改變ecx的值,所以需要先記錄下來,再通過pop ecx和eax還原原來的eax和ecx的值 push ecx }; printf("j=%d\t",j); //第二個循環end _asm{ pop ecx pop eax add eax,1 // j++ loop loop2 }; //第一個循環end _asm{ pop ecx pop eax add eax,1 // i++ loop loop1 }; printf("ssssssssss"); }
最后在循環過程中,加上是否為素數的判斷if語句,即可簡單實現C語言與匯編的嵌入式編程。
改造后的代碼:
#include <stdio.h> void main(){ int i=0xA; // dword ptr [ebp-4],0Ah int j=0xB; // dword ptr [ebp-8],0Bh int count=0; // dword ptr [ebp-0Ch],1 //第一個循環start _asm{ mov eax,2 // i=2 mov ecx,99 // i<100 loop1: // 開始循環1 mov i,eax // 保存i push eax // push eax和ecx到堆棧,是因為程序調用printf函數后,會改變ecx的值,所以需要先記錄下來,再通過pop ecx和eax還原原來的eax和ecx的值 push ecx }; printf("\n\n第一層循環i=%d\n",i); //第二個循環start _asm{ mov eax,2 // j=2 mov ecx,i // j<i sub ecx,1 // j=i-2 loop2: // 開始循環2 mov j,eax // 保存j push eax // push eax和ecx到堆棧,是因為程序調用printf函數后,會改變ecx的值,所以需要先記錄下來,再通過pop ecx和eax還原原來的eax和ecx的值 push ecx }; //判斷是否為素數 if(i%j==0) { count+=1; } /* _asm{ //if(i%j==0) mov eax,i cdq idiv eax,j test edx,edx jne loop2+2Ah (0040d822) //{ //count+=1; mov edx,dword ptr [ebp-0Ch] add edx,1 mov dword ptr [ebp-0Ch],edx //} }*/ printf("j=%d,count=%d\t",j,count); //第二個循環end _asm{ pop ecx pop eax add eax,1 // j++ loop loop2 }; if(count ==1) { printf("%d是素數\n",j); } count =0; //第一個循環end _asm{ pop ecx pop eax add eax,1 // i++ loop loop1 }; printf("ssssssssss"); }
最后,還可以將if,printf等轉換為匯編
總結下思路;
1、先用C語言寫好一個算法程序
2、使用loop代替for循環
3、在loop循環中加入printf輸出語句,實現循環變量值得打印
4、在loop循環中嵌入loop循環
5、加上判斷等其他語句
6、再將第5步的判斷等其他語句再統一轉換成匯編代碼。