鱼C论坛

 找回密码
 立即注册
查看: 1504|回复: 0

[技术交流] 分析编译器对变长数组的实现

[复制链接]
发表于 2014-11-27 18:04:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
分析编译器对变长数组的实现

#include <stdio.h>

int main(void)
{
    int n;
    scanf("%d", &n);      // 实验而已,输入n时,请输入大于3的数字
    int ar[n];
    ar[2] = 0xff00;
    printf("%d\n", ar[2]);
    printf("%p", ar);

    return 0;
}

以上代码经codeblocks13.12编译后(release版),使用od载入后(请结合栈的变化图来分析)

CPU Disasm
Address   Hex dump          Command                                       Comments
00401C2C  /$  8D4C24 04     lea     ecx, [esp+4]                          ; ecx = argc变量的地址,c中的main(argc, argv, env),argc为第一个参数
00401C30  |.  83E4 F0       and     esp, FFFFFFF0                         ; dqword (16.-byte) stack alignment
00401C33  |.  FF71 FC       push    dword ptr ds:[ecx-4]                  ; 返回地址再次压栈(如何获取函数返回后的地址?这就是方法)
00401C36  |.  55            push    ebp
00401C37  |.  89E5          mov     ebp, esp
00401C39  |.  53            push    ebx
00401C3A  |.  51            push    ecx                                   ; argc的地址压栈
00401C3B  |.  83EC 20       sub     esp, 20
00401C3E  |.  E8 ADFCFFFF   call    004018F0                              ; [cConsole.004018F0, 未分析出函数的目的
00401C43  |.  8D45 F4       lea     eax, [ebp-0C]
00401C46  |.  894424 04     mov     dword ptr ss:[esp+4], eax             ; /<%d> => offset LOCAL.4
00401C4A  |.  C70424 243040 mov     dword ptr ss:[esp], offset 00403024   ; |format => "%d"
00401C51  |.  E8 36FFFFFF   call    <jmp.&msvcrt.scanf>                   ; \MSVCRT.scanf
00401C56  |.  8B45 F4       mov     eax, dword ptr ss:[ebp-0C]
00401C59  |.  8D0485 120000 lea     eax, [eax*4+12]                       ; 准备为变长数组分配空间,有多0x12,但为啥是0x12?
00401C60  |.  83E0 F0       and     eax, FFFFFFF0                         ; 清空了低4位,即又保证了栈为16字节对齐
00401C63  |.  E8 C8FEFFFF   call    00401B30                              ; 检测变长数组的长度是否可能导致栈溢出, probes EAX bytes on stack
00401C68  |.  29C4          sub     esp, eax                              ; 为变长数组分配空间,在栈中分配的哦
00401C6A  |.  8D5C24 08     lea     ebx, [esp+8]                          ; 现开始,esp指向的就是变长数组的首元素的首地址,即esp指向了变长数组的第一个元素
00401C6E  |.  C74424 10 00F mov     dword ptr ss:[esp+10], 0FF00          ; 给ar[2]赋值0xff00
00401C76  |.  C74424 04 00F mov     dword ptr ss:[esp+4], 0FF00           ; /<%d> => 65280. 即0xff00 == 65280
00401C7E  |.  C70424 273040 mov     dword ptr ss:[esp], offset 00403027   ; |format => "%d\n"
00401C85  |.  E8 0AFFFFFF   call    <jmp.&msvcrt.printf>                  ; \MSVCRT.printf
00401C8A  |.  895C24 04     mov     dword ptr ss:[esp+4], ebx             ; /<%p>
00401C8E  |.  C70424 2B3040 mov     dword ptr ss:[esp], offset 0040302B   ; |format => "%p"
00401C95  |.  E8 FAFEFFFF   call    <jmp.&msvcrt.printf>                  ; \MSVCRT.printf
00401C9A  |.  31C0          xor     eax, eax
00401C9C  |.  8D65 F8       lea     esp, [ebp-8]                          ; 令esp指向argc
00401C9F  |.  59            pop     ecx                                   ; argc的地址出栈
00401CA0  |.  5B            pop     ebx
00401CA1  |.  5D            pop     ebp
00401CA2  |.  8D61 FC       lea     esp, [ecx-4]                          ; 令esp指向返回地址
00401CA5  \.  C3            retn

CPU Disasm
Address   Hex dump          Command                                       Comments
004018A0  /> /53            push    ebx
004018A1  |. |83EC 18       sub     esp, 18
004018A4  |. |8B1D C41C4000 mov     ebx, dword ptr ds:[401CC4]
004018AA  |. |83FB FF       cmp     ebx, -1
004018AD  |. |74 24         je      short 004018D3
004018AF  |> |85DB          test    ebx, ebx
004018B1  |. |74 0F         jz      short 004018C2
004018B3  |> |FF149D C41C40 /call    near dword ptr ds:[ebx*4+401CC4]
004018BA  |. |83EB 01       |sub     ebx, 1
004018BD  |. |8D76 00       |lea     esi, [esi]
004018C0  |.^|75 F1         \jnz     short 004018B3
004018C2  |> |C70424 701840 mov     dword ptr ss:[esp], 00401870          ; Entry point
004018C9  |. |E8 F2F9FFFF   call    004012C0
004018CE  |. |83C4 18       add     esp, 18
004018D1  |. |5B            pop     ebx
004018D2  |. |C3            retn
004018D3  |> |31DB          xor     ebx, ebx
004018D5  |. |EB 02         jmp     short 004018D9
004018D7  |> |89C3          /mov     ebx, eax
004018D9  |> |8D43 01       |lea     eax, [ebx+1]
004018DC  |. |8B1485 C41C40 |mov     edx, dword ptr ds:[eax*4+401CC4]
004018E3  |. |85D2          |test    edx, edx
004018E5  |.^|75 F0         \jnz     short 004018D7
004018E7  |.^|EB C6         jmp     short 004018AF
004018E9  |  |8DB426 000000 lea     esi, [esi]
004018F0  |$ |8B0D 24504000 mov     ecx, dword ptr ds:[405024]            ; cConsole.004018F0(guessed void)
004018F6  |. |85C9          test    ecx, ecx
004018F8  |. |74 06         jz      short 00401900
004018FA  |. |F3:C3         rep retn
004018FC  |  |8D7426 00     lea     esi, [esi]
00401900  |> |C705 24504000 mov     dword ptr ds:[405024], 1
0040190A  \.^\EB 94         jmp     short 004018A0

CPU Disasm
Address   Hex dump          Command                                       Comments
00401B30  /$  51            push    ecx
00401B31  |.  50            push    eax
00401B32  |.  3D 00100000   cmp     eax, 1000                             ; 0x1000==4096==4k,变长数组长度不可超过4k字节?非也!参考下面
00401B37  |.  8D4C24 0C     lea     ecx, [esp+0C]                         ; 可是此子程序并没有实现什么功能啊
00401B3B  |.  72 15         jb      short 00401B52
00401B3D  |>  81E9 00100000 /sub     ecx, 1000
00401B43  |.  8309 00       |or      dword ptr ds:[ecx], 00000000         ; 看似没有实现什么功能,实际上ecx不断减去4k,如果eax太大,则会使得ds:[ecx]进入操作系统数据区域,再进行写入数据时造成访问违例的异常!非常巧妙的技巧!
00401B46  |.  2D 00100000   |sub     eax, 1000
00401B4B  |.  3D 00100000   |cmp     eax, 1000
00401B50  |.^ 77 EB         \ja      short 00401B3D
00401B52  |>  29C1          sub     ecx, eax
00401B54  |.  8309 00       or      dword ptr ds:[ecx], 00000000
00401B57  |.  58            pop     eax
00401B58  |.  59            pop     ecx
00401B59  \.  C3            retn
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-25 11:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表