﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Figo的狗窝-文章分类-Tutorial</title><link>http://www.cppblog.com/figoyao/category/12685.html</link><description>我也很想让世界变得更好，可是上帝却不开放源代码。</description><language>zh-cn</language><lastBuildDate>Sun, 03 Jan 2010 11:07:50 GMT</lastBuildDate><pubDate>Sun, 03 Jan 2010 11:07:50 GMT</pubDate><ttl>60</ttl><item><title>游戏辅助工具开发教程-从入门到精通之A2_7篇</title><link>http://www.cppblog.com/figoyao/articles/104700.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:37:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104700.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104700.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104700.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104700.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104700.html</trackback:ping><description><![CDATA[作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a>
<p>本节我们以<strong><a  href="http://www.duotegame.com/soft/4862.html" target="_blank">红警2[共和国之辉]</a></strong>为上手的第一个游戏，首先是作为<a  href="http://www.figoyao.com/blog/2009/12/06/135/" target="_blank">复习</a>，其次是引入新内容：马上我将带领大家学习Win32编程。时间过得真快，希望你这段时间也有一定的进步。</p>
<p>首先给出<a  href="http://figoyao.com/blog/file/RACheatGame.rar" target="_blank">源码和Bin文件</a>，这次有<strong>控制台</strong>和<strong>Win32</strong>两个版本，阅读源码时候最好结合<a  href="http://msdn.microsoft.com/" target="_blank">MSDN</a>。<br>
Win32版本的截图：<br>
<a  href="http://www.figoyao.com/blog/2009/12/10/190/null"><img  src="http://farm5.static.flickr.com/4007/4173385261_1cf7e078d0_o.jpg" class="alignnone" title="Windowsra1" alt="" height="160" width="278"></a><br>
<a  href="http://www.figoyao.com/blog/2009/12/10/190/null"><img  src="http://farm3.static.flickr.com/2664/4173385265_0f58aea650_o.jpg" class="alignnone" title="windustry" alt="" height="157" width="458"></a><br>
控制台版本的截图：<br>
<a  href="http://www.figoyao.com/blog/2009/12/10/190/null"><img  src="http://farm3.static.flickr.com/2531/4173385267_4bd637d41b_o.jpg" class="alignnone" title="ConsoleRA" alt="" height="154" width="683"></a><br>
一个小Tip：红警窗口模式，红警安装完后有一个叫做Ra2.exe的文件，把它的快捷键发送到桌面，然后右键-&gt;属性，在路径名最后输入<span style="color: #ff0000;">-win</span>启动参数：<br>
<a  href="http://www.figoyao.com/blog/2009/12/10/190/null"><img  src="http://farm3.static.flickr.com/2680/4173486179_17c063e963_o.jpg" class="alignnone" title="winramodel" alt="" height="209" width="369"></a><br>
所有源码是在VC6上编写并编译的。下载完文件的读者很快会发现控制台的程序比Win32还大，这两个执行文件我没有做任何处理。<a  href="http://www.figoyao.com/blog/2009/12/06/135/" target="_blank">前面的章节</a>我们分析过一个文字性质的游戏Demo，这里涉及的大部分原理性知识是一样的。重复的知识我就不深入讲解了。<br>
在使用CheatEngine定位需要修改的地址后，我们就开始动手了。这次不必像上次那样还得自己输入游戏进程的PID，我们交给程序来做。</p>
<p>源码还是比较简单的，有疑问的话看看前面的章节的那次讲解。如果还不明白，可以留言。下次开始我就要进入Windows应用程序设计的讲解了。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/10/190" target="_blank">http://www.figoyao.com/blog/2009/12/10/190</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104700.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:37 <a href="http://www.cppblog.com/figoyao/articles/104700.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A2_6篇</title><link>http://www.cppblog.com/figoyao/articles/104699.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:36:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104699.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104699.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104699.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104699.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104699.html</trackback:ping><description><![CDATA[作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a>
<p>本节承接<a  href="http://www.figoyao.com/blog/2009/12/09/178/" target="_blank">上节</a>继续讲汇编中的指令。</p>
<p>一、标志位操作指令<br>
<a  href="http://farm3.static.flickr.com/2670/4170522907_cc5478b718_o.jpg"><img  src="http://farm3.static.flickr.com/2670/4170522907_cc5478b718_o.jpg" class="alignnone" title="flags" alt="" height="706" width="834"></a><br>
1、<strong>进位CF标志操作指令</strong><br>
清零标志位CLC：CF&lt;-0<br>
置位标志位STC：CF&lt;-1<br>
标志位取反CMC：CF&lt;-NOT CF<br>
2、<strong>方向位DF操作指令</strong><br>
清零方向位CLD：DF&lt;-0<br>
置位方向位STD：DF&lt;-1<br>
3、<strong>中断允许位IF操作指令</strong><br>
清零CLI：IF&lt;-0<br>
置位STI：IF&lt;-1<br>
4、<strong>取标志位操作指令</strong><br>
LAHF：AH&lt;-EFlags低8位<br>
SAHF：EFlags低八位&lt;-AH<br>
5、标志位堆栈操作指令<br>
PUSHF/PUSHFD：16bit/32bit标志位进栈<br>
POPF/POPFD：16bit/32bit标志位出栈</p>
<p>二、算术运算指令<br>
1、<strong>加法指令</strong><br>
1）、<strong>普通加法指令ADD</strong><br>
ADD&nbsp; reg/mem,reg/mem/imm<br>
受影响标志位：AF/CF/OF/PF/SF/ZF<br>
2）、<strong>带进位的加法ADC<br>
</strong>ADC&nbsp; reg/mem,reg/mem/imm<br>
受影响标志位：AF/CF/OF/PF/SF/ZF<br>
该指令和1）中唯一不同的是除了执行1）中加法外还要加上CF。<br>
3）、<strong>加1指令INC<br>
</strong>INC&nbsp; reg/mem<br>
受影响标志位：AF/OF/PF/SF/ZF<br>
4）、<strong>交换加法指令XADD</strong><br>
XADD&nbsp; reg/mem,reg<br>
该指令首先交换两个操作数的值，然再做加法，相当于以下两条指令：<br>
XCHG&nbsp; reg/mem,reg<br>
ADD&nbsp; reg.mem,reg<br>
2、<strong>减法指令</strong>[和加法指令相反]<br>
1）、普通减法SUB<br>
2）、带借位的减法SBB<br>
除了1）中减法还有减去CF<br>
3）、减1指令DEC<br>
4）、求补指令NEG<br>
NEG&nbsp; reg/mem<br>
受影响标志位：AF/CF/OF/PF/SF/ZF<br>
执行结果：操作数=0-操作数<br>
3、<strong>乘法指令</strong><br>
分为带符号乘法和无符号乘法，区别在于：数据的最高位是作为<strong>符号</strong>还是<strong>数值</strong>参与运算。<br>
1）、无符号乘法MUL<br>
MUL&nbsp; reg/mem<br>
受影响标志位：CF/OF<br>
我们知道乘法要有乘数和被乘数，指令中只有一个操作数，所以我们必须知道第二个操作数在哪里。Intel处理的方式是，被乘数提前存在EAX中，然后与给出的乘数相乘，结果放在规定的寄存器中：</p>
<table bgcolor="#ffffff" border="1" bordercolor="#000000">
    <tbody>
        <tr>
            <td><strong>乘数位数</strong></td>
            <td><strong>隐含的被乘数</strong></td>
            <td><strong>乘积存放位置[高-低]</strong></td>
            <td><strong>举例</strong></td>
        </tr>
        <tr>
            <td>8</td>
            <td>AL</td>
            <td>AX</td>
            <td>MUL&nbsp; CL</td>
        </tr>
        <tr>
            <td>16</td>
            <td>AX</td>
            <td>DX-AX</td>
            <td>NUL&nbsp; CX</td>
        </tr>
        <tr>
            <td>32</td>
            <td>EAX</td>
            <td>EDX-EAX</td>
            <td>MUL&nbsp; ECX</td>
        </tr>
    </tbody>
</table>
<p>2)、有符号乘法IMUL<br>
IMUL&nbsp; reg/mem<br>
受影响标志位：CF/OF<br>
其操作数都作为有符号数相乘。<br>
4、<strong>除法指令<br>
</strong>1）无符号除法<br>
DIV&nbsp; reg/mem<br>
不影响标志位<br>
被除数默认存放规则如下：</p>
<table bgcolor="#ffffff" border="1" bordercolor="#000000">
    <tbody>
        <tr>
            <td>除数位数</td>
            <td>隐含的被除数</td>
            <td>商</td>
            <td>余数</td>
        </tr>
        <tr>
            <td>8</td>
            <td>AX</td>
            <td>AL</td>
            <td>AH</td>
        </tr>
        <tr>
            <td>16</td>
            <td>DX-AX</td>
            <td>AX</td>
            <td>DX</td>
        </tr>
        <tr>
            <td>32</td>
            <td>EDX-EAX</td>
            <td>EAX</td>
            <td>EDX</td>
        </tr>
    </tbody>
</table>
<p>2）有符号除法<br>
IDIV&nbsp; reg/mem<br>
受影响标志位：AF/CF/OF/PF/SF/ZF</p>
<p>三、逻辑运算指令<br>
1、<strong>逻辑与AND指令<br>
</strong>AND&nbsp;&nbsp;reg/mem,reg/mem/imm<br>
受影响的标志位：CF(0)/OF(0)/SF/PF/ZF<br>
执行过程：源操作数和目的操作数进行逻辑与运算，结果存放在目的操作数。<br>
<strong>2、逻辑或OR指令</strong><br>
OR&nbsp;&nbsp;reg/mem,reg/mem/imm<br>
受影响的标志位：CF(0)/OF(0)/SF/PF/ZF<br>
执行过程：源操作数和目的操作数进行逻辑或运算，结果存放在目的操作数。<br>
<strong>3、逻辑非NOT指令</strong><br>
NOT&nbsp;&nbsp;reg/mem<br>
受影响的标志位：无<br>
执行过程：把操作数按位取反。<br>
<strong>4、逻辑异与XOR指令</strong><br>
XOR&nbsp;&nbsp;reg/mem,reg/mem/imm<br>
受影响的标志位：CF(0)/OF(0)/SF/PF/ZF<br>
执行过程：源操作数和目的操作数进行逻辑异与运算，结果存放在目的操作数。<br>
异或就是两数相同则结果为0，反之为1。<br>
<strong>5、测试指令TEST</strong><br>
TEST&nbsp;&nbsp;reg/mem,reg/mem/imm<br>
受影响的标志位：SF/PF/ZF<br>
test类似and指令，但只是逻辑与进行测试，根据结果修改标志位，却不改变操作数的值。</p>
<p>四、跳转指令<br>
1、<strong>无条件跳转指令<br>
</strong>JUMP&nbsp; reg/mem/imm<br>
执行结果是跳转到指定地址，然后继续执行代码。按照<a  href="http://www.intel.com/Assets/PDF/manual/253666.pdf" target="_blank">Intel指令手册</a>上的说法，jump一共有4中不同的跳法，这比起跳大神的神棍的跳法可少多了：<br>
1）、Near Jump<br>
这种跳法为啥叫near呢，因为它跳来跳去都是在一个代码段跳，所以又称作段内转移。这就好比你遛狗，总是不出你的县城，这就叫<strong>near遛</strong>：）<br>
2）、Short Jump<br>
Short Jump是Near Jump的一种，但是比Near还有Near，它跳转的范围是[-128,127]。这时候你可能只是在你的村子溜溜狗而已，太Short了。<br>
3）、Far Jump<br>
一看Far就是那么有气势，此时跳转的范围已经扩大到其他段，你连其他段都能跳，本段当然更可以了，但是要注意，此时你可以跳转到的目标代码的特权级别必
须和当前代码相同：如果你是用户权限，你跳转到系统权限的代码就会出错。这时候你已经厌倦在小县城遛狗了，终于，你鼓起勇气，决定去丈母娘的县城遛狗
╮(╯_╰)╭。<br>
4）、Task Switch<br>
这个跳转一下就从你当前任务的代码到别的任务里面执行代码了，可以说是跳的最远的。<br>
2、<strong>条件跳转指令<br>
</strong>顾名思义，得依据条件来跳转，在这里，条件指的是标志寄存器的一个或多个标志位，如果满足条件就跳转否则继续执行跳转指令下面的代码。在介绍指令的时候，首先说下助记符中字母的含义：<br>
<strong><span style="color: #ff0000;">E</span></strong>：Equal[相等]<br>
<span style="color: #ff0000;"><strong>A</strong></span>：Above[大于]<br>
<span style="color: #ff0000;"><strong>B</strong></span>：Below[小于]<br>
<span style="color: #ff0000;"><strong>G</strong></span>：Greater Than[大于]<br>
<span style="color: #ff0000;"><strong>L</strong></span>：Less Than[小于]<br>
<strong><span style="color: #ff0000;">N</span></strong>:Not[不]<br>
条件跳转大体上分为2类：<br>
<strong>直接标志位测试</strong></p>
<table bgcolor="#ffffff" border="1" bordercolor="#000000">
    <tbody>
        <tr>
            <td><strong>助记符</strong></td>
            <td><strong>测试条件</strong></td>
            <td><strong>跳转条件</strong></td>
        </tr>
        <tr>
            <td>JC</td>
            <td>CF=1</td>
            <td>有进位</td>
        </tr>
        <tr>
            <td>JNC</td>
            <td>CF=0</td>
            <td>无进位</td>
        </tr>
        <tr>
            <td>JZ/JE</td>
            <td>ZF=1</td>
            <td>为0或相等</td>
        </tr>
        <tr>
            <td>JNZ/JNE</td>
            <td>ZF=0</td>
            <td>不为0或不等</td>
        </tr>
        <tr>
            <td>JS</td>
            <td>SF=1</td>
            <td>负数</td>
        </tr>
        <tr>
            <td>JNS</td>
            <td>SF=0</td>
            <td>正数</td>
        </tr>
        <tr>
            <td>JO</td>
            <td>OF=1</td>
            <td>溢出</td>
        </tr>
        <tr>
            <td>JNO</td>
            <td>OF=0</td>
            <td>无溢出</td>
        </tr>
        <tr>
            <td>JP/JPE</td>
            <td>PF=1</td>
            <td>偶数</td>
        </tr>
        <tr>
            <td>JNP/JPO</td>
            <td>PF=0</td>
            <td>奇数</td>
        </tr>
    </tbody>
</table>
<p><strong>间接标志位测试</strong></p>
<table bgcolor="#ffffff" border="1">
    <tbody>
        <tr>
            <td><strong>类别</strong></td>
            <td><strong>助记符</strong></td>
            <td><strong>测试条件</strong></td>
            <td><strong>跳转条件</strong></td>
        </tr>
        <tr>
            <td>无符号数</td>
            <td>
            <table bgcolor="#ffffff" border="1">
                <tbody>
                    <tr>
                        <td>JA/JNBE</td>
                    </tr>
                    <tr>
                        <td>JAE/JNB</td>
                    </tr>
                    <tr>
                        <td>JB/JNAE</td>
                    </tr>
                    <tr>
                        <td>JBE/JNA</td>
                    </tr>
                </tbody>
            </table>
            </td>
            <td>
            <table bgcolor="#ffffff" border="1">
                <tbody>
                    <tr>
                        <td>CF=0且ZF=0</td>
                    </tr>
                    <tr>
                        <td>CF=0</td>
                    </tr>
                    <tr>
                        <td>CF=1</td>
                    </tr>
                    <tr>
                        <td>CF=1或ZF=1</td>
                    </tr>
                </tbody>
            </table>
            </td>
            <td>
            <table bgcolor="#ffffff" border="1">
                <tbody>
                    <tr>
                        <td>大于/大于等于</td>
                    </tr>
                    <tr>
                        <td>大于等于</td>
                    </tr>
                    <tr>
                        <td>小于/小于等于</td>
                    </tr>
                    <tr>
                        <td>小于等于</td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
        <tr>
            <td>有符号数</td>
            <td>
            <table bgcolor="#ffffff" border="1">
                <tbody>
                    <tr>
                        <td>JG/JNLE</td>
                    </tr>
                    <tr>
                        <td>JGE/JNL</td>
                    </tr>
                    <tr>
                        <td>JL/JNGE</td>
                    </tr>
                    <tr>
                        <td>JLE/JNG</td>
                    </tr>
                </tbody>
            </table>
            </td>
            <td>
            <table bgcolor="#ffffff" border="1">
                <tbody>
                    <tr>
                        <td>ZF=0且SF=OF</td>
                    </tr>
                    <tr>
                        <td>SF=OF</td>
                    </tr>
                    <tr>
                        <td>SF!=OF</td>
                    </tr>
                    <tr>
                        <td>SF!=OF或ZF=1</td>
                    </tr>
                </tbody>
            </table>
            </td>
            <td>
            <table bgcolor="#ffffff" border="1">
                <tbody>
                    <tr>
                        <td>大于/大于等于</td>
                    </tr>
                    <tr>
                        <td>大于等于</td>
                    </tr>
                    <tr>
                        <td>小于/小于等于</td>
                    </tr>
                    <tr>
                        <td>小于等于</td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>以上是根据<a  href="http://www.intel.com/Assets/PDF/manual/253666.pdf" target="_blank">Intel指令手册</a>（<em>3-542 vol.2A</em>）整理，有些教材的跳转条件是错误的。</p>
<p>五、<strong>其他指令<br>
</strong>本教程不可能把所有指令都介绍完整，有些指令需要在实践的过程中自己查阅手册，学习一门技能从来都不是一蹴而就的。<br>
1、nop指令<br>
nop是空指令，就是占位，除此没有任何作用。<br>
2、call指令<br>
call&nbsp; reg/mem/imm<br>
call指令执行的过程是，首先把当前EIP或CS加EIP压入堆栈，然后跳转到call后操作数指定地址执行代码。手册里介绍了四种跳转，这里只讲下
Near Call和Far
Call。前者call呼叫的函数在同一代码段，此时只需把EIP压栈即可；而后者call呼叫的是不同段，需要把当前段的选择子和EIP均压入栈。<br>
3、ret/retn/retf<br>
ret&nbsp; reg/mem/imm[可选]<br>
retn是近返回；retf是远返回。</p>
<p>至此汇编语言的基本内容就介绍完了。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/09/182" target="_blank">http://www.figoyao.com/blog/2009/12/09/182</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104699.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:36 <a href="http://www.cppblog.com/figoyao/articles/104699.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A2_5篇</title><link>http://www.cppblog.com/figoyao/articles/104698.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:35:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104698.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104698.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104698.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104698.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104698.html</trackback:ping><description><![CDATA[作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a>
<p>本节主要讲解汇编中的指令。</p>
<p>下载一个<a  href="http://www.52z.com/soft/19908.html" target="_blank">指令查看器</a>，用于初期查询之用。在讲指令之前，我先简单说下汇编中有关变量定义的相关内容。</p>
<p>一、标识符和表达式<br>
汇编中，标号、内存变量、子程序名和宏定义名等都叫做标识符，最多由31个字母、数字和特殊字符（?、@、_、$）等组成，不能以数字开头。汇编中是不区分大小写的。并且标识符不能和编译器保留关键字重名，如：<br>
<strong>正确的</strong>：msg、_Student、?iRand<br>
<strong>错误的</strong>：2boys、mov、eax<br>
这里需要注意的是，ABCH和0ABCH，前者是标识符，后者是16进制数。在实际编程中一般要求十六进制数以0或0x开头。<br>
1、内存变量定义<br>
一般我们常用的有字节(byte)、字(word)和双字(doubleword)，浮点数在后面会涉及。定义变量的一般形式是：<br>
<strong>变量名</strong> <strong>类型</strong> 表达式1,表达式2,&#8230;&#8230;表达式n<br>
表达式个数取决于实际定义；变量名命名规则上面已经介绍；类型常用的有<strong>db</strong>(byte)、<strong>dw</strong>(word)、<strong>dd</strong>(doubleword)。各表达式之间用逗号隔开，最后一个表达式没有逗号；如果变量没有在定义时初始，表达式用问号（<strong>?</strong>）代替。例子如下：<br>
1）、定义一个名为iPlayerHP的单字变量，初始值为200<br>
iPlayer&nbsp;&nbsp;<strong>dw </strong> 200<br>
2）、定义一个名为msgname的ASCII字符串变量，初始值为&#8217;I am Figo Yao.&#8217;<br>
msgname&nbsp; <strong>db</strong> &#8216;I am Figo Yao.&#8217;<br>
3）、定义一个名为iTime的双字变量，初始值不确定<br>
iTime&nbsp; <strong>dd</strong> ?<br>
4）、定义一个长度为100的，名为qqNUM的双字数组变量，初始值不确定<br>
qqNum&nbsp; <strong>dd</strong> 100&nbsp; <strong>dup</strong>(?)<br>
dup是关键字，用在重复定义的情形。<br>
其一般用法如下：<br>
次数&nbsp; dup&nbsp; (表达式1,表达式2,&#8230;&#8230;表达式n)<br>
括号中是被重复的部分，如<br>
qqNum&nbsp; <strong>dd</strong> 100&nbsp; <strong>dup</strong>(10000,10010)<br>
这个表达式的结果是：qqNum数组长度是200，数值是10000和10010交替重复。即<br>
qqNum[200] = {10000,10010,10000,10010&#8230;10000,10010,10000,10010};<br>
5）、结构类型定义<br>
其语法为：<br>
结构变量名&nbsp; STRUC<br>
数据定义<br>
结构变量名&nbsp; ENDS<br>
比如我们先来定义一个时间结构：<br>
stTime&nbsp; <span style="color: #008000;">struc</span><br>
iHour&nbsp; db&nbsp; 0&nbsp;&nbsp;&nbsp; <span style="color: #008000;">//偏移量是0<br>
</span> iMin&nbsp;&nbsp;&nbsp;&nbsp; db&nbsp; 0&nbsp;&nbsp;&nbsp; <span style="color: #008000;">//偏移量是1<br>
</span> iSec&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db&nbsp; 0&nbsp;&nbsp;&nbsp; <span style="color: #008000;">//偏移量是2<br>
</span>stTime&nbsp; <span style="color: #008000;">struc<br>
<span style="color: #000000;">对于没有名字的结构体，也可以用偏移量来访问。比如我们初始化一个stTime的结构体(假设eax指向分配的地址)和一个保存秒的变量：<br>
TestTime &nbsp;&nbsp; <strong>stTime</strong> &lt;10,25,0&gt;<br>
</span></span>TestSec&nbsp;&nbsp;&nbsp; <strong>db</strong> ?<br>
TestSec&nbsp;&nbsp;&nbsp; <strong>equ</strong> TestTime.iSec<br>
我们看到取结构体分量使用的是点(.)加变量名。<span style="color: #ff0000;">equ</span>是等于的意思，属于关键字。和上面最后一句等价的语句是：<br>
TestHour&nbsp;&nbsp;&nbsp; <strong>equ</strong> byte <strong>ptr</strong> [eax+2]<br>
ptr是指明数据长度，属于关键字，一般用法为：<br>
数据类型&nbsp;&nbsp;&nbsp; ptr&nbsp;&nbsp;&nbsp; 地址<br>
操作的结果是指明操作数的地址和类型。因为我们第二种获取结构体变量的方法使用了偏移量，得到存放数据的地址后，还需要告诉CPU从这个地址读取什么类型的数据，因为我们的<strong>秒变量</strong>是字节，所以ptr前面的是byte。</p>
<p>二、汇编指令<br>
首先规定一些代号以便于讲解：<br>
reg：寄存器<br>
mem：内存单元<br>
imm：立即数<br>
这些代号后面如果跟数字，则表示是多少bit，如：reg16表示16bit的寄存器；立即数的意思是直接的具体的数值，如0&#215;1234H。<br>
下面的内容大体和教材分类一样：<br>
1、数据传输指令<br>
1）、<strong>mov</strong>指令（move）<br>
mov指令的格式如下：<br>
mov&nbsp; op1,op2<br>
[mov&nbsp;&nbsp; reg/mem,reg/mem/imm]<br>
执行的结果是op2的值被传送（复制）到op1。<br>
如：<br>
mov&nbsp; eax,0&#215;1234h<br>
mov&nbsp; dword ptr [40995b],ecx<br>
mov&nbsp; es,dx<br>
<a  href="http://www.figoyao.com/blog/2009/12/09/178/null"><img  src="http://farm3.static.flickr.com/2593/4170248411_af8a8c5838_o.jpg" class="alignnone" title="direction" alt="" height="244" width="383"></a><br>
但是mov有几条规定需要注意：<br>
<strong>a</strong>、两个操作数类型必须相同，即同为db、dw或dd等类型。<br>
<strong>b</strong>、mov指令不能用于改变cs寄存器，否则会导致程序异常错误。如mov&nbsp; cs,ax 是禁止的;但mov&nbsp; ax,cs 是允许的。<br>
<strong>c</strong>、两个操作数不能同为下列段寄存器的组合：DS、ED、SS、FS、GS，如：mov&nbsp; es,ds 是错误的用法，如果一定要把ds的数据传给es，可以如下操作：<br>
mov&nbsp; ax,ds<br>
mov&nbsp; es,ax<br>
<strong>d</strong>、两个操作数不能同为内存单元，如mov&nbsp; [1234h],[2345h] 是错误的用法。<br>
<strong>e</strong>、指令指针EIP不能作为mov的操作数。<br>
2）、<strong>movsx</strong>/<strong>movzx</strong>（传送填充指令）<br>
2a）、movsx是符号填充指令（move with sign-extend）<br>
movsx&nbsp; op1,op2<br>
一般op2的bit数比op1少，在mov中是禁止这么传送数据的，但是movsx可以，执行结果是op1低位由op2填充，op1剩下的高位由op2的符号位填充。<br>
如：<br>
movsx&nbsp; eax,10H<br>
执行完后，eax的低五位为二进制10000，从第六个bit起的高位均填充1。<br>
2b）、movzx是零填充指令（move with zero-extend）<br>
与符号填充唯一的区别是使用0来填充高位。<br>
3）、交换指令<strong>xchg</strong>（Exchange）<br>
格式如下：<br>
xchg&nbsp; reg/mem,reg/mem<br>
xchg&nbsp; op1,op2<br>
执行结果是op1中存储原来op2的数据，op2中存储原来op1的数据。<br>
4）、取有效地址指令<strong>lea</strong>（load effective address）<br>
格式如下：<br>
lea&nbsp; reg,mem<br>
lea&nbsp; op1,op2<br>
执行结果是内存单元op2的有效地址（偏移地址）赋给op1。<br>
在汇编中还有一种获取有效地址的方法，使用offset<strong><span style="color: #ff0000;">伪指令</span></strong>，如：<br>
lea&nbsp; eax,dword ptr [1234H]和mov&nbsp; eax,offset&nbsp; dword ptr
[1234H]是等价的，但是后者的执行速度更快。不过当去堆栈处地址时候是不可以用offset的，因为offset在编译时实际上编译器会先求出变量
地址，然后用地址作为立即数进而合成机器码；而lea是CPU的指令，是在程序运行时候求的，所以可以处理动态地址，如：lea&nbsp; eax,dword
ptr [ebp-5ch] 的情况就不可以用offset。<br>
5）、堆栈操作指令<br>
进出栈操作<br>
push&nbsp; reg/mem/imm<br>
执行push指令后堆栈指针ESP依据进栈数据类型自动修改，如push&nbsp; eax，因为eax是4个字节，所以push执行完后，esp=esp-4，[esp]&lt;-eax。与之对应的是pop出栈指令。<br>
pusha/pushad<br>
执行该指令会依次把EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI存入堆栈，这些通用寄存器的值是执行指令前一瞬间的快照值，即要执行
这条指令的一瞬间，我们把此时的通用寄存器的值记录下来，那么这条指令就是把我们记录的值按照上面顺序依次存入堆栈。pusha是16bit的版
本，pushad是32bit的版本。与之对应的是popa和popad，这条指令是把刚才存储的快照依照和上面存储过程的逆序恢复。</p>
<p>这节就暂时讲到这里，下次我们接着讲指令。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/09/178/" target="_blank">http://www.figoyao.com/blog/2009/12/09/178/ </a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104698.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:35 <a href="http://www.cppblog.com/figoyao/articles/104698.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A2_4篇</title><link>http://www.cppblog.com/figoyao/articles/104697.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:34:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104697.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104697.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104697.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104697.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104697.html</trackback:ping><description><![CDATA[作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a>
<p>本节主要讲解汇编中的操作数寻址。</p>
<p>先来一张IDA反汇编的截图：<br>
<a  href="http://www.figoyao.com/blog/2009/12/08/159/null"><img  src="http://farm3.static.flickr.com/2729/4169306976_b50b9cde00_o.jpg" class="alignnone" title="idadecode" alt="" height="479" width="732"></a><br>
我们看到汇编代码的形式为：<br>
<strong>指令</strong> <span style="color: #008000;">操作数1</span>[可选],<span style="color: #008000;">操作数2</span>[可选]<br>
中括号（[]）内的可选，指的是操作数的个数取决于指令的类型：如果是单操作数指令，比如<strong><span style="color: #003366;">push</span></strong>指令，那么<span style="color: #008000;">操作数2（<span style="color: #ff0000;">下简称<strong>op2</strong></span>）</span>是没有的；如果是双操作数指令，比如<span style="color: #003366;"><strong>mov</strong></span>，两个操作数都有；如果是无操作数指令则后面什么也不跟。在进一步讲解之前，我先简单讲下<strong><span style="color: #003366;">mov</span></strong>指令，该指令的作用是把op2的值复制到op1。<strong>从&#8230;到&#8230;</strong>是一个具有方向的句式，我们以后把op1叫做<strong>目的操作数</strong>，op2则叫<strong>源操作数</strong>，因为是<strong>从</strong>op2<strong>到</strong>op1╮(╯_╰)╭。虽然下面是以mov指令作为讲解的对象，以下规则是可以拓展到所有指令的。</p>
<p>毛主席教导我们：有的放矢，抓住老鼠的猫就是好猫！哎，抓老鼠不是邓爷爷教导的吗？汗&#8230;下面我的讲解和大部分教科书的方式有很大不同，但是我可以保证你看完之后获得的信息量<strong>&gt;=</strong>教科书。相信我，没错的：）。</p>
<p>首先思考一下：指令存在的目的是什么？CPU是做什么的？我们一般称CPU为中央处理器，处理什么呢？当然是二进制数据了，我偷偷告诉你，其实CPU只会加减法而已。这样说来，<a  href="http://www.intel.com/" target="_blank">Intel</a>也不是什么高科技公司嘛[<a  href="http://www.loongson.cn/" target="_blank">龙芯</a>大笑]。我们小学就学过加减法，不就是两个数相加减吗？是的，所谓寻址，就是告诉CPU做加减法的数存在哪里，仅此而已。<a  href="http://www.figoyao.com/blog/2009/12/07/147/" target="_blank">前面</a>已经讲过，计算机里面能存储数据的地方有：<strong>硬盘</strong>等外部存储设备、<strong>内存</strong>、<strong>高速缓存</strong>和<strong>寄存器</strong>。我们可以无视硬盘和高速缓存：前者不直接和CPU打交道，后者暂时不直接和我们打交道。这样的话就我们关心的就只有内存和寄存器了，那我们要做的就是搞明白在汇编里面是如何表示内存地址的.为什么不管寄存器寻址呢？因为寄存器属于CPU内部固件，所以CPU可以<strong>直接</strong>访问。就好比，你去别人家拜访的话首先要知道别人的地址；在自己家里的话，想去哪个房间直接去喽，当然不要地址了！那么我们下面主要讲的就是内存地址的表示，上节教程说过，32位CPU表示地址的格式为：<br>
<a  href="http://www.figoyao.com/blog/2009/12/08/159/null"><img  src="http://farm3.static.flickr.com/2664/4169370494_0902358298_o.jpg" class="alignnone" title="addr32" alt="" height="97" width="461"></a><br>
第一个是段选择子，第二个是偏移地址[又叫有效地址]。至于得到这2个参数后如何寻址<a  href="http://www.figoyao.com/blog/2009/12/07/147/" target="_blank">上节已经说过了</a>。对于这2个参数在汇编语言中是如何给出的呢？比如我把op2复制到op1，按道理说，应该这样写：mov eax,ds:[1234H]。这句中的ds是数据段寄存器作为选择子，后面的[1234]表示偏移地址，记住<strong>一定要加中括号</strong>！不过，Intel的游戏规则是这么说的：你这么做，是可以的，但经过我们砖家的研究发现啊，大部分情况使用<strong>默认的段选择子</strong>更省事。说完这些，Inte在它的<a  href="http://www.intel.com/Assets/PDF/manual/253665.pdf" target="_blank">指令手册</a>（参见：Vol1 3-29页）中给出了默认的段选择子的规则（下面的英语比高考阅读简单多了）：<br>
<a  href="http://farm3.static.flickr.com/2667/4169414622_1c0386e72f_o.jpg"><img  src="http://farm3.static.flickr.com/2667/4169414622_1c0386e72f_o.jpg" class="alignnone" title="IntelAddrprefix" alt="" height="386" width="956"></a><br>
由上表我们看到：代码段默认的选择子是CS，堆栈段默认的选择子是SS，数据段默认的选择子是DS，字符串默认的选择子是ES。返回来看最上面那张反汇编图，我们看下地址为00401004处的汇编代码：<strong><span style="color: #003366;">mov&nbsp;&nbsp;</span>&nbsp;&nbsp; esi, [esp+<span style="color: #008000;">48h</span>+<span style="color: #008000;">hInstance</span>]。</strong>中括号里面的是偏移地址（hInstance和48H一样，都是数值，在运行时由Windows系统传递具体数值进行初始化），但是没有指明选择子，由于是要把<strong>堆栈</strong>中的数据复制到ESI中，结合上面的规定，我们知道选择子是SS。所以<strong>还原</strong>一下这个语句应该这么写：<strong><span style="color: #003366;">mov&nbsp;&nbsp;</span>&nbsp;&nbsp; esi, ss:[esp+<span style="color: #008000;">48h</span>+<span style="color: #008000;">hInstance</span>]</strong>。有同学发问了：&#8220;你怎么知道复制的数据在堆栈呢？&#8221;能提出这个说明这位同学是认真思考了，我来回答一下：凡是看到中括号第一个是ESP或EBP，那么选择子就是SS，别忘了ESP可是叫做堆栈指针寄存器，那可不是盖的！再来看下地址为00401036处的汇编代码：<strong><span style="color: #003366;">call ds</span></strong>:<span style="color: #d02ecd;"><strong>LoadIconA</strong></span>。这句是呼叫函数LoadIconA载入图标，函数一般存放在代码段，但是这个函数存放的地址却是数据段，因为Intel规定的代码段默认的选择子是cs，所以此处必须指明为ds，CPU才知道此处以ds作为选择子。其它的情况如果是字符串指令，则是ES，否则都用DS。</p>
<p>呵呵，我认为还算通俗易懂啊。今天先到这里。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/08/159/" target="_blank">http://www.figoyao.com/blog/2009/12/08/159/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104697.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:34 <a href="http://www.cppblog.com/figoyao/articles/104697.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A2_3篇</title><link>http://www.cppblog.com/figoyao/articles/104696.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:33:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104696.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104696.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104696.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104696.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104696.html</trackback:ping><description><![CDATA[作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a>
<p>本节主要讲解汇编中的内存管理。</p>
<p>CPU对内存的管理的最小单元是字节（8个bit），为了标识不同单元，就给每个单元一个编号，这个编号就是我们下面说的物理地址：地址是一个无符
号的二进制整数，但为了书写方便一般写成十六进制形式，如0&#215;410234等。下面首先讲解32位CPU的内存管理模式：实模式和保护模式。</p>
<p>一、实模式<br>
物理地址=段地址&#215;16+偏移量<br>
段地址存储在<strong>段寄存器</strong>中，即<strong>CS</strong>（代码段寄存器）、<strong>DS</strong>（数据段寄存器）、<strong>ES</strong>（附加段寄存器）、<strong>SS</strong>（堆栈段寄存器）、<strong>FS</strong>（附加段寄存器）、<strong>GS</strong>（附加段寄存器），其中FS和GS是80386及以后型号的CPU增加的寄存器。在实际编程中，遵循的原则如下表所示：</p>
<table bgcolor="#ffffff" border="1" bordercolor="#000000">
    <tbody>
        <tr>
            <td><strong>指令操作</strong></td>
            <td><strong>缺省的段寄存器</strong></td>
            <td><strong>可选的段寄存器</strong></td>
            <td><strong>偏移量</strong></td>
        </tr>
        <tr>
            <td>取指令</td>
            <td>CS</td>
            <td>&nbsp;</td>
            <td>IP</td>
        </tr>
        <tr>
            <td>堆栈操作</td>
            <td>SS</td>
            <td>&nbsp;</td>
            <td>SP</td>
        </tr>
        <tr>
            <td>取操作数</td>
            <td>DS</td>
            <td>CS、ES、SS</td>
            <td>有效地址</td>
        </tr>
        <tr>
            <td>串操作</td>
            <td>DS/ES</td>
            <td>&nbsp;</td>
            <td>SI/DI</td>
        </tr>
        <tr>
            <td>BP指针寄存器</td>
            <td>SS</td>
            <td>CS、DS、ES</td>
            <td>有效地址</td>
        </tr>
    </tbody>
</table>
<p>简单解释一下上表，比如取操作数，缺省用DS作为段寄存器，偏移量为有效地址，<strong>DS:[100H]</strong>，方括号中的是有效地址，冒号前的DS作为段基地址，假设此时DS的值为0&#215;23E6H，那么内存单元的物理地址为：0&#215;23E6H&#215;16+100H=0&#215;23F60H。所谓缺省的段寄存器，是说如果地址表达式为[<strong>100H</strong>]，就认为DS是段基地址。为了便于理解，你可以这么去想：你要去宿舍楼找小明，首先需要知道楼层（段基地址），到楼层后再通过房间号（偏移地址），这样就找到小明了。<br>
内存最小单元式字节，但是我们经常接触的是字（2个字节）或双字（4个字节）。前面讲过，内存最小单元的编号就是地址，那么寻址字或双字的时候以哪个最小单元的地址为准呢？先来看个示意图：<br>
<a  href="http://www.figoyao.com/blog/2009/12/07/147/null"><img  src="http://farm3.static.flickr.com/2617/4165719637_33e6edddf5_o.jpg" title="addrbyte" alt="" height="263" width="330"></a><br>
地址为23451H的字节的数值为：12H；<br>
地址为23451H的字的数值为：3412H；<br>
地址为23451H的双字的数值为：78563412H。<br>
Intel的CPU规定：高(低)地址存储单元存储高(低)字节。所以地址为23451H的字的数值的低字节为低地址23451H处的12H，高字节为23452H处的34H。</p>
<p>二、保护模式<br>
此时的地址计算与实模式完全不同，段寄存器存储的不再是段基地址。对于32位CPU来讲，可以使用32根地址线访问内存，排列组合一下可以算出总共可以访
问2^32Byte，即4GB。顾名思义，保护模式涉及到地址空间优先级等安全属性的描述，段寄存器就用来保存这些安全描述信息，但由于信息太多，需要
64位长的数据才可存储完整，这个存储安全信息的64位长的数据有个专门的称谓：段描述符（Segment
Descriptor）。16位的段寄存器是不够用的，为了解决这个问题。80X86CPU引入了两个新的寄存器：全局描述符表寄存器<strong>GDTR</strong>（48位）和局部描述符表寄存器<strong>LDTR</strong>（16位）。原理就是充分利用内存空间，实现机制如下：<br>
<a  href="http://farm3.static.flickr.com/2768/4168308535_79ecce6d8a_o.jpg"><img  src="http://farm3.static.flickr.com/2768/4168308535_79ecce6d8a_o.jpg" class="alignnone" title="GDTR" alt="" height="695" width="851"></a><br>
在操作系统启动后，GDTR指向一块内存区域，该区域的起始地址为GDTR的16到47位指示的地址，长度为GDTR的0到15位指示的长度。这块内存被称作<strong>全局描述符表（GDT）</strong>，
因为它存储了操作系统使用的代码段、数据段和堆栈段的全部信息；同时还存储了用户建立的执行任务的信息（局部描述符表LDT索引），该信息记录了各个任务
内部代码段、数据段等的描述表的起始地址，可以理解成各个任务描述表的起始地址都存在这里，通过它可以定位所有任务的内存相关信息。<br>
在保护模式下，地址格式为XXXX:YYYYYYYY，XXXX表示段选择器，为DS、CS、FS等段寄存器；YYYYYYYY为偏移地址。我们要做的是通过XXXX确定描述符，然后找到基地址，加上偏移地址，进而得到有效的线性地址，此时才能定位内存单元。步骤如下：<br>
首先检查XXXX的第2位是否为0：为0表示描述符在GDT中，其位置由XXXX的高13位确定；不为0表示描述符在LDT中，要找LDT首先需要找到它
的基址，而基址存储在GDT中，其位置由LDTR的高13位确定，得到LDT基址后，我们进一步通过XXXX的高13位在LDT中确定目标内存单元的基
址，然后结合偏移地址就得到了线性地址。</p>
<p>今天就讲到这里，下节将开始寻址方式的讲解。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/07/147/" target="_blank">http://www.figoyao.com/blog/2009/12/07/147/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104696.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:33 <a href="http://www.cppblog.com/figoyao/articles/104696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A2_2篇</title><link>http://www.cppblog.com/figoyao/articles/104695.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:32:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104695.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104695.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104695.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104695.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104695.html</trackback:ping><description><![CDATA[<p>作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a></p>
<p>讲了这么多天理论知识有的同学可能有些迷茫和厌倦了，你看，教室后门那个穿夹克的同学都睡着了。所以今天我们来小小的演习一下，囿于目前大家的知识储备，下面的练习只能归为局部演习，等你们羽翼丰满的时候我会领着大家实战。千万记住：欲速则不达。</p>
<p>首先我们需要自己编一个小游戏：玩家和怪物打斗，通过文字输出战斗情况。代码如下：</p>
<div class="wp-caption alignnone" style="width: 674px;"><a  href="http://www.figoyao.com/blog/2009/12/06/135/null"><img  src="http://farm3.static.flickr.com/2693/4162765690_fe723c609b_o.jpg" title="SimpleGame" alt="SimpleGame" height="762" width="664"></a>
<p class="wp-caption-text">SimpleGame</p>
</div>
<p>执行界面如下，怪物和玩家的血量依次递减：<br>
<a  href="http://www.figoyao.com/blog/2009/12/06/135/null"><img  src="http://farm3.static.flickr.com/2594/4162009261_a511b356d6_o.jpg" class="alignnone" title="exegame" alt="" height="303" width="188"></a><br>
包括以后真正的实战，我们要非常明确自己的目标：这里的目标是把玩家血量改为递增，即玩家被怪物攻击一次血量增加一个伤害值大小的数值。在<a  href="http://www.figoyao.com/blog/2009/12/05/124/" target="_blank">上节教程</a>，我们讲过与CPU交互的数据主要存储在<strong>内存</strong>中，那我们要做的就是找到内存中存储玩家血量数据的地址，因为CPU是通过<strong>地址总线</strong>来定位数据，这也就是我们第一步要做的事情：找地址，工具使用大家耳熟能详的<strong><a  href="http://www.cheatengine.org/" target="_blank">CheatEngine</a></strong>。步骤如下：<br>
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" height="363" width="420">
<embed lk_media="yes" lk_mediaid="lk_juiceapp_mediaPopup_1262503883945" type="application/x-shockwave-flash" src="http://www.tudou.com/v/2vPUYWVwp5k" wmode="opaque" allowscriptaccess="always" allowfullscreen="true" height="363" width="420"></object><br>
视频中的相关代码和程序打包下载：<a  href="http://figoyao.com/blog/file/CheatGame.rar" target="_blank">点击下载</a>。<br>
视频的<strong>清晰版</strong>下载：<a  href="http://down.qiannao.com/space/file/figoyao/share/lesson-002d01.avi/.page" target="_blank">点击下载</a>。</p>
<p>下面讲解一下外挂程序的细节：<br>
<a  href="http://www.figoyao.com/blog/2009/12/06/135/null"><img  src="http://farm3.static.flickr.com/2582/4162195159_ed9a407ac3_o.jpg" class="alignnone" title="AimBot" alt="" height="651" width="768"></a><br>
需要讲解的函数有2个：<strong>OpenProcess</strong>和<strong>WriteProcessMemory</strong>。<br>
1、OpenProcess(<em>dwDesiredAccess,<em>bInheritHandle,<em>dwProcessId</em></em></em>)<br>
第一个参数：对被打开进程的访问权，设置为PROCESS_ALL_ACCESS，即所有访问权；<br>
第二个参数：打开进程创建的子进程是否可以继承该访问权限，设置为NULL；<br>
第三个参数：要打开的进程的ID值，即我们在任务管理器里看到的PID（看不到的同学，通过<strong>查看</strong>-&gt;<strong>选择列</strong>-&gt;勾选<strong>PID</strong>）。<br>
此函数执行成功的话我们就得到了目标进程的句柄，你可以暂时把句柄理解系统为进程指定的身份证号。<br>
2、WriteProcessMemory(<em>hProcess,<em>lpBaseAddress,<em>lpBuffer,<em>nSize,<em>lpNumberOfBytesWritten</em></em></em></em></em>)<br>
第一个参数：要写入内存的目标进程句柄，已经通过上面函数得到了；<br>
第二个参数：要写入内存的地址指针，就是我们通过OllyDbg得到的那个地址；<br>
第三个参数：要写入的数据，即我们修改<strong>sub</strong>指令为<strong>add</strong>指令；<br>
第四个参数：要写入数据的大小；<br>
第五个参数：可选参数，与本处无关，设置为NULL。</p>
<p>本节我们给出了一个完整的Demo演示，实战中不会这么顺利很简单。希望这篇教程能够提起大家的兴趣，以迎接真正的挑战：<span style="color: #ff0000;"><strong>当你掌握了足够技术后，如果说还有什么能够阻挡你，只有你的想象力！</strong></span></p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/06/135/" target="_blank">http://www.figoyao.com/blog/2009/12/06/135/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104695.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:32 <a href="http://www.cppblog.com/figoyao/articles/104695.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A2_1篇</title><link>http://www.cppblog.com/figoyao/articles/104694.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:31:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104694.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104694.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104694.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104694.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104694.html</trackback:ping><description><![CDATA[<p>作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a></p>
<p>本篇起我们开始讲解汇编语言，最终目标是能读懂OllyDbg或IDA等反汇编工具得到的汇编代码，并可进行基本的高级语言嵌入汇编程序设计。我假设<a  href="http://www.figoyao.com/blog/2009/11/28/34/" target="_blank">A1系列文章</a>你已经读过，并掌握基本的高级语言程序设计方法。</p>
<p>对任何事物都要从ta产生的来龙去脉去研究，这样才能获得全面深刻的理解。话说上世纪40年代产生了第一代计算机，由于是基于二进制数制逻辑，人们可以和计算机交流的语言限于<a  href="http://zh.wikipedia.org/zh-cn/%E6%9C%BA%E5%99%A8%E8%AF%AD%E8%A8%80" target="_blank">机器语言</a>，你完全可以把它理解为某种外星语言：机器语言完全由0和1组成，当然，这属于人家计算机内部交流语言。我们都知道<a  href="http://zh.wikipedia.org/zh-tw/%E5%8D%A0%E5%A3%AB%E9%82%A6" target="_blank">詹姆士.邦德</a>代号007，知道周星星代号<a  href="http://zh.wikipedia.org/zh-cn/%E5%94%90%E4%BC%AF%E8%99%8E%E9%BB%9E%E7%A7%8B%E9%A6%99" target="_blank">9527</a>，
知道圣诞节1225，情人节214&#8230;说这么多，其实是为了告诉大家：每个人的记忆力都很好的，相信我，汇编里面要你记住的常用代号不会比节日多：）。最
初，为了要计算机按照人们意图行事，不得不通过机器语言与之交流，这就使得当时的程序员和远古时期的巫师一样稀少和神秘，因为机器语言容易出错，比如，你
找出下面两个数字的不同：<br>
1000110100011101001100011100011和1000110100011101001101011100011。<br>
这还属于最简单的，如果是十几张纸都是0和1，让你找错，恐怕效率和正确率都不会太高。当人们意识到这个问题时，开始构造一种机制来简化编程，这样就有了汇编语言，它的思想就是互相替换：在人编写程序时候，用邦德<strong>替换</strong>007，周星星<strong>替换</strong>9527，&#8230;；在计算机执行时候，用007<strong>替换</strong>邦德，9527<strong>替换</strong>周星星，&#8230;。虽然这里说的是替换，但实际属于<a  href="http://zh.wikipedia.org/zh-cn/%E7%BC%96%E8%AF%91" target="_blank">编译原理</a>的东西，操作起来比较复杂，此处就不深入了。</p>
<p>永远记住，汇编语言是处理器相关的，此处主要以<a  href="http://www.intel.com/technology/product/index.htm" target="_blank">X86系列</a>处理器为原型讲解，<a  href="http://www.amd.com/" target="_blank">AMD公司</a>的CPU一般都是兼容IA-32架构的，所以满足X86规则的汇编程序在AMD兼容芯片一样可以运行。</p>
<p>我们知道计算机几个主要配件：CPU、内存和硬盘等，而把这些配件整合到一起的就是主板，上面有各种形式的导线。下面是一张逻辑图：<br>
<a  href="http://www.figoyao.com/blog/2009/12/05/124/null"><img  src="http://farm3.static.flickr.com/2753/4160289334_2606383040_o.jpg" class="alignnone" title="CPUArchitect" alt="" height="247" width="566"></a><br>
上图中的<strong>I/O设备</strong>是
指输入（Input）输出（Output）设备，如鼠标、键盘和摄像头等；I/O接口指的是USB、COM等接口；存储器主要指内存。从上图我们看到由
CPU引出三种总线：控制、地址和数据总线，这是CPU坐阵指挥的途径，也就是说所有CPU指令最终都要表现在总线的操作上，而汇编语言本质上就是学会通
过CPU操作总线的方法。那么，好奇的你就没有什么想问的吗？记住，有时候，好奇是比知识更重要的想象力！虽然好奇<a  href="http://en.wikipedia.org/wiki/Curiosity_killed_the_cat" target="_blank">害死加菲猫</a>。那么，CPU里面是怎么个组成呢？在我们学校有这么一个传说：<a  href="http://baike.baidu.com/view/993031.htm" target="_blank">胡伟武</a>同学本科毕业设计就是用单片机搭出一个类8086芯片系统，这从一个侧面表达出X86的复杂。幸运的是，大家暂时不必了解太多；不幸的是，如果你打算像我的那个去<a  href="http://www.360.cn/" target="_blank">360</a>的师兄一样<strong>坚持走底层技术路线</strong>的话，你还是有必要读读Intel指令手册的。不过，我们暂时只需做个&#8220;幸运儿&#8221;：）。</p>
<p>当我们要求计算机对两个数执行求和运算时，CPU处理的流程是怎样的呢？假设要对a与b求和，a、b均已经存在于内存了。结合上面架构图来看：CPU通过<strong>控制总线</strong>发出读数据的指令，通过<strong>地址总线</strong>指明要读数据在内存中的地址，通过<strong>数据总线</strong>把数据传给CPU，CPU把数据存储在自己的<strong>寄存器</strong>中，然后通过<strong>算术逻辑部件</strong>（ALU）完成运算。这里多了两个名词：寄存器和算术逻辑部件，我将逐一讲解。</p>
<p>任何事物不能凭空存在，包括数据，CPU要交互的数据大部分放在内存和硬盘：硬盘向内存传输数据的速率远低于内存向CPU传输数据的速率；内存向
CPU传输数据的速率远低于CPU的处理速率，现在的CPU为了缓解这个矛盾，一般都使用高速缓存机制，因为高速缓存向CPU传输数据的速率更快。那么，
问题来了：CPU接收数据后把数据存放在哪里呢？答案是寄存器，寄存器的存取速率比内存快很多，主要用来存放运算过程中的数据地址、数据及中间结果等。本
篇教程是以32位处理器为原型讲解，首先要讲的是最常用的<strong>通用寄存器</strong>：<span style="color: #ff0000;">EAX</span>、<span style="color: #ff0000;">EBX</span>、<span style="color: #ff0000;">ECX</span>和<span style="color: #ff0000;">EDX</span>。这就是寄存器代号，类似9527代表周星星：<br>
<a  href="http://www.figoyao.com/blog/2009/12/05/124/null"><img  src="http://farm3.static.flickr.com/2635/4160382064_d98c938b92_o.gif" class="alignnone" title="EAX" alt="" height="117" width="367"></a><br>
有的同学看到上面的图可能像魔兽争霸一样：混乱之至了，怎么又有AH、AL和AX，这是什么啊？我们来论资排辈一下，《天龙八部》里面少林<strong><span style="color: #0000ff;">觉</span>字辈</strong>高于<strong><span style="color: #0000ff;">玄</span>字辈</strong>，因为他们老师的辈分不同所导致；那么把从AL到EAX按照<strong>位数</strong>排
下辈：（AL、AH[8位]）&lt;AX[16位]&lt;EAX[32位]。其实它们指的是同一个东西的不同部分，好比一个手由5个指头组成，一个人
有2个手：但自始自终都是指的一个人，只是范围不同而已。同理EBX、ECX和EDX与EAX结构和命名类似，比如EBX也有BX、BH和BL。这样做的
目的是提供最大的灵活性，比如有时你只需要存一个8位的值，那么就没必要占用全部寄存器，只需要用一部分即可：这与宿舍类似，一个宿舍假设可以容纳4个
人，那么只有一个学生的时候占一张床即可，不必全部占满。<br>
<a  href="http://www.figoyao.com/blog/2009/12/05/124/null"><img  src="http://farm3.static.flickr.com/2794/4168308533_ba350da612_o.jpg" class="alignnone" title="EXX" alt="" height="326" width="564"></a></p>
<p>除了通用寄存器，还有<strong>变址和指针寄存器(EDI/ESI/ESP/EBP)</strong>、<strong>指令指针寄存器(EIP)</strong>、<strong>标志寄存器(EFlags)</strong>：这些都是32位的寄存器。CPU中16位的寄存器是<strong>段寄存器</strong>，也就是说段寄存器这个房子的平米数比前面的寄存器要少，最大可以存16bit。<br>
<a  href="http://www.figoyao.com/blog/2009/12/05/124/null"><img  src="http://farm3.static.flickr.com/2567/4168308537_f948d1984f_o.jpg" class="alignnone" title="EIP" alt="" height="715" width="465"></a><br>
各种寄存器的主要用途如下表：</p>
<table bgcolor="#ffffff" border="1" bordercolor="#000000">
    <tbody>
        <tr>
            <td><strong>寄存器</strong></td>
            <td><strong>代号</strong></td>
            <td><strong>主要用途</strong></td>
        </tr>
        <tr>
            <td>累加器</td>
            <td>EAX</td>
            <td>算术运算、存储中间结果、函数返回值</td>
        </tr>
        <tr>
            <td>基地址寄存器</td>
            <td>EBX</td>
            <td>基地址指针</td>
        </tr>
        <tr>
            <td>计数器</td>
            <td>ECX</td>
            <td>循环计数、移位操作计数、重复操作计数</td>
        </tr>
        <tr>
            <td>数据寄存器</td>
            <td>EDX</td>
            <td>乘除运算、存储中间结果</td>
        </tr>
        <tr>
            <td>源变址寄存器</td>
            <td>ESI</td>
            <td>存储指针、串指令的源操作数指针</td>
        </tr>
        <tr>
            <td>源目标变址寄存器</td>
            <td>EDI</td>
            <td>存储指针、串指令的目的操作数指针</td>
        </tr>
        <tr>
            <td>基地址指针</td>
            <td>EBP</td>
            <td>存储指针、存取堆栈指针</td>
        </tr>
        <tr>
            <td>栈顶指针</td>
            <td>ESP</td>
            <td>堆栈的栈顶指针</td>
        </tr>
    </tbody>
</table>
<p>这节暂时讲到这里。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/05/124/" target="_blank">http://www.figoyao.com/blog/2009/12/05/124/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104694.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:31 <a href="http://www.cppblog.com/figoyao/articles/104694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A1_7篇</title><link>http://www.cppblog.com/figoyao/articles/104693.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:30:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104693.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104693.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104693.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104693.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104693.html</trackback:ping><description><![CDATA[<p>作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a></p>
<p>本篇讲解一些杂项：预处理命令、typedef定义新类型以及推荐书目。</p>
<p>1、预处理命令<br>
该类命令一般以<strong>#</strong>（井字符）开头：#include；#define、#undef；#if、#ifdef、#ifndef、#else、#elif；#pragma。<br>
1）、#include 记号序列<br>
记号序列必须被解释为&lt;&#8230;&gt;或&#8221;&#8230;&#8221;之一，如：<br>
<span style="color: #0000ff;">#include</span> &lt;stdio.h&gt; <span style="color: #008000;">//包含标准输入输出头文件</span><br>
<span style="color: #0000ff;">#include</span> &#8220;userdefine.h&#8221; <span style="color: #008000;">//包含用户自定义头文件</span><br>
这两者的区别在于，&lt;&#8230;&gt;指示编译器去系统目录或环境变量寻找头文件；而&#8221;&#8230;&#8221;指示首先去当前目录寻找头文件，如果找不到再按照前者规则寻找。<br>
2）、#define 标示符 记号序列 或 #define 标示符<br>
#define的第一种用法主要用在定义宏，如：<br>
#define PI 3.1415926<br>
上面就定义PI为3.1415926，但实际上我们推荐使用const方式来定义。<br>
#define的第二种用法主要用在编译不同版本及指示标志，如：<br>
#define _UNICODE<br>
这样定义的话当我们编写windows应用程序时候，里面函数版本会被替换为UNICODE版本。而#undef的作用在于抵消#define定义的指示标志：<br>
#undef _UNICODE<br>
这会导致上面的#define语句失效。<br>
3）、#if 系列主要用在debug和防止头文件重复包含方面：<br>
4）、#pragma<br>
该预处理指令是比较复杂的一个，你只需暂时记住有即可，当你遇到也不会生疏。如需详细用法可查阅<a  href="http://www.china-pub.com/39842" target="_blank">手册</a>。</p>
<p>2、typedef<br>
主要用来定义新类型别名，其用法如下：<br>
<span style="color: #0000ff;">typedef</span> 原数据类型名 新数据类型名<br>
比如wchar_t的定义为：<strong>typedef</strong> <span style="color: #0000ff;">unsigned short</span> wchar_t。</p>
<p>3、推荐书目<br>
《<a  href="http://www.china-pub.com/14975" target="_blank">C程序设计语言</a>》<br>
《<a  href="http://www.china-pub.com/38125" target="_blank">C缺陷与陷阱</a>》<br>
《<a  href="http://www.china-pub.com/38679" target="_blank">C和指针</a>》<br>
《<a  href="http://www.china-pub.com/5926" target="_blank">C++ Primer</a>》<br>
《<a  href="http://www.china-pub.com/7645" target="_blank">C++标准程序库</a>》</p>
<p>至此C++基础就讲完了，下面开始的章节将讲解汇编语言程序设计。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/04/116/" target="_blank">http://www.figoyao.com/blog/2009/12/04/116/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104693.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:30 <a href="http://www.cppblog.com/figoyao/articles/104693.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A1_5篇</title><link>http://www.cppblog.com/figoyao/articles/104691.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:29:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104691.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104691.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104691.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104691.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104691.html</trackback:ping><description><![CDATA[<p>作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a></p>
<p>本篇讲解类的使用。</p>
<p>当谈到类的时候，我们经常听到的是面向对象编程（oop），其实呢，面向对象是一种编程思想，只不过类机制较好的支持这种想法，但是并不代表要编写面向对象的程序一定要用C++或类似语言（如Java等），即使用传统的C，依然可以写出面向对象的程序。</p>
<p>class的成员除了可以是数据外，最大的变化是，函数也可以作为其成员，对于其成员按照访问属性的不同有：private、public和
protected三种。按照来源不同，其成员可分为：用户自定义、语言默认和强制系统定义。我们可以把一个类理解为一个功能完整的小麻雀：除了具有数据
成员外，还有具有类提供给用户的功能函数。下面设计一个动物类：<br>
<span style="color: #0000ff;">class animal<br>
{<br>
&nbsp;&nbsp;&nbsp; private：<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp; eat();<span style="color: #008000;">//吃饭</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp; sleep();<span style="color: #008000;">//睡觉</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp; run();<span style="color: #008000;">//跑</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp; age;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool&nbsp; alive;<br>
&nbsp;&nbsp;&nbsp; public:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool&nbsp; feed();<span style="color: #008000;">//喂食</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool&nbsp; blood();<span style="color: #008000;">//血型</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp; state();<span style="color: #008000;">//状态信息</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp; foodlimit;<span style="color: #008000;">//饮食控制</span><br>
};<br>
</span>animal类呢其实是定义了一个模板，因为大部分陆地动物都具有上面的属性，类的成员函数<strong>通常</strong>在类外
完成具体实现，实际编程时，我们一般都把类声明放在头文件中，而把类实现放在包含头文件的同名cpp源文件中，如，我们在define.h中定义了要实现
的类和数据结构以及系统头文件预处理，那么我们需要新建一个名为define.cpp的源文件，该源文件要在文件开始包含define.h文件，这样我们
在其他文件中如果要使用这个类，只要包含define.h即可，建议大家有意识的建立自己的个人类库，随着时间的推移，你会发现你的开发效率会大大提高。</p>
<p>下面我们实际开始动手，本教程使用的工具是Visual C++6.0：<br>
<strong>第一步</strong>：新建文件<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/68/null"><img  src="http://farm3.static.flickr.com/2750/4154265191_19c276ff0f_o.jpg" class="alignnone" title="ctrl+n" alt="" height="359" width="160"></a><br>
<strong>第二步</strong>：工程类型<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/68/null"><img  src="http://farm3.static.flickr.com/2577/4154271687_e8be19e572_o.jpg" class="alignnone" title="project" alt="" height="479" width="739"></a><br>
<strong>第三步</strong>：建立空工程【我给工程起名字是ClassDefine】<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/68/null"><img  src="http://farm3.static.flickr.com/2640/4154276973_45d5f44639_o.jpg" class="alignnone" title="finish" alt="" height="464" width="611"></a><br>
<strong>第四步</strong>：添加头文件和源文件<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/68/null"><img  src="http://farm3.static.flickr.com/2795/4155046880_e5af436951_o.jpg" class="alignnone" title="define.h" alt="" height="477" width="741"></a></p>
<p><a  href="http://www.figoyao.com/blog/2009/12/03/68/null"><img  src="http://farm3.static.flickr.com/2667/4155046882_dc9c058731_o.jpg" class="alignnone" title="define.cpp" alt="" height="478" width="740"></a><br>
上面两项建立好后左侧目录如下：<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/68/null"><img  src="http://farm3.static.flickr.com/2559/4155046876_721b1eb797_o.jpg" class="alignnone" title="gamebegin" alt="" height="136" width="209"></a><br>
<strong>第五步</strong>：添加类定义和实现<br>
<em><strong>类的定义</strong></em><br>
<a  href="http://www.figoyao.com/blog/2009/12/03/68/null"><img  src="http://farm3.static.flickr.com/2700/4155106190_f59dea32f5_o.jpg" class="alignnone" title="definehdetail" alt="" height="473" width="572"></a><br>
<em><strong>类的实现：</strong></em><br>
<a  href="http://www.figoyao.com/blog/2009/12/03/68/null"><img  src="http://farm3.static.flickr.com/2729/4155106196_9be479815f_o.jpg" class="alignnone" title="definecppdetail" alt="" height="598" width="719"></a><br>
<strong><em>建立main函数文件</em></strong><br>
<a  href="http://www.figoyao.com/blog/2009/12/03/68/null"><img  src="http://farm3.static.flickr.com/2685/4155106198_85ed38d9bc_o.jpg" class="alignnone" title="maincppdetail" alt="" height="509" width="677"></a><br>
完整源文件<a  href="http://figoyao.com/blog/file/ClassDefine.rar" target="_blank">下载</a>。<br>
类成员的三种不同属性主要用来限制成员的访问方式，读者可以看到上面当定义一个类对象smFish后，我们使用.(点)运算符来访问成员，能够使用此种方
式被访问的只有被指明是public的成员，凡是private属性的成员是不能这样被访问的，此时只能在成员内部使用。关于friend（友元）属性本
教程不涉及，读者可以参考<a  href="http://www.china-pub.com/5926" target="_blank">C++ primer</a>或其他书籍进一步研究。</p>
<p>下次我们将讲解类的继承派生和虚函数。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/03/68/" target="_blank">http://www.figoyao.com/blog/2009/12/03/68/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104691.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:29 <a href="http://www.cppblog.com/figoyao/articles/104691.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A1_6篇</title><link>http://www.cppblog.com/figoyao/articles/104692.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:29:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104692.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104692.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104692.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104692.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104692.html</trackback:ping><description><![CDATA[<p>作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a></p>
<p>本篇讲解类的继承派生和虚函数。</p>
<p>一、继承派生机制<br>
在古装片里我们经常看到某某太子继承王位，太子继承王位的结果就是他首先拥有了皇帝的权利并要原则上承担义务；又或某张三继承富翁老爹的财产，那么这个某张三就拥有了富翁对于财产的支配权等等。在类里面的继承和这些很类似，比如我们<a  href="http://www.figoyao.com/blog/2009/12/03/68/" target="_blank">上节</a>定义了一个叫做Fish的类，鱼分很多种，有金鱼、草鱼、武昌鱼（╮(╯_╰)╭）等等，当我们需要实现一个<a  href="http://zh.wikipedia.org/zh-cn/%E9%9B%BB%E9%B0%BB" target="_blank">电鳗</a>类的定义时，我们可以从已经定义好的Fish类派生一个电鳗类，派生的子类就继承了Fish所以的特征；同时，因为电鳗有自己的特点，比如放电，因此我们还要定义电鳗自身的特征函数和特征数据：<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/74/null"><img  src="http://farm3.static.flickr.com/2790/4155187592_4d9ba0c0e0_o.jpg" class="alignnone" title="public" alt="" height="132" width="264"></a><br>
此时电鳗类就简单定义完成了，继承时候需要制定继承参数类型：public、private和protected。继承类型的不同会影响成员的属性：</p>
<table bgcolor="#ffffff" border="1">
    <tbody>
        <tr>
            <td><span style="font-size: x-small;">继承方式</span>[<span style="font-size: medium; color: #ff0000;"><strong>&#8595;</strong></span>]<span style="font-size: x-small;">访问属性</span>[<strong><span style="font-size: medium; color: #ff0000;">&#8594;</span></strong>]</td>
            <td><strong>public</strong></td>
            <td><strong>protected</strong></td>
            <td><strong>private</strong></td>
        </tr>
        <tr>
            <td><strong>public</strong></td>
            <td>public</td>
            <td>protected</td>
            <td>不可访问</td>
        </tr>
        <tr>
            <td><strong>protected</strong></td>
            <td>protected</td>
            <td>protected</td>
            <td>不可访问</td>
        </tr>
        <tr>
            <td><strong>private</strong></td>
            <td>private</td>
            <td>private</td>
            <td>不可访问</td>
        </tr>
    </tbody>
</table>
<p>具体到电鳗类，我们看下Fish类的定义：<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/74/null"><img  src="http://farm3.static.flickr.com/2700/4155106190_f59dea32f5_o.jpg" class="alignnone" title="FishClass" alt="" height="473" width="572"></a></p>
<p>因为电鳗的继承方式是public，对照上面表格，可知电鳗中的Eat()等函数依旧是public属性。下面给出代码，大家可以看下用法：<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/74/null"><img  src="http://farm3.static.flickr.com/2528/4154539355_74ac267262_o.jpg" class="alignnone" title="efish" alt="" height="393" width="478"></a></p>
<p>二、虚函数<br>
在继承的机制中存在这样的问题，子类成员函数如果有何父类同名的话应该如何处理呢？C++中引入了虚函数机制，多态性就是通过虚函数来体现的。<br>
我们先来看下不用虚函数机制，直接在子类中定义同名函数：<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/74/null"><img  src="http://farm3.static.flickr.com/2799/4155579482_e488e7cf41_o.jpg" class="alignnone" title="eat" alt="" height="73" width="304"></a><br>
父类Fish类中Eat的定义如下：<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/74/null"><img  src="http://farm3.static.flickr.com/2798/4154822725_d63872580d_o.jpg" class="alignnone" title="fisheat" alt="" height="89" width="305"></a><br>
执行结果如下：<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/74/null"><img  src="http://farm3.static.flickr.com/2748/4154870833_57bb84f22f_o.jpg" class="alignnone" title="virtual" alt="" height="607" width="522"></a><br>
注意上图红色方框处的指示。我们本来的想法是当指针pFish指向不同的类时执行不同的成员函数，但实际是，未强制类型转换前执行的依旧是父类Eat函数，为了避免类型转换的麻烦，引进的虚函数：<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/74/null"><img  src="http://farm3.static.flickr.com/2753/4155641622_d596191832_o.jpg" class="alignnone" title="parents" alt="" height="467" width="374"></a><br>
此时执行的结果如下：<br>
<a  href="http://www.figoyao.com/blog/2009/12/03/74/null"><img  src="http://farm3.static.flickr.com/2668/4154870835_dd81b85691_o.jpg" class="alignnone" title="parents" alt="" height="595" width="506"></a></p>
<p>
下一节将把一些杂项讲解一下，然后C++精简教程就完结了。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://http//www.figoyao.com/blog/2009/12/03/74/">http://www.figoyao.com/blog/2009/12/03/74/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104692.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:29 <a href="http://www.cppblog.com/figoyao/articles/104692.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A1_3篇</title><link>http://www.cppblog.com/figoyao/articles/104689.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:27:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104689.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104689.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104689.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104689.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104689.html</trackback:ping><description><![CDATA[<p>作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a></p>
<p>本篇讲解指针和函数。</p>
<p>一个运行的程序，其指令和数据主要存储位置是内存。当我们定义好数据后，如何取用该数据呢。比如：<br>
int&nbsp; iTest = 0;<br>
上面我们定义了iTest，任何事物不能凭空存在，包括数据，iTest的存储位置就是内存中一个4字节的单元，那么当我们要使用iTest的时候计算机
如何知道去哪里找它呢，实际上是使用了指针机制。指针本质上是索引，可以理解为学号，在一个学校里面，所有人的学号都是不同的，有些人可能生日啊、名字的
相同，但学号是不会相同的；在内存中，有些数据的值可能一样，但是指示这些数据存储位置的指针却不可能相同（我们在此暂不考虑Window系统中私有内存
机制）。在家乐福等大型超市里面我们要自助存包的时候，每个储物箱对应着唯一编号（即指针），当我们存包后（即定义变量），储物箱中有了内容物（即数
据），购物完毕，我们可以依据储物箱编号准确找到自己的物品，指针的机制就是如此。</p>
<p>由上段我们看到指针类型可以多种多样：在C++中，当要指示不同数据类型时候指针类型也是不同的。其定义方法如下：<br>
1、定义一个指向int类型的指针<br>
<span style="color: #0000ff;">int<span style="color: #ff0000;">*</span> piNum;</span><br>
2、定义一个指向char型的指针<br>
<span style="color: #0000ff;">char <span style="color: #ff0000;">*</span>pcCh;</span><br>
通用定义格式如下，其中<span style="color: #ff0000;">*</span>指的是星号：<br>
[数据类型]* 变量名;<br>
定义指针完毕我们可以给指针赋值：<br>
<span style="color: #0000ff;">int</span> iNum = 3;<br>
piNum =<span style="color: #ff0000;"> &amp;</span>iNum;<br>
上面定义中，<span style="color: #ff0000;">&amp;</span>为取地址符，求出iNum的存储地址后，把地址的值赋给piNum，此时piNum指向就是存储单元中的内容物就是3。</p>
<p><strong>指针的运算</strong><br>
我们假设p和q均为指向char类型数据的指针<br>
1、加法<br>
q = p+1：q指向p为起点向后数1个存储位置的数据单元，即紧邻p位置的但地址大于p数据单元。<br>
q = p+n：q指向p为起点向后数n个存储位置的数据单元。<br>
2、减法<br>
q = p-1：q指向p为起点向前数1个存储位置的数据单元，即紧邻p位置的但地址小于p数据单元。<br>
q = p-n：q指向p为起点向前数n个存储位置的数据单元。<br>
3、指针相减<br>
<span style="color: #0000ff;"><strong>q</strong></span>-&gt;|&#8217;A'|&nbsp;[<span style="color: #008000;">0x0410000h</span>]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&#8217;B'| [<span style="color: #008000;">0x0410002h</span>]<br>
<strong><span style="color: #0000ff;">p</span></strong>-&gt;|&#8217;C'| [<span style="color: #008000;">0x0410004h</span>]<br>
上面中括号中数值表示指针p和q的实际取值，C++中规定两个指针相减并不是在用地址作减法，而是两个指针所代表的地址位之间的数据个数的减法。以上面示意图为例，p-q的数值并不是0&#215;4h，而是0&#215;2h，因为q指的是第1个数据，p指的是第3个数据，3-1=2。</p>
<p>指针就暂时讲到这里，下面开始讲解函数。<br>
我们可以这样理解函数，如果学校的大门属于入口函数main的话，学校的设施就是这个函数中的内容，而各个班级则可以理解为<strong>自定义函数</strong>，班级内部的实现过程只和本班级有关系。比如我要定义一个加法函数addnum( )，那么一个函数的标准格式如下：<br>
<span style="color: #0000ff;">返回类型</span> <span style="color: #ff0000;">函数名</span>(<strong>参数类型</strong> 参数1, <strong>参数类型</strong> 参数2,&#8230;)<br>
{<br>
&nbsp;&nbsp;&nbsp; <span style="color: #008000;">函数体</span>;<br>
}<br>
<span style="color: #0000ff;">int</span> <span style="color: #ff0000;">addnum</span>(<strong>int</strong> iNum1, <strong>int </strong>iNum2)<br>
{<br>
&nbsp;&nbsp;&nbsp;<span style="color: #008000;"> return iNum1+iNum2;<br>
</span>}</p>
<p>为什么要把指针和函数放在一起讲呢，因为函数的识别过程和指针有很大关联。函数名实际上就是指针变量的值：<br>
int (*paddnum)(int iNum1, int iNum2);<br>
paddnum = addnum;<br>
上面我们定义了一个指向addnum()函数的函数指针paddnum。</p>
<p>下节主要讲解构造类型数据。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/02/62/" target="_blank">http://www.figoyao.com/blog/2009/12/02/62/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104689.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:27 <a href="http://www.cppblog.com/figoyao/articles/104689.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A1_4篇</title><link>http://www.cppblog.com/figoyao/articles/104690.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:27:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104690.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104690.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104690.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104690.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104690.html</trackback:ping><description><![CDATA[<p>作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a></p>
<p>本篇讲解构造类型数据。</p>
<p>构造类型数据包括以下几种：<br>
指针类型、数组类型、结构体类型（struct）、共用体类型（union）、枚举类型（enum）、类类型（class）</p>
<p>1、指针类型<br>
<a  href="http://www.figoyao.com/blog/2009/12/02/62/" target="_blank">上节</a>已经讲解过了。</p>
<p>2、数组类型<br>
组，就是把相同的个体集合为一个整体，以便于处理。数组其实除了由各种数组成的集合，其字面意义已经延伸至任何相同类型的个体组成的集合，如，字符数组、指针数组等等。数组的定义及表示方法如下：<br>
类型 数组名[个数];<br>
一个例子：<br>
1）、<span style="color: #0000ff;">int</span>&nbsp; isNum[10];<span style="color: #008000;">//定义一个拥有10个元素的整数数组</span><br>
2）、<span style="color: #0000ff;">char</span>&nbsp; szName[] = &#8220;Figo&#8221;;<span style="color: #008000;">//定义一个内容为Figo的字符数组</span><br>
C++中注释部分需要使用<span style="color: #008000;"><strong>//</strong></span>或<span style="color: #008000;">/* */<span style="color: #000000;">。</span></span>注意到<strong>前者</strong>下标明确指出是10，但在C++中下标是从0开始表示，直至9，即isNum[10]指的是isNum[0]、isNum[1]、&#8230;isNum[8]、isNum[9]，<strong><span style="color: #ff0000;">没有isNum[10]</span></strong>！<strong>后者</strong>没有指出确切的下标，系统将按照实际长度分配下标，Figo是4个字符，所以<span style="color: #0000ff;">char</span>&nbsp; szName[] = &#8220;Figo&#8221;;等价于<span style="color: #0000ff;">char</span>&nbsp; szName[4] = &#8220;Figo&#8221;;<br>
数组初始化有2种方法：<br>
1）、<span style="color: #0000ff;">int</span> isNum[10] = {1,2,3,4,5};<br>
从isNum[0]到isNum[4]依次为1到5，而isNum[5]到isNum[9]全部为0。<br>
2）、<span style="color: #0000ff;">int</span> isNum[10];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff;">int</span> isNum[0] = 1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff;">int</span> isNum[1] = 2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&nbsp; &#8230;<br>
就是依次给个体赋值。<br>
数组维数一般常用的是一维数组、二维数组和三维数组，使用频率依次降低。<br>
二维数组就是下面有2个：<br>
类型 数组名[下标1][下标2];<br>
int&nbsp; iClass[6][4];<span style="color: #008000;">//一个学校6个年级，每年级有4个班</span></p>
<p><span style="color: #000000;">3、结构体类型<br>
其格式为：<br>
<span style="color: #0000ff;">struct</span>&nbsp; 结构体名<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据类型1&nbsp; 成员1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据类型2&nbsp; 成员2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&nbsp;&nbsp;&nbsp; &#8230;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据类型n&nbsp; 成员n;<br>
};<br>
<span style="color: #0000ff;">struct</span>&nbsp; <strong>StuInfo</strong><br>
{<br>
&nbsp;&nbsp;&nbsp; int iID;<br>
&nbsp;&nbsp;&nbsp; wchar_t szName[255];<br>
&nbsp;&nbsp;&nbsp; bool bReg;<br>
};<br>
结构体本身的目的是为了使得功用相同的数据能够被归为一体从而便于处理，并使得数据流程<strong>结构清晰</strong>。当定义一个结构体后，可以使用结构体名去最为新类型的类型声明新变量：<br>
<strong><span style="color: #0000ff;">StuInfo</span></strong>&nbsp; XiaoMing = {20091202,&#8221;小明&#8221;,true};<br>
使用方法如下：<br>
XiaoMing.bReg = false;</span></p>
<p><span style="color: #000000;">4、共用体类型<br>
定义的一般形式如下：<br>
<span style="color: #0000ff;">union</span>&nbsp; 结构体名<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据类型1&nbsp; 成员1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据类型2&nbsp; 成员2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&nbsp;&nbsp;&nbsp; &#8230;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据类型n&nbsp; 成员n;<br>
};<br>
<span style="color: #0000ff;">union</span>&nbsp;<strong>StuInfo</strong><br>
{<br>
&nbsp;&nbsp;&nbsp; int iID;<br>
&nbsp;&nbsp;&nbsp; wchar_t szName[255];<br>
&nbsp;&nbsp;&nbsp; bool bReg;<br>
};<br>
union和struct的区别在于内存空间的分配：union<strong>共用</strong>体在声明时候，系统只会按照其成员变量中占用存储空间最大作为分配空间的标准，上面种szName占用最大，所以StuInfo的大小事255个字符的大小。你可以这样去理解，三个人轮流站岗，但是每8小时只能有一人上床休息，为了<strong>合理的</strong>节约资源，只制作了一张床，我们把床按照个子最高的人的身高作为标准制作才行。</span></p>
<p><span style="color: #000000;">5、枚举类型<br>
枚举类型用在switch的时候较多，如其名，枚举类型要求在定义的时候把所有可能的取值都列出来：<br>
<span style="color: #0000ff;">enum</span> 枚举类型名 {枚举元素1,枚举元素2,&#8230;,枚举元素n};<br>
<span style="color: #0000ff;">enum</span> Day {Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday};<br>
如果没有明确指出变量元素的具体数值，系统将自动按照从0开始依次加1的规则来赋值，即Monday = 0，Sunday = 6。从习惯来说，我们希望Monday = 1，那么我们需要这么定义：<br>
<span style="color: #0000ff;">enum</span> Day {Monday = 1,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday};<br>
系统除了按照上面规则自动赋值外，如果程序员规定了具体数值后，系统将从规定数值的变量开始依次加1，即Monday = 1的话，Tuesday是Monday+1为2。</span></p>
<p>6、类类型<br>
类类型与上面最大的不同是可以规定变量的访问属性：public、private和protected，早没有规定访问属性时候默认为private。<br>
定义形式如下：<br>
<span style="color: #0000ff;">class</span>&nbsp; 类名<br>
{<br>
&nbsp;&nbsp;&nbsp;<strong> public</strong>:<br>
&nbsp;&nbsp;&nbsp; &#8230;&#8230;;<br>
&nbsp;&nbsp;&nbsp; <strong>private</strong>:<br>
&nbsp;&nbsp;&nbsp; &#8230;&#8230;;<br>
&nbsp;&nbsp;&nbsp; <strong>protected</strong>:<br>
&nbsp;&nbsp;&nbsp; &#8230;&#8230;;<br>
};<br>
<span style="color: #0000ff;">class</span>&nbsp; Fish<br>
{<br>
&nbsp;&nbsp;&nbsp; <strong>public</strong>:<br>
&nbsp;&nbsp;&nbsp; bool Born();<br>
&nbsp;&nbsp;&nbsp; int iNum;<br>
&nbsp;&nbsp;&nbsp; <strong>private</strong>:<br>
&nbsp;&nbsp;&nbsp; void eat();<br>
&nbsp;&nbsp;&nbsp; void dead();<br>
&nbsp;&nbsp;&nbsp; int iAge;<br>
};<br>
关于类的详细内容会在下一节来讲解。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/12/02/64/">http://www.figoyao.com/blog/2009/12/02/64/</a></span></p>
<ul class="previousnext clearfix">
    <li class="previous_post"><a  href="http://www.figoyao.com/blog/2009/12/02/62/"><span>上一篇:</span> 游戏辅助工具[外挂]开发教程-从入门到精通之A1_3篇</a></li>
</ul><img src ="http://www.cppblog.com/figoyao/aggbug/104690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:27 <a href="http://www.cppblog.com/figoyao/articles/104690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A1_2篇</title><link>http://www.cppblog.com/figoyao/articles/104688.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:26:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104688.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104688.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104688.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104688.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104688.html</trackback:ping><description><![CDATA[<p>作者：<a  href="http://www.figoyao.com/" target="_blank">Figo</a></p>
<p>本篇讲解三种不同类型的控制语句：顺序结构语句、选择结构语句和循环结构语句。</p>
<p>计算机语言理论已经证明，使用上面的三种语句结构已足以表示所有问题，不同的是复杂度而已。这也就是我们常常听到的面向过程编程方法，因为是基于控制的。我们已经知道，计算机是很愚钝的，在知道了<a  href="http://www.figoyao.com/blog/2009/11/28/34/" target="_blank">基本的数据类型和运算符</a>后，当我们需要计算机为我们的意志服务时，必须把它需要做什么交代的一清二楚它才会按照指令行事，而这中间的媒介主要就是这3种语句。</p>
<p>一、顺序结构语句<br>
本语句不涉及关键字，只要相同语义范围内处于先后的语句自然构成了顺序结构。比如我们排队买票，假设你是售票员，你执行买票的过程就是顺序执行：先来的先
买到票。在编程中，每个函数体内，先出现的语句单位总是会先被执行。所谓函数体，值的就是编程中把相同功能的语句集合封装起来的一种逻辑结构。比如在QQ
里面，我们会根据好友与自己的不同关系而把好友归为不同的组，并为每组起名，有的叫<strong>同学</strong>，有的叫<strong>同事</strong>等等。但不论你怎么分组，总会有一组叫做<strong>我的好友</strong>。
而在我们写程序的时候，不论我们分不分组或怎么分组，系统都要求有一组叫做main，即所谓main函数，当然，我们会根据程序要完成的不同功能再自己定
义一些函数，把执行相同功能的语句归为一组，这就是我们的自定义函数。下面就是最简单的一个函数，它的作用是打印出&#8221;你好，游戏！&#8221;。<br>
<span style="color: #0000ff;">#include &lt;stdio.h&gt;<br>
void <span style="color: #ff0000;">main</span>()<br>
{<br>
&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">printf</span>(&#8221;%s\n&#8221;,&#8221;你好，游戏！&#8221;);<br>
}</span><br>
上面红色的都是函数名，main属于程序的入口函数，可以理解为计算机执行程序的时候首先会从main开始执行，即所谓入口；而printf属于打印函数，这个函数的实现在<strong>stdio.h</strong>文件中，正如电影有.wmv、.rmvb等格式，代码文件有.h、.cpp等格式，.h表示该文件是<strong>头文件</strong>，.cpp表示该文件时<strong>C++源码文件</strong>：头文件内容一般为函数声明，全局变量声明等，源码文件一般为函数具体的实现过程。<strong>#include</strong>关键字表示包含文件的意思，后面接要包含的文件，编译器在处理时，会用指示包含文件的内容替换掉#include声明。</p>
<p>二、选择结构语句<br>
选择语句主要有<strong>if</strong>实现和<strong>switch</strong>实现2种。<br>
1、if语句的基本形式<br>
1）、if(表达式) 语句<br>
2）、if(表达式) 语句<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else 语句<br>
3）、if(表达式1) 语句<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(表达式2)语句<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else 语句<br>
括号里面的表达式就是判断条件，我举个例子：<br>
<span style="color: #0000ff;"><span style="color: #ff0000;">if</span>(<span style="color: #008000;">是美女</span>) 要手机号;<br>
<span style="color: #ff0000;">else if</span>(<span style="color: #008000;">是美女的朋友</span>) 考虑要手机号;<br>
<span style="color: #ff0000;">else</span> 我是打酱油的&#8230;;</span></p>
<p><span style="color: #000000;">2、switch语句<br>
switch语句的存在主要是为了弥补if语句面对很多判断条件时候的不足，比如你要根据不同日期来做不同的事情，使用if语句作为判断的实现的话就会非常繁琐：<br>
if(1号) 走路;<br>
else if(2号) 睡觉;<br>
else if(3号) 游戏;<br>
&#8230;.<br>
else if(31号) 回家;<br>
</span>看到了吧，相当的繁琐，而switch的实现就很条理清晰，它的用法为：<br>
<span style="color: #0000ff;">switch(表达式)<br>
{<br>
&nbsp;&nbsp;&nbsp; case 情况1: 语句1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>
case 情况2: 语句2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>
case 情况3: 语句3;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>
case 情况4: 语句4;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>
case 情况5: 语句5;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>
&#8230;<br>
case 情况n: 语句n;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>
default: 万金油语句;<br>
}</span><br>
当进入switch语句时候，满足条件的情况就会执行，其中break的作用在于执行完本情况语句后跳出switch语句。</p>
<p>三、循环语句<br>
1、do-while<br>
do<br>
{<br>
&nbsp;&nbsp;&nbsp; 语句;<br>
}while(条件表达式);<br>
该循环的特点是第一次执行不判断条件，后面的执行一旦条件不满足就立即停止循环。<br>
2、while语句<br>
while(条件表达式)<br>
{<br>
&nbsp;&nbsp;&nbsp; 语句;<br>
}<br>
该循环语句的特点是首先判断条件是否满足，满足才执行语句，否则不执行。<br>
3、for语句<br>
for(表达式1;表达式2;表达式3)<br>
{<br>
&nbsp;&nbsp;&nbsp; 语句;<br>
}<br>
for语句的特点是，首先求解表达式1，然后判断表达式2的真假，如果真则执行，否则for循环结束；表达式3在每次循环结束后求解，当求解完毕后再次判
断表达式2是否满足。糊涂了不要紧，我举个例子，比如你要上大学，在你第一去学校报到的时候，需要注册学籍，这就是求解表达式1，只需在开始的时候求一次
即可；然后每年的开学之初你都要去教学秘书那里报到，这就是求解表达式3；每次你报到完毕呢，班主任会检查你是否满足毕业的条件，这就是求解表达式2，一
旦满足，ok，你可以毕业了，这就是所谓for循环结束。写成语句如下：<br>
for(第一次注册学籍;是否毕业;开学注册)<br>
{<br>
&nbsp;&nbsp;&nbsp; 宿舍;<br>
&nbsp;&nbsp;&nbsp; 教室;<br>
&nbsp;&nbsp;&nbsp; 食堂;<br>
}</p>
<p>今天的讲解就先到这里，下次我们开始讲解函数和指针。</p>
<p>转载请注明出处：<span id="sample-permalink"><a  href="http://www.figoyao.com/blog/2009/11/29/56/" target="_blank">http://www.figoyao.com/blog/2009/11/29/56/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104688.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:26 <a href="http://www.cppblog.com/figoyao/articles/104688.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之A1_1篇</title><link>http://www.cppblog.com/figoyao/articles/104687.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:25:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104687.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104687.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104687.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104687.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104687.html</trackback:ping><description><![CDATA[<p>作者：<a href="http://www.figoyao.com/" target="_blank">Figo</a></p>
<p>A1篇主要讲解C++程序设计基础。</p>
<p>任何一门语言本质上都是用来交流，所谓编程语言，你交流的最终对象是CPU，通过对CPU下达指令来操纵整个计算机甚至互联网。为什么是C++呢？因为这是我的入门语言（倒下一片）&#8230;其实有的人甚至用<a href="http://www.dywt.com.cn/" target="_blank">易语言</a>去编外挂，这再次说明，达到和CPU交流的目的即可，不要太在乎外皮。下面的讲解是在不对你之前的基础做太多假设的前提下进行的。闻道有先后，术业有专攻，先走过这条路的人，你们怀念下就好，别在这里充小牛，没啥意思，当然，我眼中的大牛也不会来看我的博客的，比如<a href="http://en.wikipedia.org/wiki/Donald_Knuth" target="_blank">Kunth大叔</a>。我尽量让整个教程浅显易懂、生动诙谐，但是任何技能在达到精通级别之前，都需要大量的付出。</p>
<p>语言是用来传递信息的，但是计算机对于信息的识别是很迟钝的，比如，任何时候，当你要对一个对象操作前，你得告诉计算机关于这个对象所有信息，比如
你要操作的是一个图片还是一个视频，是整数还是小数，是做加法还是做减法等等，这些都是数据。计算机的英文叫做computer，是单词
compute（v.计算）的名词，因为计算机主要的功能就是数据处理，而为了方便它处理数据，人为的把数据分成不同的类型，类似于为了方便收费，人为地
按照排量把汽车分为小排量和大排量等类型，因为这样的话交流起来就很方便，这也是为什么每个程序设计语言的开篇都会首先说说在本语言的范畴，都涉及哪些数
据类型以及基本的运算符号。在C++里，基本的数据类型有以下几种：<br>
【<strong>基本的</strong>】整数类型（int/short int/long int/unsigned int）、浮点数类型（float/double/long double）<br>
【<strong>引申的</strong>】字符类型（char）、布尔类型（bool）、空类型（void）<br>
【<strong>构造的</strong>】指针类型、数组类型、结构体类型（struct）、共用体类型（union）、枚举类型（enum）、类类型（class）<br>
所谓基本的类型，是指CPU层次的支持，引申的类型都是在基本层次上人为的赋予数据不同的含义：比如字符类型，本质上在内存中存储的也是数字而不是字符，
打个比方，监狱里面每个犯人都有唯一编号，比如9527代表的是周星星；而在计算机世界，人们把目前已知的符号进行整理，进而为每个符号规定一个数字，当
告诉计算机一个数字的集合代表字符时候，计算机就会把数字转换为字符，所以字符本质上也是数字。其它类型会在下面的教程依次讲解。</p>
<p>当我们提及一个人时，根据分类标准的不同可以把人分成不同的类别，根据性别可以分为男人和女人；根据国别可以分为地球人和火星人等等。对于数据来
说，除了依据其类型把它分成上面的类型外，我们还根据一个数据会不会改变自己的值把数据分为常量和变量：比如举个不恰当的比方，你下载一个电影时，在下载
完成之前，存储这个电影的文件是个变量，但是一旦下载完成，这个文件就是常量了。在编程过程中，我们把在程序运行中不改变数值的量叫做<strong>常量</strong>，否则叫做<strong>变量</strong>。程序中的每个数据总是属于这两者之一，所以当我们需要使用数据时候，必须告诉计算机这个数据是常量还是变量，对应于实际的&#8220;单词&#8221;就是，使用<span style="color: #ff0000;">const</span>和<span style="color: #ff0000;">#</span><span style="color: #ff0000;">define</span>来告诉计算机，语法如下：<br>
1）定义一个数值为7的整数<br>
<span style="color: #008000;"><span style="color: #ff0000;">const</span> <span style="color: #0000ff;">int&nbsp;</span><span style="color: #000000;">DAY</span> <span style="color: #000000;">= 7;</span></span><br>
2）定义一个数值为7的符号<br>
<span style="color: #ff0000;">#define</span>&nbsp;DAY 7<br>
两者的区别在于前者可以指明数据类型，而后者则不能，推荐采用第一种方法定义常量。常量最好用全部大写字母组合表示，在C++中是区分大小写的。Day和day就表示不同的名称。</p>
<p>每一个变量对应一个内存单元，至于对应多大的单元要看是什么类型的变量，都叫单元楼，其大小还有不同呢。在计算机中基本的单元度量单位叫做比特
（bit），它可以存多少数字呢，0或1！你可以这样去理解，计算机内存由大量的灯泡组成的，灯泡亮表示1，不亮表示0，那么灯泡就是最基本的表示单位，
每个灯泡叫做一个比特(bit），这就是<a href="http://zh.wikipedia.org/zh-cn/%E4%BA%8C%E8%BF%9B%E5%88%B6" target="_blank">二进制</a>。我们的计算机大厦就是建立在一堆灯泡的二进制上，神奇吧：），据说是莱布尼兹从太极图得到启发后发现二进制的。但人们习惯的还是十进制，虽然有人习惯二进制，以至于搞出二进制表：<br>
<img src="http://www.figoyao.com/blog/wp-content/uploads/2009/11/p_large_m6dD_35e90003647c2d11.jpg" title="Watch" alt="Watch" height="279" width="200"><br>
有了二进制我们可以表示任何进制的数，计算机常用的进制有：<br>
<a href="http://zh.wikipedia.org/zh-cn/%E5%8D%81%E9%80%B2%E5%88%B6" target="_blank">十进制</a>：由0到9的数字组成，不能以0开始，如110，25；<br>
<a href="http://zh.wikipedia.org/zh-cn/%E5%85%AB%E9%80%B2%E5%88%B6" target="_blank">八进制</a>：由0到7的数字组成，以0（零）为前缀，如0125，098；<br>
<a href="http://zh.wikipedia.org/zh-cn/%E5%8D%81%E5%85%AD%E9%80%B2%E5%88%B6" target="_blank">十六进制</a>：由0到9和a到f（大小写均可）组成，以0x或0X（0为零）为前缀，如0&#215;1025，0X2009。<br>
在C++中后两者没有正负之分。并且<strong>在给变量及常量取名字的时候有如下限制</strong>：<br>
1）、只能以26个字母或下划线<span style="color: #ff0000;">_</span>为<strong>前缀</strong>；<br>
2）、前缀确定后，后面部分除了1）中范围还可以用数字组成。<br>
下面举几个例子：<br>
正确的：_gold、Blood、mana；<br>
错误的：<span style="text-decoration: line-through;">91China</span>、<span style="text-decoration: line-through;">5party</span>。</p>
<p>下面开始讲解数据类型的一些细节：<br>
1、整型（integral type），数值范围如下表：</p>
<table bgcolor="#ffffff" border="1">
    <tbody>
        <tr>
            <td>关键字</td>
            <td>字节(byte)</td>
            <td>范围</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>short (int)</td>
            <td>2</td>
            <td>-32768~32767</td>
            <td>-2^15~(2^15-1)</td>
        </tr>
        <tr>
            <td>unsigned short (int)</td>
            <td>2</td>
            <td>0~65536</td>
            <td>0~(2^16-1)</td>
        </tr>
        <tr>
            <td>int</td>
            <td>4</td>
            <td>-2147483648~2147483647</td>
            <td>-2^31~(2^31-1)</td>
        </tr>
        <tr>
            <td>unsigned int</td>
            <td>4</td>
            <td>0~4294967295</td>
            <td>0~(2^32-1)</td>
        </tr>
        <tr>
            <td>long (int)</td>
            <td>4</td>
            <td>-2147483648~2147483647</td>
            <td>-2^31~(2^31-1)</td>
        </tr>
        <tr>
            <td>unsigned long (int)</td>
            <td>4</td>
            <td>0~4294967295</td>
            <td>0~(2^32-1)</td>
        </tr>
    </tbody>
</table>
<p>上表中关键字一栏中括号中的表示可以省略；<strong>1byte = 8bit</strong>。</p>
<p>2、浮点类型（floating-point number type）<br>
有三种不同范围</p>
<table bgcolor="#ffffff" border="1">
    <tbody>
        <tr>
            <td>关键字</td>
            <td>字节(byte)</td>
            <td>大致范围</td>
        </tr>
        <tr>
            <td>float</td>
            <td>4</td>
            <td>10^(-38)~10^38</td>
        </tr>
        <tr>
            <td>double</td>
            <td>8</td>
            <td>10^(-308)~10^308</td>
        </tr>
        <tr>
            <td>long double</td>
            <td>16</td>
            <td>10(-4932)~10^4932</td>
        </tr>
    </tbody>
</table>
<p>在实际编程中，常用的是double。要表示float必给数字加上f或F后缀；要表示long double必给数字加上l(字母L的小写)或L后缀，如:<br>
float fHit = 329.78F;<br>
long double lbExp = 7894.45L;</p>
<p>3、字符类型（character type）<br>
上文中说了，字符本质上是整数通过对应关系在表示，由于计算机最初产生在邪恶的资本主义国家，主要是欧美语系，所以开始的时候没有考虑到伟大的天朝的象形文字，这就导致第一代整数-字符关系表如下：</p>
<div class="wp-caption alignnone" style="width: 810px;"><a href="http://yes.nctu.edu.tw/vb/9_Misc/ASCII_1.gif"><img src="http://yes.nctu.edu.tw/vb/9_Misc/ASCII_1.gif" title="ASCII" alt="ASCII" height="1144" width="800"></a>
<p class="wp-caption-text">ASCII</p>
</div>
<p>&nbsp;随着科技春风吹拂天朝大地，问题出来了，不是每个天朝子民都懂殖民语言English，为了解决这个办法，<a href="http://zh.wikipedia.org/zh-cn/Unicode" target="_blank">Unicode</a>被提了出来，本质上就是一张更大的表而已。等到人类统治火星的时候估计还会有比Unicode大的表出来。再后面，你会越来越多的见到Unicode这个单词。要定义一个字符，有以下2种方法：<br>
1）、char happy = &#8216;H&#8217;;<br>
2）、wchar_t happy = &#8216;乐&#8217;;<br>
区别在于，前者占用1个字节（byte），是ASCII；后者占2个字节（byte），而后者是Unicode。wchar_t是什么呢，其实就是
unsigned
short，自己看上面给出的范围，这个范围就是Unicode最多表示的符号个数范围。表示单个字符时候必须用单引号括起来或者给出符号对应的数值，比
如0&#215;41表示A，那么下面的定义是等价的，<a href="http://en.wikipedia.org/wiki/Shellcode" target="_blank">shellcode</a>经常用到：<br>
char set = &#8216;A&#8217;;<br>
char set = 0&#215;41;</p>
<p>&nbsp;4、布尔类型（bool type）<br>
布尔类型数据取值只有2个：真（true）或假（false）。主要用在程序中控制数据处理流程。<br>
声明一个bool变量如下：<br>
bool bLive = false;<br>
在实际的程序设计中，任何非零的量都被认为是true，否则为false。</p>
<p>5、void类型<br>
当你要定义一个不属于以上任何类型的数据时候，可以把它定义为void，其本质上是指针。</p>
<p>以上5种类型是最基本的数据类型，构造类型的数据将放在后续章节介绍。类型讲完后就轮到运算符了，像我们以前接触的<em>加减乘除</em>就属于运算符，在C++中涉及的运算符列表如下：</p>
<table bgcolor="#ffffff" border="1">
    <tbody>
        <tr>
            <td>运算符</td>
            <td>表示</td>
        </tr>
        <tr>
            <td>算术</td>
            <td>+、-、*、/、++、&#8211;、%</td>
        </tr>
        <tr>
            <td>关系</td>
            <td>&gt;、&gt;=、&lt;、&lt;=、==、!=</td>
        </tr>
        <tr>
            <td>逻辑</td>
            <td>&amp;&amp;[与]、||[或]、![非]</td>
        </tr>
        <tr>
            <td>赋值</td>
            <td>=、+=、-=、*=、/=</td>
        </tr>
        <tr>
            <td>逗号</td>
            <td>,</td>
        </tr>
        <tr>
            <td>条件</td>
            <td>? :</td>
        </tr>
        <tr>
            <td>位</td>
            <td>&lt;&lt;、&gt;&gt;、~、|、^、&amp;</td>
        </tr>
        <tr>
            <td>指针</td>
            <td>*、&amp;</td>
        </tr>
        <tr>
            <td>求字节数</td>
            <td>sizeof</td>
        </tr>
        <tr>
            <td>强制类型转换</td>
            <td>类型(变量)、(类型)变量</td>
        </tr>
        <tr>
            <td>下标</td>
            <td>[ ]</td>
        </tr>
        <tr>
            <td>分量</td>
            <td>.、-&gt;</td>
        </tr>
    </tbody>
</table>
<p>在后面的应用中会详细讲解，这里了解即可。<br>
今天暂时到这里，我会保持每天一篇左右的进度来完成这个<a href="http://www.figoyao.com/blog/2009/11/28/24/" target="_blank">系列的文章</a>。</p>
<p>转载请注明出处：<span id="sample-permalink"><a href="http://www.figoyao.com/blog/2009/11/28/34/" target="_blank">http://www.figoyao.com/blog/2009/11/28/34/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104687.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:25 <a href="http://www.cppblog.com/figoyao/articles/104687.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏辅助工具开发教程-从入门到精通之开篇</title><link>http://www.cppblog.com/figoyao/articles/104684.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 03 Jan 2010 07:11:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/articles/104684.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/104684.html</wfw:comment><comments>http://www.cppblog.com/figoyao/articles/104684.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/104684.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/104684.html</trackback:ping><description><![CDATA[<p>作者：<a href="http://www.figoyao.com/" target="_blank">Figo</a></p>
<p>所谓游戏辅助工具通俗的说就是外挂，比如<a href="http://www.soff.net/" target="_blank">珊瑚虫</a>也是一种外挂。外挂本质上是通过修改<strong>目标</strong>的硬盘文件、内存映像数据、数据封包等[当然有时还得修改逻辑校验部分]，以达到个性化定制目标程序目的的一种辅助工具。其本质上还是计算机程序。但是，那些用病毒伪称外挂的程序编写不在我们的探讨范围。</p>
<p>在后面的教程中，我将陆续讲解的内容list如下：<br>
—————————-<br>
一、<strong>程序设计基础<br>
</strong>1.1 C++程序设计精简篇<br>
1.2 汇编程序设计入门篇<br>
1.3 Win32程序设计之SDK篇<br>
1.4 Win32程序设计之网络篇<br>
1.5 Win32程序设计之文件驱动篇</p>
<p>二、<strong>计算机系统理论基础<br>
</strong>2.1 数据结构篇<br>
2.2 加密解密算法篇<br>
2.3 深入Windows系统篇</p>
<p>三、<strong>工具使用基础<br>
</strong>3.1 OllyDbg<br>
3.2 SoftICE<br>
3.3 <a href="http://wpepro.net/" target="_blank">WPE Pro</a>和<a href="http://www.cheatengine.org/" target="_blank">CheatEngine</a>[涉及<a href="http://www.heijnen1.demon.nl/CheatEngine55src.rar" target="_blank">源码</a>个性定制部分]<br>
3.4 自制工具篇</p>
<p>四、<strong>实际应用基础</strong><br>
4.1 QQ游戏篇<br>
4.2 魔兽世界篇<br>
—————————-</p>
<p>&nbsp;以上各部分无需依次阅读，依据个人实际情况选取部分章节进行阅读即可。借用<a href="http://pjf.blogcn.com/" target="_blank">PJF</a>的一句话，<strong>动手写代码才是硬道理</strong>。
绝大多数在计算机应用领域有所成就的人，至少曾经是个代码高手，那些宣扬写代码层次低之类论点的人是很可笑的，因为整个计算机架构的基础从CPU的指令到
操作系统的构架没有一个环节可以离开代码的。这个社会需要高屋建瓴的指挥者，也需要代码高手，尤其是嘲笑写代码低级的人，你首先应该自问是否达到了高屋建
瓴的层次，但这个国度最不缺的就是小丑。</p>
<p>我还是那个观点，防御者永远不要幻想你面对的是风平浪静的计算机，在编写游戏或者其他程序的时候，你要假设一双双虎视眈眈的眼睛已经在打你程序的主
意才行，我们也不要寄希望于用户不作弊，除了大自然的规则，任何人为制定规则的游戏都会有玩家作弊，要学会心平气和的接受这个事实。有矛才会促进盾的升
级。</p>
<p>限于我知识储备集合的有限，难免有不当和错误的地方，在整个讲解的过程中，希望读者老师们能够不吝赐教。</p>
<p>完毕。</p>
<p>转载请注明出处： <span id="sample-permalink"><a href="http://www.figoyao.com/blog/2009/11/28/24/" target="_blank">http://www.figoyao.com/blog/2009/11/28/24/</a></span></p><img src ="http://www.cppblog.com/figoyao/aggbug/104684.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-01-03 15:11 <a href="http://www.cppblog.com/figoyao/articles/104684.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>