重学C---------第五节:常量
在程序运行过程中,其值不能被改变的量成为常量。
下面是符号常量的例子:
1 #include <stdio.h> 2 #define PRICE 30 //符号常量 3 void main() 4 { 5 int num,total; 6 num = 10; 7 total = num * PRICE; 8 printf("total= %d\n",total); 9 }
同样的,我们汇编代码瞅瞅
1 00401010 >|> \55 push ebp 2 00401011 |. 8BEC mov ebp, esp 3 00401013 |. 83EC 48 sub esp, 48 4 00401016 |. 53 push ebx 5 00401017 |. 56 push esi 6 00401018 |. 57 push edi 7 00401019 |. 8D7D B8 lea edi, dword ptr [ebp-48] 8 0040101C |. B9 12000000 mov ecx, 12 9 00401021 |. B8 CCCCCCCC mov eax, CCCCCCCC 10 00401026 |. F3:AB rep stos dword ptr es:[edi] 11 00401028 |. C745 FC 0A000>mov dword ptr [ebp-4], 0A ; num=10 12 0040102F |. 8B45 FC mov eax, dword ptr [ebp-4] 13 00401032 |. 6BC0 1E imul eax, eax, 1E ; price=0x1e 14 00401035 |. 8945 F8 mov dword ptr [ebp-8], eax 15 00401038 |. 8B4D F8 mov ecx, dword ptr [ebp-8] 16 0040103B |. 51 push ecx ; /<%d> 17 0040103C |. 68 1C204200 push 0042201C ; |format = "total= %d",LF,"" 18 00401041 |. E8 2A000000 call printf ; \printf 19 00401046 |. 83C4 08 add esp, 8 20 00401049 |. 5F pop edi 21 0040104A |. 5E pop esi 22 0040104B |. 5B pop ebx 23 0040104C |. 83C4 48 add esp, 48 24 0040104F |. 3BEC cmp ebp, esp 25 00401051 |. E8 9A000000 call _chkesp 26 00401056 |. 8BE5 mov esp, ebp 27 00401058 |. 5D pop ebp 28 00401059 \. C3 retn
我们用IDA来看看,这个PRICE在哪里?
1 int __cdecl main() 2 { 3 char v1; // [sp+Ch] [bp-48h]@1 4 int v2; // [sp+4Ch] [bp-8h]@1 5 int v3; // [sp+50h] [bp-4h]@1 6 7 memset(&v1, 0xCCCCCCCCu, 0x48u); 8 v3 = 10; 9 v2 = 300; 10 printf("total= %d\n", 300); 11 return _chkesp(); 12 }
我修改为
1 int __cdecl main() 2 { 3 char v1; // [sp+Ch] [bp-48h]@1 4 int total; // [sp+4Ch] [bp-8h]@1 5 int num; // [sp+50h] [bp-4h]@1 6 7 memset(&v1, 0xCCCCCCCCu, 0x48u); 8 num = 10; 9 total = 300; 10 printf("total= %d\n", 300); 11 return _chkesp(); 12 }
发现计算的过程没有了。还是看汇编代码吧:
1 main proc near 2 3 var_48= byte ptr -48h 4 total= dword ptr -8 5 num= dword ptr -4 6 7 push ebp 8 mov ebp, esp 9 sub esp, 48h 10 push ebx 11 push esi 12 push edi 13 lea edi, [ebp+var_48] 14 mov ecx, 12h 15 mov eax, 0CCCCCCCCh 16 rep stosd 17 mov [ebp+num], 0Ah 18 mov eax, [ebp+num] 19 imul eax, 30 20 mov [ebp+total], eax 21 mov ecx, [ebp+total] 22 push ecx 23 push offset aTotalD ; "total= %d\n" 24 call printf 25 add esp, 8 26 pop edi 27 pop esi 28 pop ebx 29 add esp, 48h 30 cmp ebp, esp 31 call __chkesp 32 mov esp, ebp 33 pop ebp 34 retn 35 main endp
我们再看看Release版的有什么变化-----主函数
1 00401000 /$ 68 2C010000 push 12C 2 00401005 |. 68 30704000 push 00407030 ; ASCII "total= %d",LF 3 0040100A |. E8 11000000 call 00401020 4 0040100F |. 83C4 08 add esp, 8 5 00401012 \. C3 retn
我们没有发现计算的过程,视乎在编译的过程中就完成了计算。
我们用IDA来看看
1 ; int __cdecl main(int argc, const char **argv, const char **envp) 2 _main proc near 3 push 12Ch 4 push offset Format ; "total= %d\n" 5 call _printf 6 add esp, 8 7 retn 8 _main endp
果然是这样。