我的四级哇哇哇哇。。。

老是差那么一点。。。就是过不去。。过不去。。。算了。。下次再来。。

上次差一道选择题。。这次差两道选择题。。就不能让我高兴几天。。哀。。继续学英语。。路漫漫其修远兮.....老子跟你死磕!

分析一个好玩的c语言程序[转自:看雪论坛]

前两天看到这么一个程序。代码如下:


#include <stdio.h>

int main()

{

     const short int c1 = 49920;

     const int c2 = 1073742008;


     int (*pf)() = (int (*)())&c2;


     printf(“%c%cn”, *(char*)pf()-19, *((char*)pf()+1)-49);

     return    0;

}


运行这个程序,屏幕上会出现一个 :)


很多人不懂其中的道理,在这里我给大家分析下代码。


先看这两句:


     const short int c1 = 49920;

     const int c2 = 1073742008;


定义了两个局部变量,数值转换成16进制为:


     const short int c1 = 0xc300;

     const int c2 = 0x400000b8;


其中变量c1的地址为:0x0012FF7C ,占两个字节,c2的地址为:0x0012FF78,占四个字节。这两个变量占据了连续的空间。变量赋值后,从0x12ff78开始的内存单元存储的字节码为:B8 00 00 40 00 C3 。对应的汇编码是:


     mov          eax,400000h

     ret



接下来的这句:


int (*pf)() = (int (*)())&c2;


分析如下:


定义了一个函数指针,参数为NULL,返回值为int类型。 这个函数指针,指向上面的汇编码。这样,后面执行pf(),就执行了这段汇编码。


继续分析下面这句代码:


printf(“%c%cn”, *(char*)pf()-19, *((char*)pf()+1)-49);


先看*(char*)pf()-19这个表达式, 执行了了pf指向的汇编代码,从汇编代码看,


这个函数调用后的返回值是0x400000,pf()前面的char *是把函数的返回值转换成一个


char*型指针,这个指针指向0x400000,前面再加个*号,表示取0x400000地址的内容,


由于是char *型指针,因此从这个地址取一个字节。


*(char*)pf()-19 表示的是从0x400000取出的字节内容再减去19。


接下来:*((char*)pf()+1)-49代表的意思是从0x400000 + 1的地址取出一个字节内容在减去49。


熟悉PE文件结构的朋友一定知道,对于exe文件0x400000是内存加载的基地址。

也就是说,0x400000 字节的内容对应的是0x4D,0x400001 字节的内容对应的是0x5A.

这是我们常说的pe文件起始的两个字节,”MZ”


这样,表达式*(char*)pf()-19的结果是0x3A ,表达式*((char*)pf()+1)-49的结果是0x29


察看ascii码表,输出就是我们看到的样子。


总结:

   别看一个这么小的程序,但是其中涉及的知识面比较广。

just have a fun

1.再逼我,再逼我就装死给你看!

2.老子不但有车,还是自行的!

3.喜欢的话哥我给你买…(意识到对方的怒意后)啊不,是“哥,我给您买!”

4.鄙视我的人那么多,你算老几?

5.打死我也不说,你还没使美人儿计呢!

6.我不但手气好,脚气也不错!

7.是镜子总会反光的!

8.帅有个P用?搞不好还不是被卒子给吃掉!

9.交给我你就不用放心了,没有错不了的事!

10.别紧张,我不是什么好人……

11.别担心女朋友跟着我会出事—-只要她一生蛋,我们便立即把蛋踩破,绝不让校长和父母知道!

12.别谢,谢完还怎么好意思向你收钱啊!

13.别和我说放马过来—-我是阿凡提!

14.你都不理我,那我成狗不理了!

15.明月几时有,去问易中天!

16.够不着吧,左脚踩右脚上试试

17.有的人活着,她已经死了.有的人活着,他早该死了!

18.你说…你喜欢我?其实…我一开始…其实我也…唉跟你说了吧,其实我也挺喜欢我自己的.

19.你是喝水,还是喝水,还是喝水?随你挑!

20.青山依旧在,只是有点红.

21.哎该说的说,不该说的小声说.

22.读书人的事,能说偷么

23.讨厌啦,不要问单身男人这种问题!

24.子曾经曰过:不要把我对你的容忍当成你不要脸的资本!

25.别以为我长的帅就认为我遥不可及高不可攀,其实我是海纳百川啊.

26.今天天气不错,又刮风又下雨的.

27.作为失败的典型,你实在是太成功了!

28.真想消灭这个小虫,奈何我的舌头不够长…

29.三个皮匠的脚臭死一个诸葛亮.

30.在这个红叶枫了的金秋……

31.一个切甲状腺激素,一个不切.

32.再烦我就把你绑草船上借箭去!

33.风萧萧兮易水寒,欠了钱兮你要还!

34.A:去哪吃?我没钱了.

   B:下馆子吧,我请—-水管子.

35.看有该落下的没落下吗?

36.我左青龙右白虎,腰间纹个米老鼠.

38.A:此仇不报难咽下这口恶气啊.

   B:那怎么才能让你咽气啊?

40.她胖得我大腿都拧不过她胳膊.

41.书山有路先干为净,学海无涯八宝作粥.

42.世界是我们的,也是儿子们的,但最终是那帮孙子们的.

43.作业吧我写了得了!

44.A:作业作了没有?

   B:坐了!喏,在P股底下,还热乎着呢…你要啊?那给你.

45.今天谁坐庄啊,连黑板都不擦!

46.这鞋多少钱一斤?

47.当初真是瞎了我的狗眼…

48.这个盲人难道是个瞎子?

49.一个人骂另一个人:“我真想往你脸上吐一泡狗屎!”

50.当年,俺们宿舍一哥们抢别人的包子吃,边吃边说:“就这玩意思儿,只配塞屁股。”

51.宿舍一个喝别人的开水,烫得跳起来,嘴里还叫:“天哪,这么烫,猪都受不了啊。”

52.我一初中同学好摸别人的脑袋,一天,摸着人家脑袋说:“脑袋挺圆啊。”那同学烦了,一拨拉他的手说:“少给我扯蛋。”

记录程序崩溃时的调用堆栈[转载]

简介
release版本的程序交付给用户使用后,如果应用程序崩溃了,怎么样通过windows提示的offset地址来定位源程序中对应的出错代码呢?这篇文章就来讨论这个问题。

建立调试环境
1.(VC 6)依次选择FileàNewàProjects,在列表中选择“MFC AppWizardEXE)”在“Project Name”中输入“Crash_Test”作为项目名,“OK”进入下一步。在“MFC Appwizard Step 1”对话框中选择“Dialog Based”单选框。“Finish”完成工程的建立,F7编译无误。
2.(VC 6)双击确定按钮,提示加入(重写)“OnOK”函数,OK,进入“CCrash_TestDlg::OnOK()”函数。
3.我们将在OnOK函数中构造一些能够引起程序崩溃的错误代码:
void CCrash_TestDlg::OnOK()
{
AfxGetApp()->GetMainWnd()->SetWindowText(_T(“Crash”));
int* pTest = NULL;
*pTest = 0; // 为空指针赋值,程序将崩溃
CDialog::OnOK();
}
加入“AfxGetApp()->GetMainWnd()->SetWindowText(_T(“Crash”));”的目的是使崩溃地址和“OnOK”的地址有一定偏移,使演示更具一般性。
4.(VC 6)首先设置Release编译(在BuildàSet as configuration中选择Win32 Release)。依次选择ProjectàSettings,选择“C/C++”tab页,Category中选择“Listing Files”,然后在“Listing file type”中选择“Assembly, Machine Code, and Source”,OK。这个选项将为每个源文件(*.cpp)生成机器码、汇编码和源代码的对应表,可以在“Release”目录下找到和查看这些文件。
5.(VC 6)依次选择ProjectàSettings,选择“Linktab页,Category中选择“Debug”,
钩选“Generate map file”,OK。这个选项将生成编译后的函数地址和函数名的对应表。

定位错误代码

1.现在运行“Release”目录下的测试程序,当点击“确定”按钮时,程序将崩溃。
Windows XP 会出现“Crash_Test.exe 遇到问题需要关闭。我们对此引起的不便表示抱歉。”…………
云云的对话框,在对话框的下方,单击“请单击此处”的超连接,在“错误签名”中,我们会得到如下信息:
AppName: crash_test.exeAppVer: 1 lass="pun">.0.0.1ModName: crash_test.exe
ModVer: 1.0.0.1Offset: 000014a0
其中的Offset值就是崩溃的地址啦,现在我们根据这个地址来定位源程序中出错的代码行。
2.用记事本打开“Release”目录下的,“Crash_Test.map”文件,在文件中会看到类似下面的内容:
0001:00000470?OnQueryDragIcon@CCrash_TestDlg@@IAEPAUHICON__@@XZ 00401470 fCrash_TestDlg.obj
0001:00000480?OnOK@CCrash_TestDlg@@MAEXXZ 00401480 fCrash_TestDlg.obj
0001:000004c0?BeginModalState@CWnd@@UAEXXZ 004014c0 f i Crash_TestDlg.obj
0001:000004d0?EndModalState@CWnd@@UAEXXZ 004014d0 f i Crash_TestDlg.obj
画线的部分就是各个函数编译运行后在内存中的相对地址 (高位部分是基地址,就不参与计算啦,基地址可能因机器不同而异,但相对地址都是一样的。) ,因为“Offset”指示的崩溃地址为“14a0”,
1480(OnOK地址) < 14a0(出错地址) < 14c0(BeginModalState地址),很显然,14a0的地址是在OnOK函数的地址范围内的,也就是说OnOK就是引起崩溃的函数。接下来再来确定出错的具体代码行。
3.因为OnOK是在“Crash_TestDlg.cpp”中实现的,因此,我们打开对应的“Crash_TestDlg.cod”文件,其中有如下代码:
?OnOK@CCrash_TestDlg@@MAEXXZ PROC NEAR; CCrash_TestDlg::OnOK, COMDAT
; 173: {
0000056pushesi
000018b f1movesi, ecx

; 175: int* pTest = NULL;
; 176: *pTest = 0;
; 177: CDialog::OnOK();
0001e8b cemovecx, esi
00020c7 05 00 00 00
00 00 00 00 00movDWORD PTR ds:0, 0
0002ae8 00 00 00 00call?OnOK@CDialog@@MAEXXZ; CDialog::OnOK
0002f5epopesi
; 178: }

很明显,这些就是OnOK函数的汇编表示和机器码表示,画线的地址就是函数中各个语句的相对(相对于函数首地址)地址。
在步骤1中,我们已经得
到,
Offset14a0OnOK的函数首地址为0480,现在,我们用14a01480就得到20(注意,这里都是16进制运算),可见,出错的代码行为:
00020c7 05 00 00 00 00 00 00 00 00movDWORD PTR ds:0, 0
对应上面注释的:
; 176: *pTest = 0;

聪明的“编译器”



聪明的“编译器”

这次讨论的话题是为什么编译器自作主张一般把“条件语句”取反。。

编译器把“条件语句”取反的原因是为了节省开销。。看下边这两个例子

例1.

while:

cmp a,10

jbe end

inc a

jmp while

end:

…….

例2.

while:

cmp a,10

ja continue

jmp end

continue:

inc a

jmp while

end:

…..

从这两个例子中可以看到,都是这么一句代码:while(a>10)a++;但例1用了6句,例2用了8句。。编译器

还是很聪明的嘛。。说根到底还是人弄出来的编译器。。还是人聪明。。呵呵

不过在有些时候不必取反,在后置条件(上面两例是前置条件)的情况下。。。。。

repeat:

inc a

cmp a,10

jl repeat

end:

……..

悟出点C的东西



刚上大一的时候,C语言的语法都是背会的,考试全是蒙的。即使会点,考完也就忘的差不多了

记得在学switch语句的时候,有这么个语法:

如果要在每个条件语句后边不加break,那么这个条件以下的所有条件都会执行一遍,当时只是背会了,

记住了,原理不懂,这几天通过看《黑客反汇编揭秘》这本书,里面提到这么个东东。。把原理弄懂了

。。

如果写个下面的程序

void main()

{

int a=10;

switch(a) {

case 1:

   printf(“1n”);

   break;

case 10:

   printf(“OKn”);

   break;

default:

   break;

}

}

那么对应的反汇编代码如下:

void main()

5:    {

0040D4D0   push        ebp

0040D4D1   mov         ebp,esp

0040D4D3   sub         esp,48h

0040D4D6   push        ebx

0040D4D7   push        esi

0040D4D8   push        edi

0040D4D9   lea         edi,[ebp-48h]

0040D4DC   mov         ecx,12h

0040D4E1   mov         eax,0CCCCCCCCh

0040D4E6   rep stos    dword ptr [edi]

6:        int a=10;

0040D4E8   mov         dword ptr [ebp-4],0Ah

7:        switch(a) {

0040D4EF   mov         eax,dword ptr [ebp-4]

0040D4F2   mov         dword ptr [ebp-8],eax

0040D4F5   cmp         dword ptr [ebp-8],1

0040D4F9   je          main+33h (0040d503)

0040D4FB   cmp         dword ptr [ebp-8],0Ah

0040D4FF   je          main+42h (0040d512)

0040D501   jmp         main+4Fh (0040d51f)

8:        case 1:

9:            printf(“1n”);

0040D503   push        offset string “1n” (00422f6c)

0040D508   call        printf (0040d750)

0040D50D   add         esp,4

10:           break;

0040D510   jmp         main+4Fh (0040d51f)

11:       case 10:

12:           printf(“OKn”);

0040D512   push        offset string “%sn” (0042210c)

0040D517   call        printf (0040d750)

0040D51C   add         esp,4

13:           break;

14:

15:       default:

16:           break;

17:       }

18:

19:   }

由此可以看到,如果不加break;这条语句,那么就没有下边的jmp那条语句,当然就会顺次向下执行。。

。。。还有一点需要注意,在执行switch(a)这条语句时

0040D4EF   mov         eax,dword ptr [ebp-4]

0040D4F2   mov         dword ptr [ebp-8],eax

对应这么两条汇编代码,这个程序只有一个变量,为什么会有[ebp-8],这可是第二个变量呀?秘密就在

switch这条语句在比较的时候生成自己的临时变量,所以在下边比较的时候会有:

0040D4F5   cmp         dword ptr [ebp-8],1

会和switch生成的临时变量相比较。。。。。

_MSC_VER含义

_MSC_VER 是什么意思?
这是微软的预编译控制。

在_MSC_VER较小时,它对一些东西的支持与新版不同


_MSC_VER分解如下:
MS:Microsoft(微软)的简写
C:MSC就是Microsoft出的C编译器。
VER:Version(版本)的简写。
全部加在一起就是:Microsoft的C编译器的版本


很多头文件中有
#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000
_MSC_VER 定义编译器的版本,VC++6.0就是1200  

#if   _MSC_VER   >   1000的意思就是如果编译器版本高于1000(VC++5.0)
关于编译器的版本信息可在command line里敲cl /?得到.示例:
C:Documents and SettingsAdministrator>cl /?

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80×86

Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
                          C/C++ COMPILER OPTIONS
                              -OPTIMIZATION-
/O1 minimize space                       /Op[-] improve floating-pt consistency

/O2 maximize speed                       /Os favor code space

/Oa assume no aliasing                   /Ot favor code speed

/Ob<n> inline expansion (default n=0)    /Ow assume cross-function aliasing

/Od disable optimizations (default)      /Ox maximum opts. (/Ogityb1 /Gs)

/Og enable global optimization           /Oy[-] enable frame pointer omission

/Oi enable intrinsic functions
                             -CODE GENERATION-
/G3 optimize for 80386                   /Gy separate functions for linker

/G4 optimize for 80486                   /Ge force stack checking for all funcs

/G5 optimize for Pentium                 /Gs[num] disable stack checking calls

/G6 optimize for Pentium Pro             /Gh enable hook function call

/GB optimize for blended model (default) /GR[-] enable C++ RTTI

/Gd __cdecl calling convention           /GX[-] enable C++ EH (same as /EHsc)

/Gr __fastcall calling convention        /Gi[-] enable incremental compilation

/Gz __stdcall calling convention         /Gm[-] enable minimal rebuild

/GA optimize for Windows Application     /EHs enable synchronous C++ EH

/GD optimize for Windows DLL             /EHa enable asynchronous C++ EH

(press <return> to continue)

/Gf enable string pooling                /EHc extern “C” defaults to nothrow

/GF enable read-only string pooling      /QIfdiv[-] enable Pentium FDIV fix

/GZ enable runtime debug checks          /QI0f[-] enable Pentium 0x0f fix
                              -OUTPUT FILES-
/Fa[file] name assembly listing file     /Fo<file> name object file

/FA[sc] configure assembly listing       /Fp<file> name precompiled header file

/Fd[file] name .PDB file                 /Fr[file] name source browser file

/Fe<file> name executable file           /FR[file] name extended .SBR file

/Fm[file] name map file
                              -PREPROCESSOR-
/C don’t strip comments                  /FI<file> name forced include file

/D<name>{=|#}<text> define macro         /U<name> remove predefined macro

/E preprocess to stdout                  /u remove all predefined macros

/EP preprocess to stdout, no #line       /I<dir> add to include search path

/P preprocess to file                    /X ignore “standard places”
                                -LANGUAGE-
/Zi enable debugging information         /Zl omit default library name in .OBJ

/ZI enable Edit and Continue debug info /Zg generate function prototypes

(press <return> to continue)

/Z7 enable old-style debug info          /Zs syntax check only

/Zd line number debugging info only      /vd{0|1} disable/enable vtordisp

/Zp[n] pack structs on n-byte boundary   /vm<x> type of pointers to members

/Za disable extensions (implies /Op)     /noBool disable “bool” keyword

/Ze enable extensions (default)
                              -MISCELLANEOUS-
/?, /help print this help message        /V<string> set version string

/c compile only, no link                 /w disable all warnings

/H<num> max external name length         /W<n> set warning level (default n=1)

/J default char type is unsigned         /WX treat warnings as errors

/nologo suppress copyright message       /Yc[file] create .PCH file

/Tc<source file> compile file as .c      /Yd put debug info in every .OBJ

/Tp<source file> compile file as .cpp    /Yu[file] use .PCH file

/TC compile all files as .c              /YX[file] automatic .PCH

/TP compile all files as .cpp            /Zm<n> max memory alloc (% of default)
                                 -LINKING-
/MD link with MSVCRT.LIB                 /MDd link with MSVCRTD.LIB debug lib

/ML link with LIBC.LIB                   /MLd link with LIBCD.LIB debug lib

/MT link with LIBCMT.LIB                 /MTd link with LIBCMTD.LIB debug lib

/LD Create .DLL                          /F<num> set stack size

(press <return> to continue)

/LDd Create .DLL debug libary            /link [linker options and libraries]
C:Documents and SettingsAdministrator>