fengogo 发表于 2008-3-20 00:53

vc6 下反汇编代码:
char s[]="HELLO";
mov         eax,
mov         dword ptr ,eax
mov         cx,word ptr
mov         word ptr ,cx
12:   return s;
lea         eax,

可见,字符串"hello\0"位于一个固定的内存区域,如果你在其他地方也引用了"hello",也是编译指向该地址.我们通常称其为字符串常量.C/C++编译器会将字符串常量放于内存某个区域(通常我们称其为常量区),并用指针代替字符串引用.而不做优化的编译器有可能在内存中生成多个相同的拷贝. :0
ebp-8 是字符数组s的开始地址, 将该地址放于寄存器eax中返回. 但是堆栈指针寄存器esp在函数返回时,已经指向ebp+某常数的位置了, 亦即我们说的出栈, 但其低地址的内容是否被销毁了呢? 其实没有, 但如果又有进出栈的话, 原内存地址的内容可能被覆盖,即 s 数组可能会被覆盖. 从上面我们可以看出 s 数组的大小为dword + word =6字节 , 其实在"hello"+5处存放的是0 .
---------------------------------------------------------------------------------------------------
23:   int *p;
24:   int i = 32;
       dword ptr ,20h
25:   p = &i;
      lea         eax,
      mov         dword ptr ,eax
26:   return p;
      mov         eax,dword ptr

看第一句定义了一个指针,然而却没有对应的汇编代码.没错, 所有变量在最后其实都变成了对一个地址的引用,如ebp-8 处是i , ebp-4处是p;但是不同的变量占有不同字节的内存, 那么我们怎么知道要操作多少字节呢? 呵呵,这就是编译器的事了, i 是int , p是int *. 所以操作都是dword . 更复杂的, 对结构体是如何处理的呢?大家有空自己上网搜一搜.
cout char * 是输出字符串, cout int *是输出地址, 为什么会有乱码和输出地址应该可以总结出来了. 大家也可以想一下cout重载<<运算符的实现,嗯,应该也是靠判断末尾0来判断一个字符串的结束吧.
=========================================================
* f() 即取s 数组第一个字符( 因为f()返回的是 s 的地址) , 其实你还可以试试,*( f()+1) 就是e , +2 就是 l , 嗯, 这就是我们前面所说的, 函数虽然返回了, 但其原先的参数是否销毁了呢? 没有(也没有必要,难道特意增加指令去将这些内存单元置0?) .但当cout 函数调用时, s 数组有可能要被覆盖了. 因为有新的进出栈的动作.(所以产生了乱码)   .需要弄清楚的是函数调用的先后, cout << f()   , 先调用 f(), f()的返回值作为参数再调用operater<< 函数..

:)   以上是我的一点理解
页: 1 [2]
查看完整版本: 有请编程高手指导下!!!