C基础反汇编

冷不防 2023-02-16 04:06 178阅读 0赞

switch

switch性能高于if语句的原因在于在case值较为连续的时候会生成值连续的大表,用switch的参数减去第一个最小的case值,和最大值进行比较,小于等于的话在表的范围内寻址即可[ecx*4+0F44D04h] 。牺牲内存空间,提升效率,以空间换时间。有时间隔较大的还需要生成小表来记录大表的偏移量,省去大表的许多数据。小表记录偏移量的最大值为FF。

  1. int main(int argc, char *argv[])
  2. {
  3. switch (1)
  4. {
  5. case 1:
  6. printf("111111\n");
  7. break;
  8. case 2:
  9. printf("222222\n");
  10. break;
  11. case 3:
  12. printf("333333\n");
  13. break;
  14. case 4:
  15. printf("444444\n");
  16. break;
  17. case 5:
  18. printf("555555\n");
  19. break;
  20. default:
  21. break;
  22. }
  23. system("pause");
  24. return 0;
  25. }
  26. switch (1)
  27. 00F44C5E mov dword ptr [ebp-0C4h],1
  28. 00F44C68 mov eax,dword ptr [ebp-0C4h]
  29. 00F44C6E sub eax,1
  30. 00F44C71 mov dword ptr [ebp-0C4h],eax
  31. 00F44C77 cmp dword ptr [ebp-0C4h],4
  32. 00F44C7E ja $LN8+0Dh (0F44CD6h)
  33. 00F44C80 mov ecx,dword ptr [ebp-0C4h]
  34. 00F44C86 jmp dword ptr [ecx*4+0F44D04h]
  1. 什么时候会生成大表:case过少的时候并不生成大表(一般情况下,在vc与vs中,4case就可以生成大表了),而是类似于if的逐个比较,区别就是比较部分与每个的任务部分分开了。

    switch (1)

    1. {
    2. case 1:
    3. printf("111111\n");
    4. break;
    5. case 2:
    6. printf("222222\n");
    7. break;
    8. case 3:
    9. printf("333333\n");
    10. break;
    11. default:
    12. break;
    13. }

    switch (1)
    00B64C5E mov dword ptr [ebp-0C4h],1
    00B64C68 cmp dword ptr [ebp-0C4h],1
    00B64C6F je main+45h (0B64C85h)
    00B64C71 cmp dword ptr [ebp-0C4h],2
    00B64C78 je main+54h (0B64C94h)
    00B64C7A cmp dword ptr [ebp-0C4h],3
    00B64C81 je main+63h (0B64CA3h)
    00B64C83 jmp main+70h (0B64CB0h)

  2. 顺序不会影响生成大表:观察内存可以发现case数值顺序并不会影响到大表的生成,编译器会自动在大表内按照case值大小进行排序的。

    switch (1)

    1. {
    2. case 4:
    3. printf("444444\n");
    4. break;
    5. case 2:
    6. printf("222222\n");
    7. break;
    8. case 3:
    9. printf("333333\n");
    10. break;
    11. case 1:
    12. printf("111111\n");
    13. break;
    14. default:
    15. break;
    16. }

    0x00384CF4 ba 4c 38 00 9c 4c 38 00
    0x00384CFC ab 4c 38 00 8d 4c 38 00

  3. 值较大时是否生成大表:case数值较大时依然会生成大表。

    switch (101)

    1. {
    2. case 101:
    3. printf("101\n");
    4. break;
    5. case 102:
    6. printf("102\n");
    7. break;
    8. case 103:
    9. printf("103\n");
    10. break;
    11. case 104:
    12. printf("104\n");
    13. break;
    14. case 105:
    15. printf("105\n");
    16. break;
    17. case 106:
    18. printf("106\n");
    19. break;
    20. case 107:
    21. printf("107\n");
    22. break;
    23. case 108:
    24. printf("108\n");
    25. break;
    26. case 109:
    27. printf("109\n");
    28. break;
    29. default:
    30. break;
    31. }

    00F94C5E mov dword ptr [ebp-0C4h],65h
    00F94C68 mov eax,dword ptr [ebp-0C4h]
    00F94C6E sub eax,65h
    00F94C71 mov dword ptr [ebp-0C4h],eax
    00F94C77 cmp dword ptr [ebp-0C4h],8
    00F94C7E ja $LN12+0Dh (0F94D16h)
    00F94C84 mov ecx,dword ptr [ebp-0C4h]
    00F94C8A jmp dword ptr [ecx*4+0F94D44h]

  4. 保留最值,去掉两个case,就会发现空缺的case值在表中就会给出default的地址。
    如果给出的是101~109之间空缺的值的话就会跳转到表中给出的default的地址;
    如果是大于最大值的就会在和最大值比较的时候pass掉;
    如果小于最小值的时候减去一个101~109的最小值时也会跳到default,因为ja是无符号比较。

    switch (101)

    1. {
    2. case 101:
    3. printf("101\n");
    4. break;
    5. case 104:
    6. printf("104\n");
    7. break;
    8. case 105:
    9. printf("105\n");
    10. break;
    11. case 106:
    12. printf("106\n");
    13. break;
    14. case 107:
    15. printf("107\n");
    16. break;
    17. case 108:
    18. printf("108\n");
    19. break;
    20. case 109:
    21. printf("109\n");
    22. break;
    23. default:
    24. break;
    25. }

    00134C5E mov dword ptr [ebp-0C4h],65h
    00134C68 mov eax,dword ptr [ebp-0C4h]
    00134C6E sub eax,65h
    00134C71 mov dword ptr [ebp-0C4h],eax
    00134C77 cmp dword ptr [ebp-0C4h],8
    00134C7E ja $LN10+0Dh (0134CF4h)
    00134C80 mov ecx,dword ptr [ebp-0C4h]
    00134C86 jmp dword ptr [ecx*4+134D24h]

    0x00134D24 8d 4c 13 00 f4 4c 13 00
    0x00134D2C f4 4c 13 00 9c 4c 13 00
    0x00134D34 ab 4c 13 00 ba 4c 13 00
    0x00134D3C c9 4c 13 00 d8 4c 13 00
    0x00134D44 e7 4c 13 00 cc cc cc cc

  5. 何时生成小表:case值连续但有些间隔时。使用小表来记录大表的偏移量。但是小表最多也只能记录FF个偏移量。
    大表只列出有效的case和放在最后的default,而小表则列出所有case与间隔,case保持在大表中的偏移,间隔则给出在大表中default的偏移,即下面内存图中显示的08,而且显而易见的是最后一个给出的值时07,也就是最后一个case的值。
    大表一共8 + 1 = 9个有效地址。
    小表一共44个偏移量。

    switch (101)

    1. {
    2. case 101:
    3. printf("101\n");
    4. break;
    5. case 107:
    6. printf("107\n");
    7. break;
    8. case 108:
    9. printf("108\n");
    10. break;
    11. case 109:
    12. printf("109\n");
    13. break;
    14. case 111:
    15. printf("101\n");
    16. break;
    17. case 122:
    18. printf("107\n");
    19. break;
    20. case 133:
    21. printf("108\n");
    22. break;
    23. case 144:
    24. printf("109\n");
    25. break;
    26. default:
    27. break;
    28. }

    switch (101)
    00764C5E mov dword ptr [ebp-0C4h],65h
    00764C68 mov eax,dword ptr [ebp-0C4h]
    00764C6E sub eax,65h
    00764C71 mov dword ptr [ebp-0C4h],eax
    00764C77 cmp dword ptr [ebp-0C4h],2Bh
    00764C7E ja $LN11+0Dh (0764D0Eh)
    00764C84 mov ecx,dword ptr [ebp-0C4h]
    00764C8A movzx edx,byte ptr [ecx+764D60h]
    00764C91 jmp dword ptr [edx*4+764D3Ch]

    0x00764D3C 98 4c 76 00 a7 4c 76 00
    0x00764D44 b6 4c 76 00 c5 4c 76 00
    0x00764D4C d4 4c 76 00 e3 4c 76 00
    0x00764D54 f2 4c 76 00 01 4d 76 00
    0x00764D5C 0e 4d 76 00 00 08 08 08
    0x00764D64 08 08 01 02 03 08 04 08
    0x00764D6C 08 08 08 08 08 08 08 08
    0x00764D74 08 05 08 08 08 08 08 08
    0x00764D7C 08 08 08 08 06 08 08 08
    0x00764D84 08 08 08 08 08 08 08 07

  6. 如果case后是忽大忽小毫不连续的值时,不做讨论。

    switch (101)

    1. {
    2. case 101:
    3. printf("101\n");
    4. break;
    5. case 1:
    6. printf("107\n");
    7. break;
    8. case 108:
    9. printf("108\n");
    10. break;
    11. case 2:
    12. printf("109\n");
    13. break;
    14. case 111:
    15. printf("101\n");
    16. break;
    17. case 1231:
    18. printf("107\n");
    19. break;
    20. case 9999:
    21. printf("108\n");
    22. break;
    23. case 10:
    24. printf("109\n");
    25. break;
    26. default:
    27. break;
    28. }

    switch (101)
    00754C5E mov dword ptr [ebp-0C4h],65h
    00754C68 cmp dword ptr [ebp-0C4h],6Ch
    00754C6F jg main+6Ah (0754CAAh)
    00754C71 cmp dword ptr [ebp-0C4h],6Ch
    00754C78 je main+0ABh (0754CEBh)
    00754C7A mov eax,dword ptr [ebp-0C4h]
    00754C80 sub eax,1
    00754C83 mov dword ptr [ebp-0C4h],eax
    00754C89 cmp dword ptr [ebp-0C4h],64h
    00754C90 ja $LN11+0Dh (0754D43h)
    00754C96 mov ecx,dword ptr [ebp-0C4h]
    00754C9C movzx edx,byte ptr [ecx+754D84h]
    00754CA3 jmp dword ptr [edx*4+754D70h]
    00754CAA cmp dword ptr [ebp-0C4h],6Fh
    00754CB1 je main+0C9h (0754D09h)
    00754CB3 cmp dword ptr [ebp-0C4h],4CFh
    00754CBD je main+0D8h (0754D18h)
    00754CBF cmp dword ptr [ebp-0C4h],270Fh
    00754CC9 je main+0E7h (0754D27h)
    00754CCB jmp $LN11+0Dh (0754D43h)

发表评论

表情:
评论列表 (有 0 条评论,178人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C基础汇编

    switch switch性能高于if语句的原因在于在case值较为连续的时候会生成值连续的大表,用switch的参数减去第一个最小的case值,和最大值进行比较,小于等

    相关 汇编-objdump

    windows下完成objdump需要用到:反汇编的目标镜像、镜像生成的本地编译器(.exe),相关指令如下。 > 反汇编命令: > > 1. 编译器路径,例:D:\

    相关 汇编

    从代码到最终可执行文件,要经过预处理、编译、汇编、链接四个过程: 1.预处理:对程序进行简单的处理,比如头文件包含展开 2.编译:汇编语言编译器用汇编语言来翻译文件

    相关 汇编工具

    最近上网络编程这门课,孙老师给我们介绍了下反汇编相关工具,让我对反汇编有了一个基本的认识,算是增长见识了。大概介绍了三个工具: 1.source insight 此工具为查