[谬]C语言指针的底层汇编实现原理
指针的赋值过程与指针类型的真相int指针:int gi;int *p;p = &gi;00EF166E C7 05 3C 91 EF 00 38 91 EF 00mov dword ptr ds:,0EF9138h*p = 12;00EF1678 A1 3C 91 EF 00 mov eax,dword ptr ds: 00EF167D C7 00 0C 00 00 00 mov dword ptr ,0Ch
注释:p = &gi;mov dword ptr ds:,0EF9138h 将gi的地址0EF9138h放入00EF913Ch所指向的地址中保存 *p = 12;mov eax,dword ptr ds:[00EF913Ch ] 将00EF913Ch所存储的地址,也就是gi的地址0EF9138h放入eax中.mov dword ptr ,0Ch 将0ch放入eax所存储的地址中,也就是把0ch放在了gi所代表的地址中,dword也就代表了向eax中写入4字节数据
short型指针:
short gi;short *p;p = &gi;0034166E C7 05 3C 91 34 00 38 91 34 00 mov dword ptr ds:,349138h *p = 12;00341678 B8 0C 00 00 00 mov eax,0Ch 0034167D 8B 0D 3C 91 34 00 mov ecx,dword ptr ds: 00341683 66 89 01 mov word ptr ,ax 注释:p = &gi; mov dword ptr ds:,349138h 将gi的地址0EF9138h放入00EF913Ch所指向的地址中保存 *p = 12;mov eax,0Ch 将0Ch放入eax中,由于eax是4字节,所以0ch放到了eax的低2字节,ax中mov ecx,dword ptr ds: 将p所存储的地址,也就是gi的地址放入ecx中.mov word ptr ,ax 将ax所存储的内容写入到ecx所指向的地址,也就是gi的地址,.word说明将向gi的地址写入2字节数据
char型指针:char gi;char *p; p = &gi;00CC166E C7 05 3C 91 CC 00 38 91 CC 00 mov dword ptr ds:,0CC9138h *p = 12;00CC1678 A1 3C 91 CC 00 mov eax,dword ptr ds: 00CC167D C6 00 0C mov byte ptr ,0Ch
注释: p = &gi; mov dword ptr ds:,0CC9138h 将gi的地址0EF9138h放入00EF913Ch所指向的地址中保存
*p = 12; mov eax,dword ptr ds: 将00EF913Ch所存储的地址,也就是gi的地址0EF9138h放入eax中. mov byte ptr ,0Ch 将0ch放入eax所存储的地址中,也就是把0ch放在了gi所代表的地址中,byte 也就代表了向eax所存储的地址中写入1字节数据
总结: C语言指针包含两方面信息,一个是地址,存放在指针变量中,另一个是类型信息,决定了读写的长度,没有存储在指针变量中,位于指针读写过程所使用的mov指令中,不同的指针类型对应着读写的字节数.这也间接解释了指针为什么+-1不是+-1个字节,而是加减长度是指针类型的字节数,void类型的指针之所以无法加减,就是因为它没有类型信息,无法确定加减的长度,代表的仅仅是一块内存地址.
指针类型强制转换/****************************************************************/程序:int i;int * pi;short * ps;char * pc;int main(){ pi = &i; ps = ( short *)&i; pc = ( char *)&i; *pi = 0x1234; *ps = 0x1234; *pc = 0x12;}/***************************************************************/
反汇编:
pi = &i;00941A8E C7 05 E0 94 94 00 DC 94 94 00 mov dword ptr ds:,9494DCh ps = (short *)&i;00941A98 C7 05 E4 94 94 00 DC 94 94 00 mov dword ptr ds:,9494DCh pc = (char *)&i;00941AA2 C7 05 E8 94 94 00 DC 94 94 00 mov dword ptr ds:,9494DCh *pi = 0x1234;
注释:在把i赋值其他指针变量的过程中,强制转换并没有生成任何指令,可见,强制转换并不是在这里产生效果的
00941AAC A1 E0 94 94 00 mov eax,dword ptr ds: 00941AB1 C7 00 34 12 00 00 mov dword ptr ,1234h *ps = 0x1234;00941AB7 B8 34 12 00 00 mov eax,1234h 00941ABC 8B 0D E4 94 94 00 mov ecx,dword ptr ds: 00941AC2 66 89 01 mov word ptr ,ax *pc = 0x12;00941AC5 A1 E8 94 94 00 mov eax,dword ptr ds: 00941ACA C6 00 12 mov byte ptr ,12h
注释: 可以看出,在这里,写入的字节数发生了变化,所以,强制转换的效果不在转换过程中体现,而是体现在转换后去访问内存时的指令中
注释2:如果转换后指针指向的数据类型大小小于原来的数据类型大小,那么用该转换后的指针访问就不会越过原数据的内存,是安全的,否则危险,要越界
/*****************************************************/程序:#include<stdio.h>
int main(){ int * pi; short si = 12; pi = ( int *)&si; printf( "%d,%x", *pi, *pi);}/*****************************************************/
注释:正常情况下这段程序应该输入的是12,0c但是实际上的运行结果是-859045876,cccc000c这是由于将si的地址强制转换为int *类型,然后赋值给pi;那么pi会访问4字节,这时越界了,将si后的2字节纳入了范围,即是cc cc,他们和0c 00合在一起正好与结果吻合这就是违反了强制转换的原则,越界了
现在终于搞清楚从语言为什么是底层语言了,它与汇编有着很多的联系,这样可以更加清楚的理解底层的原理和认识,谢谢楼主的解答了啊 沙发躺着舒服,讲的不错, 给个评分
谢谢分享 有空可以看看 ????ケ?????? 还不错! 感谢分享 晕针。。 这个对c指针很有用。。
感谢分享 了解了!谢谢
页:
[1]
2