写一个简单的c语言程序并用反汇编工具得到其汇编代码,对其汇编代码进行注释解释。
要求:程序中要包含加减乘除基本运算。
以下是我选取的C语言程序
#include
int solve(int a,int b,int c)
{
int result = 0;
a = 4*a;
b = 7+b;
c = c / 2;
if (result < a){
result = a;
}
if(result < b){
result = b;
}
if (result < c){
result = c;
}
return result;
}
int main(void)
{
printf("请输入三个数据(a,b,c):\n");
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
a = solve(a,b,c);
printf("4*a,7+b,c/2中最大是:%d\n",a);
return 0;
}
以下是我认为的汇编代码的意思。
注释即为我对代码的理解。希望大家认真思考,不到最后一刻不要放弃。
1:
2: #include
3:
4: int solve(int a,int b,int c)
5: {
00401020 push ebp ;保存ebp的值,在这个函数中要用这个寄存器
00401021 mov ebp,esp ;获得栈顶指针的位置
00401023 sub esp,44h ;腾出位置在这个函数中使用
00401026 push ebx ;保护现场
00401027 push esi ;保护现场
00401028 push edi ;保护现场
00401029 lea edi,[ebp-44h] ;获得刚才分配的空间的栈顶指针
0040102C mov ecx,11h ;将要循环填充的次数
00401031 mov eax,0CCCCCCCCh ;要循环填充的数值
00401036 rep stos dword ptr [edi] ;循环填充刚才分配的空间
6: int result = 0;
00401038 mov dword ptr [ebp-4],0 ;保存临时变量
7: a = 4*a;
0040103F mov eax,dword ptr [ebp+8] ;取出第一个参数
00401042 shl eax,2 ;参数左移两位,即乘以四
00401045 mov dword ptr [ebp+8],eax ;保存结果
8: b = 7+b;
00401048 mov ecx,dword ptr [ebp+0Ch] ;取出计算参数
0040104B add ecx,7 ;参数加7
0040104E mov dword ptr [ebp+0Ch],ecx ;保存结果
9: c = c / 2;
00401051 mov eax,dword ptr [ebp+10h] ;取出计算参数
00401054 cdq
00401055 sub eax,edx ;eax-edx
00401057 sar eax,1 ;右移一位,相当于除以二
00401059 mov dword ptr [ebp+10h],eax ;保存结果
10: if (result < a){
0040105C mov edx,dword ptr [ebp-4] ;取出临时变量
0040105F cmp edx,dword ptr [ebp+8] ;比较大小
00401062 jge solve+4Ah (0040106a) ;如果大于等于就跳转
11: result = a;
00401064 mov eax,dword ptr [ebp+8] ;小于就取出a的值
00401067 mov dword ptr [ebp-4],eax ;赋值给临时变量,入栈
12: }
13: if(result < b){
0040106A mov ecx,dword ptr [ebp-4] ;取出临时变量
0040106D cmp ecx,dword ptr [ebp+0Ch] ;比较大小
00401070 jge solve+58h (00401078) ;如果大于等于就跳转
14: result = b;
00401072 mov edx,dword ptr [ebp+0Ch] ;小于就取出b的值
00401075 mov dword ptr [ebp-4],edx ;赋值给临时变量,入栈
15: }
16: if (result < c){
00401078 mov eax,dword ptr [ebp-4] ;取出临时变量
0040107B cmp eax,dword ptr [ebp+10h] ;比较大小
0040107E jge solve+66h (00401086) ;如果大于等于就跳转
17: result = c;
00401080 mov ecx,dword ptr [ebp+10h] ;小于就取出c的值
00401083 mov dword ptr [ebp-4],ecx ;赋值给临时变量,入栈
18: }
19: return result;
00401086 mov eax,dword ptr [ebp-4] 把结果保存到eax中
20: }
00401089 pop edi ;恢复现场
0040108A pop esi ;恢复现场
0040108B pop ebx ;恢复现场
0040108C mov esp,ebp ;恢复现场
0040108E pop ebp ;恢复现场
0040108F ret ;返回主函数
21:
22: int main(void)
23: {
004010B0 push ebp ;保存ebp寄存器的值,保护现场
004010B1 mov ebp,esp ;取出esp中的值给ebp调用
004010B3 sub esp,4Ch ;esp地址减少4cH个字节,用来临时存放数据
004010B6 push ebx ;保存ebx寄存器的值,保护现场
004010B7 push esi ;保护现场
004010B8 push edi ;保护现场
004010B9 lea edi,[ebp-4Ch] ;找到存放临时数据的栈顶位置
004010BC mov ecx,13h ;循环次数
004010C1 mov eax,0CCCCCCCCh ;临时空间中数据的默认值
004010C6 rep stos dword ptr [edi] ;重复往栈中填入默认值
24: printf("请输入三个数据(a,b,c):\n");
004010C8 push offset string "\xc7\xeb\xca\xe4\xc8\xeb\xc8\xfd\xb8\xf6\xca\xfd\xbe\xdd(a,b,c)\xa3\xba\n
;把字符串的首地址入栈
004010CD call printf (004011b0) ;调用printf函数
004010D2 add esp,4 ;栈指针下移四个字节,跳过上一个函数的传入参数
25: int a, b, c;
26: scanf("%d %d %d", &a, &b, &c);
004010D5 lea eax,[ebp-0Ch] ;分配一个临时空间给变量,取得其首地址
004010D8 push eax ;寄存器将取得的地址入栈
004010D9 lea ecx,[ebp-8] ;同上
004010DC push ecx
004010DD lea edx,[ebp-4];同上
004010E0 push edx
004010E1 push offset string "%d %d %d" (00425028) ;将要用的字符串首地址入栈
004010E6 call scanf (00401150) ;调用输入函数
004010EB add esp,10h ;跳过之前用栈传递的参数
27: a = solve(a,b,c);
004010EE mov eax,dword ptr [ebp-0Ch] ;把之前保存在栈中的结果取出来
004010F1 push eax ;入栈
004010F2 mov ecx,dword ptr [ebp-8] ;同上
004010F5 push ecx
004010F6 mov edx,dword ptr [ebp-4];同上
004010F9 push edx
004010FA call @ILT+0(solve) (00401005) ;调用自己写的求最大值的函数
004010FF add esp,0Ch ;跳过函数参数
00401102 mov dword ptr [ebp-4],eax ;将返回值保存起来
28: printf("4*a,7+b,c/2中最大是:%d\n",a);
00401105 mov eax,dword ptr [ebp-4] ;把要输出的数取出来
00401108 push eax ;入栈
00401109 push offset string "4*a,7+b,c/2\xd6\xd0\xd7\xee\xb4\xf3\xca\xc7\xa3\xba%d\n" (00426028) ;要输出的字符串
0040110E call printf (004011b0) ;调用打印函数
00401113 add esp,8 ;跳过函数参数
29: return 0;
00401116 xor eax,eax ;eax清零
30: }
00401118 pop edi
00401119 pop esi
0040111A pop ebx
0040111B add esp,4Ch
0040111E cmp ebp,esp
00401120 call __chkesp (00401230)
00401125 mov esp,ebp
00401127 pop ebp
00401128 ret