C&汇编基础-数据类型02
9unk Lv5

全局变量与局部变量

  1. 全局变量和局部变量表现形式

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "stdafx.h"
int g_n1;
int g_n2 = 0x12345678;

void Function1()
{
//读取全局变量
int x = g_n1;
int y = g_n2;
//写全局变量
g_n1 = 1;
g_n2 = 2;
}

int main(int argc, char* argv[])
{
Function1();
return 0;
}

反汇编

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
0040EBA0   push        ebp
0040EBA1 mov ebp,esp
0040EBA3 sub esp,48h
0040EBA6 push ebx
0040EBA7 push esi
0040EBA8 push edi
0040EBA9 lea edi,[ebp-48h]
0040EBAC mov ecx,12h
0040EBB1 mov eax,0CCCCCCCCh
0040EBB6 rep stos dword ptr [edi]

//********int x = g_n1;(读取全局变量)*****//
0040EBB8 mov eax,[g (00427958)]
0040EBBD mov dword ptr [ebp-4],eax

//********int y = g_n2;*****//
0040EBC0 mov ecx,dword ptr [g_n2 (00426a6c)]
0040EBC6 mov dword ptr [ebp-8],ecx

//********g_n1 = 1;(写全局变量)*****//
0040EBC9 mov dword ptr [g (00427958)],1

//********g_n2 = 2;*****//
0040EBD3 mov dword ptr [g_n2 (00426a6c)],2

0040EBDD pop edi
0040EBDE pop esi
0040EBDF pop ebx
0040EBE0 mov esp,ebp
0040EBE2 pop ebp
0040EBE3 ret

从全局变量和局部变量的表现形式来看:全局变量是一个内存地址;局部比变量是 [ebp-xxx]

全局变量可以从其他函数中进行读写

  1. 全局变量的初始值

1.jpg

2.jpg

全局变量如果不赋值时,它的初始值为 0

  1. 全局变量和局部变量的分配

3.jpg

4.jpg

局部变量默认不分配值,需要设定初始值。

全局变量可以看做是一个地址,它的位置是不会变的,同时也说明全局变量是在程序编译的时候就已经定好了位置。所以全局变量是在程序编译以后就已经预留空间,空间大小由类型决定,且位置不会发生变化。

局部变量是[ebp-xxx]形式,当每次调用函数的时候ebp都会变化,同时函数结束后函数内的数据都将会变成垃圾数据。所以局部变量只有当函数调用时才会分配空间,且一定要有初始值。

  1. 全局变量和局部变量的作用范围

5.jpg

这里编译的时候提示报错: i 是未定义的标识符,也就是函数 Function2() 找不到变量i

局部变量作用范围仅限于当前函数自己,其他函数无法使用

数据类型转换

有符号数小转大

  1. 源码

    1
    2
    3
    4
    5
    6
    7
    //有符号小转大
    void Function1()
    {
    char ci = 0xFF;
    short si = ci;
    int ni = ci;
    }
  2. 反汇编

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    0040EBA0   push        ebp
    0040EBA1 mov ebp,esp
    0040EBA3 sub esp,4Ch
    0040EBA6 push ebx
    0040EBA7 push esi
    0040EBA8 push edi
    0040EBA9 lea edi,[ebp-4Ch]
    0040EBAC mov ecx,13h
    0040EBB1 mov eax,0CCCCCCCCh
    0040EBB6 rep stos dword ptr [edi]

    //********char ci = 0xFF;*****//
    0040EBB8 mov byte ptr [ebp-4],0FFh

    //********short si = ci;*****//
    0040EBBC movsx ax,byte ptr [ebp-4]
    0040EBC1 mov word ptr [ebp-8],ax

    //********int ni = ci;*****//
    0040EBC5 movsx ecx,byte ptr [ebp-4]
    0040EBC9 mov dword ptr [ebp-0Ch],ecx

    0040EBCC pop edi
    0040EBCD pop esi
    0040EBCE pop ebx
    0040EBCF mov esp,ebp
    0040EBD1 pop ebp
    0040EBD2 ret

有符号小转大是通过 movsx 指令对变量进行扩展的。movsx 是先获取符号位,也就是二进制的最高位,然后再对扩展位进行填充。

无符号数小转大

  1. 源码

    1
    2
    3
    4
    5
    6
    7
    //无符号小转大
    void Function2()
    {
    unsigned char ci = 0xFF;
    unsigned short si = ci;
    unsigned int ni = ci;
    }
  2. 反汇编

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    0040EB30   push        ebp
    0040EB31 mov ebp,esp
    0040EB33 sub esp,4Ch
    0040EB36 push ebx
    0040EB37 push esi
    0040EB38 push edi
    0040EB39 lea edi,[ebp-4Ch]
    0040EB3C mov ecx,13h
    0040EB41 mov eax,0CCCCCCCCh
    0040EB46 rep stos dword ptr [edi]

    //********unsigned char ci = 0xFF;*****//
    0040EB48 mov byte ptr [ebp-4],0FFh

    //********unsigned short si = ci;*****//
    0040EB4C movzx ax,byte ptr [ebp-4]
    0040EB51 mov word ptr [ebp-8],ax

    //********unsigned int ni = ci;*****//
    0040EB55 mov ecx,dword ptr [ebp-4]
    0040EB58 and ecx,0FFh
    0040EB5E mov dword ptr [ebp-0Ch],ecx

    0040EB61 pop edi
    0040EB62 pop esi
    0040EB63 pop ebx
    0040EB64 mov esp,ebp
    0040EB66 pop ebp
    0040EB67 ret

    无符号小转大是通过 movzx 指令对变量进行扩展的。movzx 是直接对扩展位填充0。

变量从大转小

  1. 源码

    1
    2
    3
    4
    5
    6
    void Function1()
    {
    int ni = 0x12345678;
    short si = ni;
    char ci = ni;
    }
  2. 反汇编

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    0040EBA0   push        ebp
    0040EBA1 mov ebp,esp
    0040EBA3 sub esp,4Ch
    0040EBA6 push ebx
    0040EBA7 push esi
    0040EBA8 push edi
    0040EBA9 lea edi,[ebp-4Ch]
    0040EBAC mov ecx,13h
    0040EBB1 mov eax,0CCCCCCCCh
    0040EBB6 rep stos dword ptr [edi]

    //********int ni = 0x12345678;*****//
    0040EBB8 mov dword ptr [ebp-4],12345678h

    //********short si = ni;*****//
    0040EBBF mov ax,word ptr [ebp-4]
    0040EBC3 mov word ptr [ebp-8],ax

    //********char ci = ni;*****//
    0040EBC7 mov cl,byte ptr [ebp-4]
    0040EBCA mov byte ptr [ebp-0Ch],cl

    0040EBCD pop edi
    0040EBCE pop esi
    0040EBCF pop ebx
    0040EBD0 mov esp,ebp
    0040EBD2 pop ebp
    0040EBD3 ret

从大转到小使用的是 mov 指令,把大的值存到小的寄存器中,然后再将小的寄存器的值存到局部变量中,进行转换的。

一维数组

  1. 源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void Function()
    {
    //数组定义
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    //数组的读取
    int x = arr[0];
    int y = arr[1];
    int z = arr[2];

    //数组的写入
    arr[3] = 20;
    }
  2. 反汇编

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    //********void Function()*****//
    00401020 push ebp
    00401021 mov ebp,esp
    00401023 sub esp,74h
    00401026 push ebx
    00401027 push esi
    00401028 push edi
    00401029 lea edi,[ebp-74h]
    0040102C mov ecx,1Dh
    00401031 mov eax,0CCCCCCCCh
    00401036 rep stos dword ptr [edi]


    //********int arr[10] = {1,2,3,4,5,6,7,8,9,10};*****//
    00401038 mov dword ptr [ebp-28h],1
    0040103F mov dword ptr [ebp-24h],2
    00401046 mov dword ptr [ebp-20h],3
    0040104D mov dword ptr [ebp-1Ch],4
    00401054 mov dword ptr [ebp-18h],5
    0040105B mov dword ptr [ebp-14h],6
    00401062 mov dword ptr [ebp-10h],7
    00401069 mov dword ptr [ebp-0Ch],8
    00401070 mov dword ptr [ebp-8],9
    00401077 mov dword ptr [ebp-4],0Ah

    //********int x = arr[0];*****//
    0040107E mov eax,dword ptr [ebp-28h]
    00401081 mov dword ptr [ebp-2Ch],eax

    //********int y = arr[1];*****//
    00401084 mov ecx,dword ptr [ebp-24h]
    00401087 mov dword ptr [ebp-30h],ecx

    //********int z = arr[2];*****//
    0040108A mov edx,dword ptr [ebp-20h]
    0040108D mov dword ptr [ebp-34h],edx


    //********arr[3] = 20;*****//
    00401090 mov dword ptr [ebp-1Ch],14h

    00401097 pop edi
    00401098 pop esi
    00401099 pop ebx
    0040109A mov esp,ebp
    0040109C pop ebp
    0040109D ret

数组的存储形式类似于变量都是 [ebp-xxx],数组的存储是从栈的低地址向高地址存储。数组的大小是根据中括号中的常量来判断的。

空数组

  1. 源码

    1
    2
    3
    4
    5
    void plus()
    {
    int arr3[5];

    }
  2. 反汇编

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    00401190   push        ebp
    00401191 mov ebp,esp
    00401193 sub esp,54h
    00401196 push ebx
    00401197 push esi
    00401198 push edi
    00401199 lea edi,[ebp-54h]
    0040119C mov ecx,15h
    004011A1 mov eax,0CCCCCCCCh
    004011A6 rep stos dword ptr [edi]
    004011A8 pop edi
    004011A9 pop esi
    004011AA pop ebx
    004011AB mov esp,ebp
    004011AD pop ebp
    004011AE ret

函数中的空数组在在反汇编中没有任何数据显示

数组[变量]

char 型

  1. 源码

    1
    2
    3
    4
    5
    6
    7
    void plus()
    {
    char arr1[3] = {1,2,3};
    char i=0;
    arr1[1]=arr1[i];

    }
  2. 反汇编

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    00401040   push        ebp
    00401041 mov ebp,esp
    00401043 sub esp,48h
    00401046 push ebx
    00401047 push esi
    00401048 push edi
    00401049 lea edi,[ebp-48h]
    0040104C mov ecx,12h
    00401051 mov eax,0CCCCCCCCh
    00401056 rep stos dword ptr [edi]
    00401058 mov byte ptr [ebp-4],1
    0040105C mov byte ptr [ebp-3],2
    00401060 mov byte ptr [ebp-2],3
    00401064 mov byte ptr [ebp-8],0
    00401068 movsx eax,byte ptr [ebp-8]
    0040106C mov cl,byte ptr [ebp+eax-4]
    00401070 mov byte ptr [ebp-3],cl
    00401073 pop edi
    00401074 pop esi
    00401075 pop ebx
    00401076 mov esp,ebp
    00401078 pop ebp
    00401079 ret

arr1[i] = [ebp+eax-4]

short 型

  1. 源码

    1
    2
    3
    4
    5
    6
    7
    void plus()
    {
    short arr1[3] = {1,2,3};
    short i=0;
    arr1[1]=arr1[i];

    }
  2. 反汇编

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    00401040   push        ebp
    00401041 mov ebp,esp
    00401043 sub esp,4Ch
    00401046 push ebx
    00401047 push esi
    00401048 push edi
    00401049 lea edi,[ebp-4Ch]
    0040104C mov ecx,13h
    00401051 mov eax,0CCCCCCCCh
    00401056 rep stos dword ptr [edi]
    00401058 mov word ptr [ebp-8],offset plus+1Ch (0040105c)
    0040105E mov word ptr [ebp-6],offset plus+22h (00401062)
    00401064 mov word ptr [ebp-4],offset plus+28h (00401068)
    0040106A mov word ptr [ebp-0Ch],offset plus+2Eh (0040106e)
    00401070 movsx eax,word ptr [ebp-0Ch]
    00401074 mov cx,word ptr [ebp+eax*2-8]
    00401079 mov word ptr [ebp-6],cx
    0040107D pop edi
    0040107E pop esi
    0040107F pop ebx
    00401080 mov esp,ebp
    00401082 pop ebp
    00401083 ret

arr1[i]=[ebp+eax*2-8]

int 型

  1. 源码

    1
    2
    3
    4
    5
    6
    7
    void plus()
    {
    int arr1[3] = {1,2,3};
    int i=0;
    arr1[1]=arr1[i];

    }
  2. 反汇编

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    00401040   push        ebp
    00401041 mov ebp,esp
    00401043 sub esp,50h
    00401046 push ebx
    00401047 push esi
    00401048 push edi
    00401049 lea edi,[ebp-50h]
    0040104C mov ecx,14h
    00401051 mov eax,0CCCCCCCCh
    00401056 rep stos dword ptr [edi]
    00401058 mov dword ptr [ebp-0Ch],1
    0040105F mov dword ptr [ebp-8],2
    00401066 mov dword ptr [ebp-4],3
    0040106D mov dword ptr [ebp-10h],0
    00401074 mov eax,dword ptr [ebp-10h]
    00401077 mov ecx,dword ptr [ebp+eax*4-0Ch]
    0040107B mov dword ptr [ebp-8],ecx
    0040107E pop edi
    0040107F pop esi
    00401080 pop ebx
    00401081 mov esp,ebp
    00401083 pop ebp
    00401084 ret

arr1[i]=[ebp+eax*4-0Ch]

数组[变量+常量]

  1. 源码

    1
    2
    3
    4
    5
    6
    7
    void plus()
    {
    int arr1[3] = {1,2,3};
    int i=0;
    arr1[1]=arr1[i+1];

    }
  2. 反汇编

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    00401040   push        ebp
    00401041 mov ebp,esp
    00401043 sub esp,50h
    00401046 push ebx
    00401047 push esi
    00401048 push edi
    00401049 lea edi,[ebp-50h]
    0040104C mov ecx,14h
    00401051 mov eax,0CCCCCCCCh
    00401056 rep stos dword ptr [edi]
    00401058 mov dword ptr [ebp-0Ch],1
    0040105F mov dword ptr [ebp-8],2
    00401066 mov dword ptr [ebp-4],3
    0040106D mov dword ptr [ebp-10h],0
    00401074 mov eax,dword ptr [ebp-10h]
    00401077 mov ecx,dword ptr [ebp+eax*4-8]
    0040107B mov dword ptr [ebp-8],ecx
    0040107E pop edi
    0040107F pop esi
    00401080 pop ebx
    00401081 mov esp,ebp
    00401083 pop ebp
    00401084 ret

arr1[i+1]=[ebp+eax*4-8]

数组[数组[变量]]

  1. 源码

    1
    2
    3
    4
    5
    6
    7
    8
    void plus()
    {
    int arr1[5] = {1,2,3,4,5};
    int i=0;
    int arr2[5];
    arr2[1]=arr2[arr1[i]];

    }
  2. 反汇编

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    00401040   push        ebp
    00401041 mov ebp,esp
    00401043 sub esp,6Ch
    00401046 push ebx
    00401047 push esi
    00401048 push edi
    00401049 lea edi,[ebp-6Ch]
    0040104C mov ecx,1Bh
    00401051 mov eax,0CCCCCCCCh
    00401056 rep stos dword ptr [edi]
    00401058 mov dword ptr [ebp-14h],1
    0040105F mov dword ptr [ebp-10h],2
    00401066 mov dword ptr [ebp-0Ch],3
    0040106D mov dword ptr [ebp-8],4
    00401074 mov dword ptr [ebp-4],5
    0040107B mov dword ptr [ebp-18h],0
    00401082 mov eax,dword ptr [ebp-18h]
    00401085 mov ecx,dword ptr [ebp+eax*4-14h]
    00401089 mov edx,dword ptr [ebp+ecx*4-2Ch]
    0040108D mov dword ptr [ebp-28h],edx
    00401090 pop edi
    00401091 pop esi
    00401092 pop ebx
    00401093 mov esp,ebp
    00401095 pop ebp
    00401096 ret

    arr2[arr1[i]]=[ebp+eax4-14h];[ebp+ecx4-2Ch]

总结

  • 数组1[变量]:将变量值存储到寄存器 eax 中,然后再使用 eax*数据宽度-数组最低地址 来定位数组的位置[ebp+eax*数据类型宽度-数组最低地址]

  • 数组1[变量+常数]:[ebp+eax*数据类型宽度-(数组最低地址+常量)]

  • 数组2[数组1[变量]]:先计算数组1,[ebp+eax数据类型宽度-数组最低地址]。再计算数组2[ebp+ecx数据类型宽度-数组最低地址]

  • 本文标题:C&汇编基础-数据类型02
  • 本文作者:9unk
  • 创建时间:2021-04-01 14:18:28
  • 本文链接:https://9unkk.github.io/2021/04/01/c-hui-bian-ji-chu-shu-ju-lei-xing-02/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!