当前位置: 首页 > 编程笔记 >

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

萧自珍
2023-03-14
本文向大家介绍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    ;这个大家都熟,不要忘了\0

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=%s\n", chTest);

       return 0;

}

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


char chTest[10]="123456789";

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


extern char *chTest;

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

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

 类似资料:
  • 本文向大家介绍C语言 数组指针详解及示例代码,包括了C语言 数组指针详解及示例代码的使用技巧和注意事项,需要的朋友参考一下 数组(Array)是一系列具有相同类型的数据的集合,每一份数据叫做一个数组元素(Element)。数组中的所有元素在内存中是连续排列的,整个数组占用的是一块内存。以int arr[] = { 99, 15, 100, 888, 252 };为例,该数组在内存中的分布如下图所示

  • 本文向大家介绍C语言中的指针以及二级指针代码详解,包括了C语言中的指针以及二级指针代码详解的使用技巧和注意事项,需要的朋友参考一下 很多初学者都对C中的指针很迷糊,希望这篇blog能帮助到大家: 1.什么是“指针”: 在执行C程序的时候,由于我们的数据是存储在内存中的。所以对于C程序本身来说,如果想找到相应被调用的数据,就要知道存储该数据的内存地址是多少,换言之,C程序通过已知的内存地址到相应的内

  • 我正在用C实现一个最小/最大堆,并试图在一般情况下实现它,因为我在将来的项目中需要它。 我们的想法是使用一个1D数组和一个通用比较器。 我的结构如下所示: 在调用heapalloc时,我为分配空间: } 一切都运行正常,直到我必须释放数据。下面的调用给出了一个seg错误,我不明白为什么---我只调用了malloc一次,数据是从它返回的指针! 任何帮助都将不胜感激。我看过很多关于类似主题的帖子,但到

  • 本文向大家介绍C语言安全之数组长度与指针实例解析,包括了C语言安全之数组长度与指针实例解析的使用技巧和注意事项,需要的朋友参考一下 1.C语言编码需要保证变长数组的长度参数位于合法范围之内 例如以下代码: 解决方案如下: 2.需要保证复制的目标具有足够的存储空间 参考代码如下所示: 3.不要把一个指向非数组对象的指针加上或减去一个整数 错误代码如下所示: 上面的代码试图用指针运算访问结构的元素,这

  • 本文向大家介绍汇编语言 跳转指令与C语言的条件分支,包括了汇编语言 跳转指令与C语言的条件分支的使用技巧和注意事项,需要的朋友参考一下 跳转指令 跳转指令也是一个组的指令,称为j组。其中jmp为无条件跳转,其余为条件跳转 上图为j组指令,可结合条件码访问指令加深理解 在机器指令水平上理解如何对跳转指令编码 如上图,通过反汇编软件得到机器指令与汇编语言,其中左边为机器指令编码,右边为对应汇编语言含义

  • C 语言的指针常常被人们认为是 C 语言中的灵魂所在,可以完成很多高难度的操作。但是更多的人感觉 C 语言的指针的存在如同噩梦一般,因为稍不注意,就会引起灾难性的后果。 不管你是不是喜欢 C 语言中的指针,我们都要学习这种看起来很神奇的东西。因为指针这个概念不是 C 语言首创的,而是苏联的计算机科学家首创的。 1. 什么是指针? 指针是什么?这是来自灵魂的拷问。其实指针也是一种变量。我们之前也说过