Python视频微信订餐小程序课程视频
https://edu.csdn.net/course/detail/36074
Python实战量化交易理财系统
https://edu.csdn.net/course/detail/35475 注:本文的所有代码都在我自己身上VS由于环境的不同,2008年测试的所有编译器都无法保证运行。
在C 中,可通过__asm将汇编语言嵌入关键字。
int main(){ \_\_asm{//汇编! mov eax,0 } return 0; } 我们知道,在C 中,可用printf输出函数。cout,运算符重载等技术在这里使用不方便)
提示:在汇编中,调用函数的指令称为CALL。函数参数保存在栈中。
然后我们就可以开始写了。首先,让我们看看C 正常版:
#include #include const char *s1="Hello, World\n",*s2="pause"; int main(){ printf(s1); system(s2); return 0; } 为了方便起见,我们首先汇编正常版本,结果如下:
printf(s1); 00BD13CE mov esi,esp 00BD13D0 mov eax,dword ptr [s1 (0BD7038h)] 00BD13D5 push eax 00BD13D6 call dword ptr [\_\_imp\_\_printf (0BD82C4h)] 00BD13DC add esp,4 00BD13DF cmp esi,esp 00BD13E1 call @ILT 315(\_\_RTC\_CheckEsp) (0BD1140h) 第一句,mov esi,esp 第二句是为了检查后面的栈是否正常使用,mov eax,dword ptr[s1] 括号中的0BD7038h是地址,别管他,就是把地址放在上面eax中去第三句,push eax 把刚才放进eax将地址放入栈中, 其实就是把参数放在栈里
第四句,call dword ptr [__imp__printf]__imp__printf是printf函数编译后的结果,从下划线开始表示这是一个函数,我们通常直接写内联汇编printf即可
第五句,add esp,4其实是手动平栈,之前在栈里放了4字节s1,现在把esp指针是栈顶指针下移(栈从高地址到低地址)
不管最后两句,都是保证esi和esp相等,因为之前手动平栈,结合第一句,这里应该是相等的,不写也没关系
最终的内联汇编应该是这样的:
#include #include const char *s1="Hello, World\n",*s2="pause"; int main(){ \_asm{ mov eax,dword ptr [s1] push eax call dword ptr [printf] add esp,4 mov eax,dword ptr[s2] push eax call dword ptr [system] add esp,4 } return 0; } 运行结果正常。
A B同时使用问题scanf和printf
首先,请注意,函数的参数倒置存储在堆栈中。(注:这个C标准没有规定,但汇编语言本身非常依赖于环境,所以暂时忽略它)
例如
scanf("%d %d",&a,&b); 如果翻译成汇编,应该是这样的(以下是伪代码)
push &b push &a push "%d %d" call scanf 然后我们就可以开始写了。
scanf注意前两个参数。由于地址被放置,因此不能使用MOV使用指令LEA指令
lea eax,[a] 把a的地址放进去eax中。
其它部分并不难,注意最后的平栈,add esp加多少,加上每个参数的大小。
例如scanf,每个地址都是4字节,总共是12字节。
完整代码
#include #include const char *s1="%d%d",*s2="%d\n",*s3="pause"; int a,b; int main(){ \_asm{ lea eax,[b] push eax lea eax,[a] push eax mov eax,dword ptr [s1] push eax call dword ptr [scanf] add esp,12 mov eax,[a] add eax,[b] push eax mov eax,dword ptr [s2] push eax call dword ptr [printf] add esp,8 mov eax,dword ptr [s3] push eax call dword ptr [system] add esp,4 } return 0; }