前言
在32位计算机中,char类型占用一个字节,short类型占用两个字节,int类型占用4个字节,但是在内存中分配存储空间的时候,并不是遵循这个规则,而是根据本机宽度来处理。本文就汇编的角度从局部变量、参数传递两种情况予以说明。
测试环境
- 操作系统:Windows xp x32
- 编译器:VC++ 6.0
分析
编写一段C语言代码,分别测试char、short、int三种类型
#include "stdafx.h"
void cfunc(char x, char y, char z)//传递三个char型变量
{
}
void sfunc(short a, short b, short c)//传递三个short型变量
{
}
void ifunc(int m, int n, int k)//传递三个int型变量
{
}
int main(int argc, char* argv[])
{
char x=1,y=2,z=3;
short a=1,b=2,c=3;
int m=1,n=2,k=3;
cfunc(x,y,z);
sfunc(a,b,c);
ifunc(m,n,k);
char o = x;
short p = a;
return 0;
}
在cfunc(x,y,z);
这一行添加断点,开始调试,然后查看反汇编
定义局部变量
从上图发现,从[ebp]
到[ebp-24h]
的缓冲区部分为三个char型变量、三个short型变量与三个int型变量提供了存储空间。
1. 分析char型变量
按照char类型占用1个字节,这里应该总共分配3个字节。但是[ebp]到[ebp-0Ch]总共将12个字节分配给了x、y、z三个变量,每个char型局部变量都分配了4个字节。
2. 分析short型变量
按照short类型占用2个字节,这里应该总共分配6个字节。但是[ebp-0Ch]
到[ebp-18h]
共12个字节分配给a、b、c三个变量,每个short型局部变量都分配了4个字节。
3.分析int型变量
int型变量占用4个字节,[ebp-18h]
到[ebp-24h]
共12个字节分配给m、n、k三个变量,int型局部变量实际分配内存并未出现奇怪的现象。
发现: char、short、int三种类型的局部变量在内存中分配存储空间时实际都是分配四个字节(具体原因后文会解析)。
使用局部变量
从汇编指令mov al,byte ptr [ebp-4]
和mov cx,word ptr [ebp-10h]
,可以发现虽然char型和short型变量在内存中均分配了4个字节,但是在使用时还是按照类型占用字节来使用。
函数传递参数
函数cfunc()、sfunc()反汇编
C/C++中函数默认调用约定是__cdcel
,参数从右到左传递,所以函数cfunc()参数传递顺序是z、y、x,函数sfunc()参数传递顺序是c、b、a,由于push
和pop
指令的操作以4个字节为单位,所以char型与short型参数入栈时均是push的32位寄存器。
函数ifunc()反汇编
可以发现当参数是 int类型时,push
的数据宽度与函数参数类型宽度一致。
解析
- 32位计算机,地址线为32根,所以一次处理32位数据效率是最高的。
- char、short型变量不足4个字节,拓展到四个字节后计算机可以当作int型处理,一次处理4个字节,提高效率。
- 现代计算机内存容量足够,而int型变量一般也够用,所以整型变量定义为int型是推荐的方式,这样计算机可以将所有整数类型“一视同仁”地处理,是一种空间换取时间的思想。