C语言中的数组和指针汇编代码分析实例

   这篇文章主要介绍了C语言中的数组和指针汇编代码分析实例,本文用一则C语言例子来得到对应的汇编代码,并一一注解每句汇编代码的含义,需要的朋友可以参考下

  今天看《程序员面试宝典》时偶然看到讲数组和指针的存取效率,闲着无聊,就自己写了段小代码,简单分析一下C语言背后的汇编,可能很多人只注重C语言,但在实际应用当中,当出现问题时,有时候还是通过分析汇编代码能够解决问题。本文只是为初学者,大牛可以飘过~

  C源代码如下:

  代码如下:

  #include "stdafx.h"

  int main(int argc, char* argv[])

  {

  char a=1;

  char c[] = "1234567890";

  char *p = "1234567890";

  a = c[1];

  a = p[1];

  return 0;

  }

  在VC6.0下查看汇编代码步骤:

  在main函数中靠前的部分随便一行F9设置断点->编译->F5 在调试界面中右键->Go to disassembly

  Debug汇编代码(已加注释):

   代码如下:

  4: #include "stdafx.h"

  5:

  6: int main(int argc, char* argv[])

  7: {

  00401010 push ebp

  00401011 mov ebp,esp ;保存栈帧

  00401013 sub esp,54h ;抬高栈顶

  00401016 push ebx

  00401017 push esi

  00401018 push edi ;压入程序中用到的寄存器,以便恢复

  00401019 lea edi,[ebp-54h]

  0040101C mov ecx,15h

  00401021 mov eax,0CCCCCCCCh

  00401026 rep stos dword ptr [edi] ;栈顶与栈帧之间的数据填充为0xcc,相当于汇编中的int 3,这是因为debug模式下把Stack上的变量都初始化为0xcc,检查未初始化的问题

  8: char a=1;

  00401028 mov byte ptr [ebp-4],1 ;ebp-4是为变量a分配的空间地址

  9: char c[] = "1234567890";

  0040102C mov eax,[string "1234567890" (0042201c)]

  00401031 mov dword ptr [ebp-10h],eax ;“1234567890”是字符串常量,存储在地址0042201c处,ebp-10是为数组C分配的空间的首地址,空间大小从ebp-0x10到ebp-0x04,共12个字节。本句中先把“1234”这4个字节拷贝到数组C中

  00401034 mov ecx,dword ptr [string "1234567890" 4 (00422020)]

  0040103A mov dword ptr [ebp-0Ch],ecx ;作用同上,把“5678”这4个字节拷贝到数组C中

  0040103D mov dx,word ptr [string "1234567890" 8 (00422024)]

  00401044 mov word ptr [ebp-8],dx ;作用同上,把“90”这2个字节拷贝到C中

  00401048 mov al,[string "1234567890" 0Ah (00422026)]

  0040104D mov byte ptr [ebp-6],al ;这个大家都熟,不要忘了

  10: char *p = "1234567890";

  00401050 mov dword ptr [ebp-14h],offset string "1234567890" (0042201c) ;ebp-0x14是为指针p分配的空间地址,大小是4个字节,地址中的值是字符串“1234567890”的首地址

  11: a = c[1];

  00401057 mov cl,byte ptr [ebp-0Fh] ;这里是重点,因为数组C在栈上连续存储,很容易根据ebp找到第其中一个字符的地址,并取值,赋给cl

  0040105A mov byte ptr [ebp-4],cl ;完成赋值

  12: a = p[1];

  0040105D mov edx,dword ptr [ebp-14h] ;这里与上面就有区别,因为根据ebp只知道指针p的值,先得到p的值,即先得到一个指针

  00401060 mov al,byte ptr [edx 1] ;根据得到的指针间接的找到字符串中的一个字符

  00401063 mov byte ptr [ebp-4],al

  13: return 0;

  00401066 xor eax,eax ;eax清0,作为main函数的返回值

  14: }

  00401068 pop edi

  00401069 pop esi

  0040106A pop ebx

  0040106B mov esp,ebp

  0040106D pop ebp ;恢复ebp

  0040106E ret

  好了,可以看到,用数组访问元素,只需2步,而用指针时要3步。可见数组和指针并不相同,有时候大家都认为可以把数组的名称看成一个指针,这种想法有时候没错,但有时候却会出错。我再举一个简单的例子,而下面的这个例子可能是大家在开发过程中经常会碰到的问题。

  在文件test.cpp中:

   代码如下:

  #include "stdafx.h"

  #include "inc.h"

  extern char chTest[10];

  int main(int argc, char* argv[])

  {

  printf("chTest=%sn", chTest);

  return 0;

  }

  上面有个extern声明,表明chTest数组是在外部文件中定义过的。chTest定义在inc.h中:

   代码如下:

  char chTest[10]="123456789";

  上述的程序,经编译后,可以成功运行。但如果把红色的代码改成如下:

   代码如下:

  extern char *chTest;

  这时,程序在编译的时候就会通不过,提示的错误信息是:redefinition; different types of indirection,但这时候并没有错误出现在哪一行的说明,如果是在开发一个大型工程,那么就不容易定位问题出在哪个地方。造成上述错误的原因我想大家都明白了,就是因为当chTest作为一个指针被引用时,其元素访问的方式与数组是不同的,就算程序能编译通过,在运行时,也是会出现错误。

  好了,上述的内容都是个人有感而发,是些简单零碎的东西,笑纳。如有哪些地方说的不合适,而望指正!

时间: 2024-09-16 00:07:11

C语言中的数组和指针汇编代码分析实例的相关文章

C语言中的数组和指针汇编代码分析实例_C 语言

今天看<程序员面试宝典>时偶然看到讲数组和指针的存取效率,闲着无聊,就自己写了段小代码,简单分析一下C语言背后的汇编,可能很多人只注重C语言,但在实际应用当中,当出现问题时,有时候还是通过分析汇编代码能够解决问题.本文只是为初学者,大牛可以飘过~ C源代码如下: 复制代码 代码如下: #include "stdafx.h" int main(int argc, char* argv[]) {        char a=1;        char c[] = "

指针-c语言中字符数组初始化问题

问题描述 c语言中字符数组初始化问题 字符数组初始化1: char str[]=""123"";//不报错2: char str[4]; str=""123"";//不能将const char[4] to char[4]字符指针初始化1: char *str=""123"";//不报错2: char *str; str=""123"";//不报错求

c语言-如何在C语言中以数组指针作为形参输出数组

问题描述 如何在C语言中以数组指针作为形参输出数组 #include ""stdafx.h""void cmdsend(unsigned int * info);int main(){ unsigned int senddata[5]; senddata[0] = 8; senddata[1] = 2; senddata[2] = 0; senddata[3] = 4; senddata[4] = 5; cmdsend( senddata ); while(1){;

c-C语言中函数数组调用问题

问题描述 C语言中函数数组调用问题 5C 定义的二维数组为全局变量,在主函数中有多个子函数要用到它.请问下大家,子函数中计算的此二维数组的值间能传递么?还是也需要调用呢?~~ 解决方案 可以传引用或者指针,或者定义为全局变量.那就直接用不用传了. 解决方案二: 传递数组地址或指针,C中没有引用 解决方案三: 你用全局变量,每个函数里面都可以改啊. 解决方案四: 全局的直接访问就行了,就是要注意不要把里面的数据乱改,导致读取出问题 解决方案五: 你使用全局变量,每个函数都可以去访问它并且修改它,会

数组 指针-c语言二维数组的指针问题

问题描述 c语言二维数组的指针问题 在WinTC下运行如下代码 #include void main() { char a1[][5]={"ab","cd","ef","ghi","sfs"}; printf("%sn",*(a1+3)); //语句1 printf("%cn",**(a1+3)); //语句2 } 运行结果为: ghi g 但如果将上述语句1中的%s

Java语言入门教程(十一):Java语言中的数组

在教程(十)中,我们学习了Java类之间常见的两种关系,即关联和依赖. 如果A关联或依赖B,如果仅从A到B这个方向看,从数量上,可能有1对1和1对多 两种可能.面向对象的应用,都是映射现实世界的对象以及对象之间的关系的, 仔细考察一下我们身边的情况,对象与对象之间如果存在关联或依赖,其实1对 多的关系更为常见.如,一个部门有多个员工,一个学员有多个院系,一个人有 多张毕业证书- 上篇文章中的例子,学生只能选择一门免费课程学习,如果培训中心加大优 惠力度,每个学生最多可以选择3门课程学习,应该如何

C语言中全局数组和局部数组的问题

 今天同学遇到一个在C语言中全局数组和局部数组的问题,卡了许久,我也没有第一时间看出问题,现在把问题梳理一下,并给出解决方案. 问题描述: 在全局声明的数组与在局部声明的数组有着不同的效果. 首先来看一个程序: 代码如下: #include <stdio.h> #include <stdlib.h> #define MAX 10 char a[MAX]; int main() { int i; char b[MAX]; char *c=(char *)malloc(MAX * si

c-C 语言中返回结构体指针,结果出来了,但是还是出现错误,不知道为什么

问题描述 C 语言中返回结构体指针,结果出来了,但是还是出现错误,不知道为什么 解决方案 p 没有初始化,也就是没有分配空间.典型的指针错误,不初始化,指针指向哪里呢? 解决方案二: array *p = new array(); 解决方案三: array p;test(&p); 解决方案四: 当然,使用指针应该首先初始化一个空地址的,否则,很容易发生指针地址错误其次,看了一下你的程序设计,程序本身是定义了一个array的结构体变量,在主函数中却要申请一个指针变量p(它的类型是结构体),一系列操

c语言中字符数组系统初始化为什么?

问题描述 c语言中字符数组系统初始化为什么? c语言中声明一个字符数组,如果自己没有初始化,那系统初始化为什么?是被初始化为空字符吗?我的实验结果好像是空字符 解决方案 在debug调试下,vc会将它初始化为0xcc 0xcc...,也就是"烫烫烫烫...",release运行的时候,vc++不会初始化,内容随机,但是很大可能是0,因为只有在堆内存被重新分配的时候,才可能出现其他值. 其它编译器不好说. 解决方案二: C语言字符数组的初始化C语言字符数组的初始化