【通过汇编语言理解C语言指针】

从汇编推导C语言指针

汇编推导C语言指针

指针,是C语言中的一个重要概念及其特点,而上一章中说到,汇编语言是为了让开发者更好的理解机器语言,并通过汇编语言来处理程序上的错误问题。
而执行机器语言的是CPU,而CPU内部有着各种各样的寄存器,其功能各有不同,目的就是为了推进程序正常运行,因此可以理解为汇编语言就在操作CPU。而C语言则是对汇编语言最纯粹的抽象(因为汇编虽然比机器语言更好理解,但也相对复杂),通俗的说C语言就是在翻译汇编语言,因此理解汇编语言能有助于我们更好的理解C语言的指针。

首先,我们有这样的一个需求,在第一个方法中调用另一个方法,同时需要将该方法中的变量传递过去,使得另一个方法修改该变量的同时,第一个方法能够感知到第二个方法修改了该变量,需要如何做呢?我们知道程序要想运行,必须先将程序加载到内存中,而操作程序中的指令方法,需要将其压入程序的栈中,而栈中保存的都是程序代码的私有数据,那么这些数据从哪里来呢?毫无疑问数据在内存中,保存在内存中的哪里?内存中有对应的地址,因此我们只要有了该数据对应的内存地址,就能操作该数据。所以对于上述的需求,我们只要把该变量的内存地址传递给第二个方法,那么,第二个方法对于该变量的操作,第一个方法也能感知到,因为第一个方法本来就有变量的内存地址!接下来介绍两个汇编指令分别为 leaf,和();
leaf指令:取变量地址
():将()中的地址送到地址总线中操作,简单理解为操作该地址中的变量
介绍完上述的需求和基础信息之后,我们来看一个C语言的例子

#include <stdio.h>

int sum(int *p){
  *p = 10;
  return 10;
}
 
int main()
{
    /* 我的第一个 C 程序 */
    int a = 3;
    int f = sum(&a);
    return 0;
}

这段代码很容易理解,设置了一个变量a,然后调用了sum方法,同时将a的地址传了进去。我们通过gcc -m32 -S demo.c 编译我们的C文件(已经省略了一些不需要的文件)

	.file	"demo.c"
	.text
	.globl	sum
	.type	sum, @function
#函数sum
sum:
.LFB0:
	pushl	%ebp
	movl	%esp, %ebp
	#调用方法之后,将刚才放入esp的值取出来放入eax中
	movl	8(%ebp), %eax
	然后将eax中的值当作地址送入地址总线,操作该地址所对应的变量
	movl	$10, (%eax)
	movl	$10, %eax
	popl	%ebp
	ret
	.cfi_endproc
.LFE0:
	.size	sum, .-sum
	.globl	main
	.type	main, @function
#程序入口main
main:
.LFB1:
	pushl	%ebp
	movl	%esp, %ebp
	#开辟20个字节的空间
	subl	$20, %esp
	将3压入离栈底-8个字节的位置(因为栈底在高地址,栈顶在低地址)
	movl	$3, -8(%ebp)
	取-8(%ebp)中的地址,并将其放入到eax寄存器中,还记得上面说的吗,leal就是取地址操作
	leal	-8(%ebp), %eax
	将eax的值放入到esp栈底寄存器中,还记得()这个操作码,就是将eax的值放入到esp所对应的内存地址中
	movl	%eax, (%esp)
	#调用sum函数,然后在去看上面的sum函数做了什么
	call	sum
	movl	%eax, -4(%ebp)
	movl	$0, %eax
	leave
	ret
.LFE1:
	.size	main, .-main
	.ident	"GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
	.section	.note.GNU-stack,"",@progbits

这段汇编代码中,我们重点关注.LFB1,在上面的代码中我做了简单注释,可以看到在eax寄存器中就是存的变量3的内存地址,然后通过leal,()等指令将地址传送到sum方法中,sum方法对变量3的内存地址进行操作,从而在main方法中也能感知到变量3的更改。
那么我们将其对照到C语言,C语言&不就是对leal指令的抽象吗? *不就是对于()的抽象吗?

通过上述的汇编以及C语言的例子,我们更好的理解了C语言的指针。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值