从C语言到汇编(一)变量

变量和常量是程序处理的两种基本数据对象。声明语句说明变量的名字及类型,也可以指定变量的初始值。
变量占用了内存的一块区域,不同数据类型的变量占用的字节大小各不相同。

类型 字节大小
char 1
short 2
int 4
long 4
char * 4
float 4
double 8

以上是C语言基本数据类型占用字节大小。在32位环境下。
声明变量需要声明变量的类型和名字。名字指定了那块内存区域,对名字的引用,就是对那块内存的引用。

局部变量

int main(void)
{
    int i;
    char ch;
    
    i=32;
    ch='a';
	
	return 0;
}

变量i占用了4字节的内存,而ch占用了一字节的内存。i=32对4字节内存赋值为32,ch=‘a’对一字节内存赋值为’a’。4字节内存是内存连续的4个字节。

将c代码翻译成汇编我们将看的更加清楚。

.text
.global main

main:
	pushl %ebp
	movl %esp,%ebp
	
	subl $5,%esp
	movl $32,-4(%ebp)
	movb $'a',-5(%ebp)
	
	movl $0,%eax	
	leave
	ret

.text指定以下片段是代码段。.global main声明main函数是全局函数。main:是函数的名字。
pushl %ebp; movl %esp,%ebp用于建立临时的栈帧,leave;ret用于销毁临时的栈帧。这将在函数章节中详细解释。
我们详细看中间的3行代码。
subl $5,%esp,栈指针减去5,在栈空间中申请了5个字节的空间。由于前面movl %esp,%ebp。%ebp=%esp。之后subl $5,%esp,所以内存地址可以使用%ebp作为基址来引用。


movl $32,-4(%ebp),将32写入-4(%ebp),-3(%ebp),-2(%ebp),-1(%ebp)这4个字节中,当然是按照小端写入的。
movb $‘a’,-5(%ebp),将’a’写入-5(%ebp)字节中。
这里用到了两个指令,如下所示。

指令 功能 描述
movl S,D S->D 赋值四个字节的数据
movw S,D S->D 赋值两个字节的数据
movb S,D S->D 赋值一个字节的数据

按照指令,我们还可以给char,short,int ,long ,char *等基本数据类型赋值。

int main(void)
{
	long l=1;
	int i=2;
	short s=3;
	char c='a';
	return 0;
}	

汇编代码

.text
.global main

main:
	pushl %ebp
	movl %esp,%ebp
	
	subl $11,%esp
	movl $1,-4(%ebp)
    movl $2,-8(%ebp)
    movw $3,-10(%ebp)
    movb $'a',-11(%ebp)	

	movl $0,%eax
	leave
	ret	

以上所说的变量都是局部变量,那全局变量是怎么样的呢?

全局变量
全局变量包括定义在函数外的变量,static 变量和定义在函数内的static 变量。

int array_len=20;
static int array_max=12;
int main(void)
{
	static int max=12;
	
	array_len=30;
	array_max=15;
	max=22;
	
	return 0;
}	

汇编代码

.data
.global array_len
array_len:.long 20
array_max:.long 12
max.1936:.long 12

.text
.global main

main:
	pushl %ebp
	movl %esp,%ebp
	
	movl $30,array_len
	movl $15,array_max
	movl $22,max.1936
	
	movl $0,%eax
	leave
	ret

.data表明以下是数据段。.global array_len表明array_len在其他文件中可见。array_max只在本文件内可见。max.1936表明只在函数内可见。由于只在函数内可见,所以可能存在多个static int max,所以这里的max被声明为max.1936。

.text段为代码段。movl $30,array_len ;movl $15,array_max; movl $22,max.1936为全局变量赋值。

指针变量

int main(void)
{
	int a=22;
	int *p;
	
	p=&a;
	
	return 0;
}

汇编代码

.text
.global main

main:
	pushl %ebp
	movl %esp,%ebp
	
	subl $8,%esp
	movl $22,-4(%ebp)
	leal -4(%ebp),%eax
	movl %eax,-8(%ebp)
	
	movl $0,%eax
	leave
	ret

int a和int *p占用了8个字节。所以subl $8,%esp。
变量a的地址为-4(%ebp),所以给-4(%ebp)赋值为$22。
leal -4(%ebp),%eax取a的地址给%eax
movl %eax,-8(%ebp)将%eax的值赋值给-8(%ebp)------p。

指令 功能 描述
leal S,D S->D 将S代表的地址值赋值给D

从上文我们也可以看出变量其实代表的就是一块内存。用变量名可以轻松的使用这块内存,而如果是汇编这需要你记住每块内存的地址。

发布了185 篇原创文章 · 获赞 18 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/pk_20140716/article/details/103044387
今日推荐