1.1 全局变量引发的故事

1.1.1 剖析赋值语句机器码

  1. int gi;
  2. void main(int argc, char* argv[]){
  3. gi = 12; // 断点, 调试
  4. }

编译器VS2022

Debug->Windows->反汇编(Disassembly): Alt+F8
image.png

  1. 0053173F int 3
  2. 1-1.exe!_JustMyCode_Default(void):
  3. 00531740 push ebp
  4. 00531741 mov ebp,esp
  5. 00531743 pop ebp
  6. 00531744 ret
  7. 00531745 int 3
  8. 00531746 int 3
  9. 00531747 int 3
  10. 00531748 int 3
  11. 00531749 int 3
  12. 0053174A int 3
  13. 0053174B int 3
  14. 0053174C int 3
  15. 0053174D int 3
  16. 0053174E int 3
  17. 0053174F int 3
  18. --- C:\Users\XXX\Desktop\OldCoder\01\1-1\1-1.c ------------------------
  19. // 1-1.cpp : This file contains the 'main' function. Program execution begins and ends there.
  20. //
  21. int gi;
  22. int main()
  23. {
  24. 00531750 push ebp
  25. 00531751 mov ebp,esp
  26. 00531753 sub esp,0C0h
  27. 00531759 push ebx
  28. 0053175A push esi
  29. 0053175B push edi
  30. 0053175C mov edi,ebp
  31. 0053175E xor ecx,ecx
  32. 00531760 mov eax,0CCCCCCCCh
  33. 00531765 rep stos dword ptr es:[edi]
  34. 00531767 mov ecx,offset _2FFE3A17_1-1@c (053C000h)
  35. 0053176C call @__CheckForDebuggerJustMyCode@4 (0531307h)
  36. gi = 12;
  37. 00531771 mov dword ptr [gi (053A57Ch)],0Ch
  38. }
  39. 0053177B xor eax,eax
  40. 0053177D pop edi
  41. 0053177E pop esi
  42. 0053177F pop ebx
  43. 00531780 add esp,0C0h
  44. 00531786 cmp ebp,esp
  45. 00531788 call __RTC_CheckEsp (0531230h)
  46. 0053178D mov esp,ebp
  47. 0053178F pop ebp
  48. 00531790 ret
  49. --- No source file -------------------------------------------------------------
  • 内存地值用十六进制表示
  • 十六进制一般以h(或H)结尾, 反汇编中一般省略

    1. 0053176C call @__CheckForDebuggerJustMyCode@4 (0531307h)
    2. gi = 12;
    3. 00531771 mov dword ptr [gi (053A57Ch)],0Ch
  • 00531771是赋值指令mov的存放地址

为什么在汇编语言中会出现gi? VS为了帮助开发者理解, 将操作对应的符号名也显示在语句中
选择暂时将显示符号名(Show Symbol Names)从反汇编语句中去除, 就会看到纯正的汇编语句了
image.png

  1. 0053176C call 00531307
  2. gi = 12;
  3. 00531771 mov dword ptr ds:[0053A57Ch],0Ch

mov指令将0Ch赋值给内存, 即0053A57Ch

  • 0Ch: C即十进制的12
  • mov [地址值], 存储值
  • ds: 数据段寄存器

对于x64

  1. 1-1.exe!__JustMyCode_Default(void):
  2. 00007FF77DC11740 ret 0
  3. 00007FF77DC11743 int 3
  4. 00007FF77DC11744 int 3
  5. 00007FF77DC11745 int 3
  6. 00007FF77DC11746 int 3
  7. 00007FF77DC11747 int 3
  8. 00007FF77DC11748 int 3
  9. 00007FF77DC11749 int 3
  10. 00007FF77DC1174A int 3
  11. 00007FF77DC1174B int 3
  12. 00007FF77DC1174C int 3
  13. 00007FF77DC1174D int 3
  14. 00007FF77DC1174E int 3
  15. 00007FF77DC1174F int 3
  16. --- C:\Users\XXX\Desktop\OldCoder\01\1-1\1-1.c ------------------------
  17. // 1-1.cpp : This file contains the 'main' function. Program execution begins and ends there.
  18. //
  19. int gi;
  20. int main()
  21. {
  22. 00007FF77DC11750 push rbp
  23. 00007FF77DC11752 push rdi
  24. 00007FF77DC11753 sub rsp,0E8h
  25. 00007FF77DC1175A lea rbp,[rsp+20h]
  26. 00007FF77DC1175F lea rcx,[00007FF77DC21000h]
  27. 00007FF77DC11766 call 00007FF77DC11343
  28. gi = 12;
  29. 00007FF77DC1176B mov dword ptr [00007FF77DC1C8C8h],0Ch
  30. }
  31. 00007FF77DC11775 xor eax,eax
  32. 00007FF77DC11777 lea rsp,[rbp+00000000000000C8h]
  33. 00007FF77DC1177E pop rdi
  34. 00007FF77DC1177F pop rbp
  35. 00007FF77DC11780 ret
  36. --- No source file -------------------------------------------------------------
  • 内存0053A57Ch真的是gi的地址吗?
  • mov指令真的放在内存00531771地址中吗?
  1. 0079176C call @__CheckForDebuggerJustMyCode@4 (0791307h)
  2. 4: gi = 12;
  3. 00791771 mov dword ptr [gi (079A57Ch)],0Ch

打印gi的地址

  1. #include <stdio.h>
  2. int gi;
  3. void main(int argc, char* argv[]) {
  4. gi = 12;
  5. printf("gi address=%p\n", &gi);
  6. // printf("gi address=%x\n", &gi);
  7. }

GCC