全局变量与局部变量
- 全局变量和局部变量表现形式
源码
1 |
|
反汇编
1 | 0040EBA0 push ebp |
从全局变量和局部变量的表现形式来看:全局变量是一个内存地址;局部比变量是 [ebp-xxx]
全局变量可以从其他函数中进行读写
- 全局变量的初始值
全局变量如果不赋值时,它的初始值为 0
- 全局变量和局部变量的分配
局部变量默认不分配值,需要设定初始值。
全局变量可以看做是一个地址,它的位置是不会变的,同时也说明全局变量是在程序编译的时候就已经定好了位置。所以全局变量是在程序编译以后就已经预留空间,空间大小由类型决定,且位置不会发生变化。
局部变量是[ebp-xxx]形式,当每次调用函数的时候ebp都会变化,同时函数结束后函数内的数据都将会变成垃圾数据。所以局部变量只有当函数调用时才会分配空间,且一定要有初始值。
- 全局变量和局部变量的作用范围
这里编译的时候提示报错: i 是未定义的标识符,也就是函数 Function2() 找不到变量i
局部变量作用范围仅限于当前函数自己,其他函数无法使用
数据类型转换
有符号数小转大
源码
1
2
3
4
5
6
7//有符号小转大
void Function1()
{
char ci = 0xFF;
short si = ci;
int ni = ci;
}反汇编
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
280040EBA0 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
2
3
4
5
6
7//无符号小转大
void Function2()
{
unsigned char ci = 0xFF;
unsigned short si = ci;
unsigned int ni = ci;
}反汇编
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
290040EB30 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
2
3
4
5
6void Function1()
{
int ni = 0x12345678;
short si = ni;
char ci = ni;
}反汇编
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
280040EBA0 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
2
3
4
5
6
7
8
9
10
11
12void 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;
}反汇编
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
2
3
4
5void plus()
{
int arr3[5];
}反汇编
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1600401190 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
2
3
4
5
6
7void plus()
{
char arr1[3] = {1,2,3};
char i=0;
arr1[1]=arr1[i];
}反汇编
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2300401040 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
2
3
4
5
6
7void plus()
{
short arr1[3] = {1,2,3};
short i=0;
arr1[1]=arr1[i];
}反汇编
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2300401040 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
2
3
4
5
6
7void plus()
{
int arr1[3] = {1,2,3};
int i=0;
arr1[1]=arr1[i];
}反汇编
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2300401040 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
2
3
4
5
6
7void plus()
{
int arr1[3] = {1,2,3};
int i=0;
arr1[1]=arr1[i+1];
}反汇编
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2400401040 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
2
3
4
5
6
7
8void plus()
{
int arr1[5] = {1,2,3,4,5};
int i=0;
int arr2[5];
arr2[1]=arr2[arr1[i]];
}反汇编
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
2600401040 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 retarr2[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 许可协议。转载请注明出处!