《软件开发环境CH.ppt》由会员分享,可在线阅读,更多相关《软件开发环境CH.ppt(18页珍藏版)》请在三一办公上搜索。
1、软件开发环境,理解指针和强制转换,我们最迷惑和没有信心的是c语言的指针和强制转换,何时能转换,怎样的转换是安全的?运用我们之前的学习成果吧。用反汇编分析。,请判断这段代码的执行结果,short i;short j;int*pi;void main(int argc,char*argv)cout j endl;pi=(int*),void main(int argc,char*argv)int i;int*pi;short*ps;char*pc;pi=*pc=0 x12,我们想分析如上代码的反汇编,这时,跑了个ebp-14h出来,不理解!这时在猜测、实证的道路上就要考验我们回避问题,迂回解决的处
2、理能力了。如何修改一下,让我们容易理解呢,pi=0041139A lea eax,ebp-8 0041139D mov dword ptr ebp-2Ch,eax,int i;int*pi;short*ps;char*pc;void main(int argc,char*argv)pi=*pc=0 x12,用全局变量,就可以看到我们之前熟悉的形式,pi=004113B7 mov eax,1234h 004113BC mov ecx,dword ptr ps(417144h)004113C2 mov word ptr ecx,ax,现在大家对mov dword ptr pi(417148h),o
3、ffset i(41714Ch)中的offset不理解,那么我们去掉符号显示得到如下结果,pi=004113B7 mov eax,1234h 004113BC mov ecx,dword ptr ds:00417144h 004113C2 mov word ptr ecx,ax,pi=004113A2 mov dword ptr ds:00417140h,41714Ch 注意以上三句话,显示了2中强制转换指针的情况,第一种没有强制转换。但三句话中除了被赋值的地址不同,其余一摸样。并没和类型转换相关的指令,就是将41714c这个地址值赋值给了三个不同的地址。我们惊讶地发现,其实没有所谓的“类型强
4、制指令或相关信息”,那强制转换怎么就复杂而不安全了?我们需要实证如下信息,请用调试器证明1.41714ch是i的地址;2.Mov指令中方括号中那三个地址分别是pi,ps,pc的地址,其实也好理解,对指针的强制转换,不过是将地址这个整数赋值给一个指针变量,地址是32位整数,指针变量时32位整数,怎么也不会有任何问题的。指针是拿来读取该地址或写该地址的,那么危险是否发生在这个地方?还有,既然是类型强制转换,这个类型信息又在哪里呢?请看那三个赋值语句的反汇编,*pi=0 x1234;004113AC mov eax,dword ptr ds:00417148h 004113B1 mov dword
5、ptr eax,1234h*ps=0 x1234;004113B7 mov eax,1234h 004113BC mov ecx,dword ptr ds:00417144h 004113C2 mov word ptr ecx,ax*pc=0 x12;004113C5 mov eax,dword ptr ds:00417140h 004113CA mov byte ptr eax,12h,1.00417148h是pi的地址,第一条mov指令让eax寄存器的值为pi变量存放的值,也就是i的地址2.第2条mov指令将1234h赋值给eax指向的地址,也就是i的地址,完成对i的赋值请大家用单步跟踪证
6、实以上分析,同理分析,*ps=0 x1234;对应的汇编语句,也有前面类似的逻辑。同样将0 x1234赋值给了i变量。*pi=0 x1234004113B1 mov dword ptr eax,1234h*ps=0 x1234;004113B7 mov eax,1234h 004113BC mov ecx,dword ptr ds:00417144h 004113C2 mov word ptr ecx,ax 既然都是对同一个地址赋值(i的地址),关键性差异在哪里?这里最关键的差异是mov赋值时,一个是dword,一个是word。代表一个是赋值4字节,一个赋值2字节的长度。这时我们发现了强制转换
7、后,关键性的不同,是在读写地址指向的内存时,读写长度的不同!这也是不同类型整数的关键差异。请大家实验一下,用调试器证明赋值长度的不同。,所以,指针强制转换的差异发生在用该指针去读写其指向的地址的内容。不同类型,生成的读写指令不同,读写的长度不同。对于上例,i是整数,长4字节,强制为short指针,读写的是2字节。所以还是在i变量的范围内。如果将i的类型换成short i;pi=(int*)i;*pi=0 x1234;这样的代码有问题吗?请分析,并用调试器证明,强制转换是否安全,关键看转换前的变量的大小能否放下转换后类型的数据。如果放不下,就是越界,就是错误其实指针是c语言有别于汇编中地址这个概
8、念的东西。虽然说c的指针首先肯定是一个地址,但不仅仅代表地址。在存取内存时,它代表了读写的长度,长度为该指针指向的类型的大小。(注意,c中指针的加减n运算不是加减一个n字节,而是加减n*类型大小,个字节),请判断这段代码的执行结果,int*pi;short si=12;pi=(int*),1179660 12000c.结果不是12和0C,为什么?指针类型表示的是指针要访问的数据的大小,int*指向4字节的数据,short*指向2字节的数据pi=(int*)/使pi指向一个等于&si的地址*pi访问通过pi指向的数据,注意,pi指向4字节的数据而不是2字节再请大家思考,这个显示结果12000c中那部分是必然的,注意:在 intel86中,整数的低字节放在内存的低地址,si=0 x0c.因为 si 是 短整型,它包括两字节,如图用红色标志的pi 也指向&si.但是它包括了4个字节的地址,0c 00 12 00.因此,*pi 不是 12,而是 0 x12000c.,数据指针反思,任何一个东西是从使用来界定其内涵的,数据指针是读写内存用的。因此包含两部分信息指针首先是地址其次提示编译器访问该地址时,生成的访问代码(读/写)到底访问多少个字节 作为指针强制转换,并不影响地址的值,因此,必然受到2部分影响。所以转换前后数据的大小将影响转换的安全性,否则会越界,