汇编与c/c++指针

直接上代码,注意区分变量和指针变量,其实它们两个是不同的类型,指针变量存储的值永远都是4字节类型(内存地址)。 c++代码 `int i,*p; { _asm { mov eax,eax mov eax,eax }

//区分下面的指针变量和变量

//00401005    8B35 A4204000   MOV ESI,DWORD PTR DS:[<&MSVCR100.printf>>; 将打印函数存储到esi,可能是优化原因


//00401015    C705 6C334000 3>MOV DWORD PTR DS:[i],0x8235              ; 赋值操作
i = 33333;
//0040101F    C705 70334000 6>MOV DWORD PTR DS:[p],OFFSET test_poi.i   ; UNICODE "舵"
p = &i;//i地址赋值给p
//0040100B    68 6C334000     PUSH OFFSET test_poi.i                   ; 直接取i地址
//00401010    68 F4204000     PUSH test_poi.004020F4                   ; ASCII "i变量地址是:0x%x\n"
//CALL ESI 
printf("i变量地址是:0x%x\n",&i);//i的地址
//0040102B    A1 6C334000     MOV EAX,DWORD PTR DS:[i]                 ; i取值,,赋值到eax
//00401030    50              PUSH EAX
//00401031    68 08214000     PUSH test_poi.00402108                   ; ASCII "i变量数值是:%d\n"
//00401036    FFD6            CALL ESI                                 ; msvcr100.printf
printf("i变量数值是:%d\n",i);//i值



//printf("i变量数值是:%\n",*i);//错误的,因为不是指针类型所以不可以通过编译,只有强制转换才可以
//printf("i变量数值是:%\n",*((int*)i));//可以运行,但是会抛出异常。除非i是一个有效的地址,否则异常


//00401038    8B0D 70334000   MOV ECX,DWORD PTR DS:[p]                 ; 取p的值,这个ecx是取值寄存器,下同
//0040103E    51              PUSH ECX                                 ; msvcr100.78B05617
//0040103F    68 1C214000     PUSH test_poi.0040211C                   ; ASCII "*p变量地址是:0x%x\n"
//00401044    FFD6            CALL ESI                                 ; msvcr100.printf
//最难理解,放在最后看
printf("*p变量地址是:0x%x\n",*&p);//*&p和&*p相同, 等同于p指针变量的值,1.&*p,先取出i的值(最后一步),然后&i。2.*&p,先得到指针变量p的地址,然后在取地址,然后继续获取指针p的地址,假定一个临时指针变量temp的值是此地址,在取得执行*temp,先取出指针变量temp的值,在用temp的值当做地址来取值(这个才是星号的作用)
//00401046    68 70334000     PUSH OFFSET test_poi.p                   ; 取指针变量p的地址
//0040104B    68 30214000     PUSH test_poi.00402130                   ; ASCII "p变量地址是:0x%x\n"
//00401050    FFD6            CALL ESI                                 ; msvcr100.printf
printf("p变量地址是:0x%x\n",&p);//指针变量p的地址
//00401052    8B15 70334000   MOV EDX,DWORD PTR DS:[p]                 ; 取指针变量p的值,值为i的地址
//00401058    52              PUSH EDX                                 ; msvcr100.78B55550
//00401059    68 44214000     PUSH test_poi.00402144                   ; ASCII "p变量数值是:%x\n"
//0040105E    FFD6            CALL ESI                                 ; msvcr100.printf
printf("p变量数值是:%x\n",p);//获取指针变量p的值
//00401060    A1 70334000     MOV EAX,DWORD PTR DS:[p]                 ; 取指针p的值,值为i的地址
//00401065    8B08            MOV ECX,DWORD PTR DS:[EAX]               ; 取eax的值,即i地址的值
//00401067    51              PUSH ECX                                 ; msvcr100.78B05617
//00401068    68 58214000     PUSH test_poi.00402158                   ; ASCII "p变量数指向值是:%d\n"
//0040106D    FFD6            CALL ESI                                 ; msvcr100.printf
printf("p变量数指向值是:%d\n",*p);//分成两部,先取出指针变量p的值,在用p的值当做地址来取值(这个才是星号的作用)


/*i变量地址是:0x40336c
	i变量数值是:33333
	*p变量地址是:0x40336c
	p变量地址是:0x403370
	p变量数值是:40336c
	p变量数指向值是:33333*/

getchar();
return 0;

}

汇编代码

00401000 > $  56            PUSH ESI
00401001   .  8BC0          MOV EAX,EAX                              ;  花指令
00401003   .  8BC0          MOV EAX,EAX                              ;  花指令
00401005   .  8B35 A4204000 MOV ESI,DWORD PTR DS:[<&MSVCR100.printf>>;  将打印函数存储到esi,可能是优化原因
0040100B   .  68 6C334000   PUSH OFFSET test_poi.i                   ; /直接放入i地址
00401010   .  68 F4204000   PUSH test_poi.004020F4                   ; |format = "i变量地址是:0x%x
"
00401015   .  C705 6C334000>MOV DWORD PTR DS:[i],0x8235              ; |赋值操作
0040101F   .  C705 70334000>MOV DWORD PTR DS:[p],OFFSET test_poi.i   ; |
00401029   .  FFD6          CALL ESI                                 ; \调用函数esi地址,即printf
0040102B   .  A1 6C334000   MOV EAX,DWORD PTR DS:[i]                 ;  通过ds寻址取值,,赋值到eax
00401030   .  50            PUSH EAX
00401031   .  68 08214000   PUSH test_poi.00402108                   ;  ASCII "i变量数值是:%d\n"
00401036   .  FFD6          CALL ESI
00401038   .  8B0D 6C334000 MOV ECX,DWORD PTR DS:[i]                 ;  取p的值,这个ecx是取值寄存器
0040103E   .  8B11          MOV EDX,DWORD PTR DS:[ECX]
00401040   .  52            PUSH EDX
00401041   .  68 1C214000   PUSH test_poi.0040211C                   ;  ASCII "i变量数值是:%\n"
00401046   .  FFD6          CALL ESI                                 ;  取变量p的值
00401048   .  A1 70334000   MOV EAX,DWORD PTR DS:[p]
0040104D   .  50            PUSH EAX
0040104E   .  68 2C214000   PUSH test_poi.0040212C                   ;  ASCII "*p变量地址是:0x%x\n"
00401053   .  FFD6          CALL ESI
00401055   .  68 70334000   PUSH OFFSET test_poi.p
0040105A   .  68 40214000   PUSH test_poi.00402140                   ;  ASCII "p变量地址是:0x%x\n"
0040105F   .  FFD6          CALL ESI
00401061   .  8B0D 70334000 MOV ECX,DWORD PTR DS:[p]
00401067   .  51            PUSH ECX                                 ;  msvcr100.__winitenv
00401068   .  68 54214000   PUSH test_poi.00402154                   ;  ASCII "p变量数值是:%x\n"
0040106D   .  FFD6          CALL ESI
0040106F   .  8B15 70334000 MOV EDX,DWORD PTR DS:[p]
00401075   .  8B02          MOV EAX,DWORD PTR DS:[EDX]
00401077   .  50            PUSH EAX


`

转载于:https://my.oschina.net/stategrace/blog/843766

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值