重学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

果然是这样。

 

工程下载地址:https://files.cnblogs.com/tk091/rl005.7z

posted @ 2012-05-03 22:31  r3call  阅读(205)  评论(0编辑  收藏  举报