洞窟物语吧 关注:3,546贴子:130,977

【翻译】洞窟物语汇编语言教程

只看楼主收藏回复

翻译自@麦士隆 提供的汇编教程。
不知道吧里有没有人做过,翻了精品看了一下,应该是没有。
一天一节的进度没有问题。。。大概
很多专业名词都不确定,欢迎指正。
先放出前三课。


IP属地:福建1楼2016-06-22 11:21回复
    介绍
    开始汇编训练
    你好,欢迎打开这本《洞窟物语汇编修改初级指导》。
    我是卡罗特罗德,将指导你们。
    在开始之前,这本指导是为汇编修改的纯新手设计的:那些几乎不懂我们将要学习的汇编语言的人。
    在阅读这本指导时,我建议你们分成几天或几周阅读。这本指导有大量的信息,因为我持续不断地向里面添加新内容。一次性阅读完全部内容只会让你疲惫不堪。
    如果你是一名资深洞窟物语汇编语言修改者,即使你已经知道了本书的很多内容,你一样可以阅读这本指导。并且,当然请自由指出本指导的错误并作出其他建议。
    那么,一起开始吧。第一课:假设,假设


    IP属地:福建2楼2016-06-22 11:22
    回复
      居然还真有人对这个有兴趣,那少年你就加油吧,我就不多说了。


      IP属地:江西5楼2016-06-22 13:50
      回复
        三楼链接太多果然被抽了。。。。


        IP属地:福建7楼2016-06-22 19:58
        回复
          再抽的话圈一下楼主


          IP属地:福建10楼2016-06-22 20:03
          收起回复
            这个必须顶、再更一些估计要精


            IP属地:重庆来自Android客户端12楼2016-06-23 12:48
            回复
              好东西,尽管好长时间不接触mod已经有些不懂……


              IP属地:上海来自Android客户端13楼2016-06-23 12:54
              收起回复
                玩了好多mod80%都坑了啊啊啊啊啊


                IP属地:日本14楼2016-06-23 13:57
                收起回复




                  IP属地:福建15楼2016-06-23 14:57
                  回复
                    这个教程的大部分,估计基本都是在讲汇编的了
                         -- (´▽`)ノ♪


                    IP属地:江西来自Android客户端16楼2016-06-23 20:10
                    收起回复
                      数据和登录器
                      十六进制数据以及保存他们的登录器
                      现在我们要真正开始汇编修改了。
                      字节和字符
                      数据是原始信息。电脑会将它们处理成二进制数据,就像我们早些看到的那样。
                      一个字节是一个简单的0或1的二进制数据。二进制数据11010包含5字节。
                      一个字符是一个8字节构成的数字。二进制数据01111011包含8字节,意味着它一定是个字符。
                      一个字符由两个十六进制数据组成。一个典型的字符也可以是这样的:
                      B6
                      (它有两个十六进制数据)
                      现在,我给你一份常用数据单位表:
                      字节=一个简单的1或0
                      半字符=4字节=1十六进制数据
                      字符=8字节=2十六进制数据
                      字=16字节=4十六进制数据
                      双字值=32字节=8十六进制数据
                      四字符值=64字节=16十六进制数据
                      我们主要用双字值工作,长8个十六进制数据的数字。
                      半字符主要用于一些琐事,我们很少用到它,可能永远都不会。一个半字符是一个字符的一半,因为无论何时你轻咬食物,你都只咬半口(哈哈……真是一个烂笑话)。(注:nibble在英语中既有半字符的意思,也有轻咬的意思)
                      双字值代表“两个字的值”然后四字符值代表“四个字符的值”。这才讲得通。一个数字长4个十六进制数据。一个双字符(8个十六进制数据)是一个字的两倍,一个四字符(16十六进制数据)是一个字的四倍。
                      登录器
                      数据是一切,但是当没有地方放置它们的时候,它们就不管用了。登录器为保存数据设计,所以它们实际上像存储数字型数据的小“盒子”。
                      登录器像你在数学或电脑编程中使用的可变因素。可变因素保存数字——或者至少它们传递数字。但是,登录器不是真正的可变因素。
                      登录器表:
                      EAX
                      ECX
                      EDX
                      EBX
                      ESP
                      EBP
                      ESI
                      EDI
                      等等,你不能使用全部!只有EAX,ECX和EDX可以用作你的私人用途。其他登录器保存着重要数据,这些数据是你不能胡乱摆弄的。
                      为什么把你自己的数据放进ESP很危险?ESP是最高级的堆叠指示器。这意味着它定义堆叠顶部的值的地址。如果你随机改变ESP的值,你就会弄乱堆叠!(是的,我意识到了我还没有解释什么是堆叠,但是我们稍后会提及)。
                      每个3字的登录器能保存32字节的值。这意味着,它实际上能保存8个十六进制数据(但是一些数据可能是0,所以你能储存小数字)。像EAX能保存数字00003105,或006C03A4,或数字FEEDBEEF。所有这些十六进制数字长8字符。
                      登录器不只是能保存数字的地方。每个地址代表一个记忆位置,所以地址也可以用于保存数字。我们将在将来的课程中讲到这个。
                      整数
                      规律的登录器(EAX,ECX,EDX,等等)只能保存整数。
                      整数:
                      ... -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6 ...
                      就像你看到的,整数包括正整数,负整数,还有0。整数不包括任何分数和小数点。所以,你不能保存像12.55或是2/3这样的数到EAX里。
                      有小数点的数叫作浮点数。稍后我们会解决这个问题。
                      下一课:指令


                      IP属地:福建21楼2016-06-28 08:30
                      回复
                        指令
                        这就是ASM命令
                        指令的格式
                        几节课前我们看到了ADD ECX,3指令并且讨论了它的用法。现在你应该知道ECX是用来储存数字的登录器。我们将用十六进制数格式代表这些数字,所以ADD ECX,3意思是“添加十六进制数3到登录器ECX中。”当然,3(十六进)=3(十进)所以这次你甚至不需要知道十六进制是什么就能懂得指令在干什么。。
                        一起看看一条指令的基本格式。
                        这里我们看到ADD EAX,72A5。这条指令会将数字72A5加到登录器EAX中。
                        指令的第一部分叫作助记然后其他部分叫作操作体。
                        ADD ECX,72A5有助记和其他两个操作体:EAX和72A5.
                        个人而言我不喜欢分成助记和操作体,因为这不是我们平时常用的词。如果第一部分被叫做“动作”而后面的部分被叫做“物品”听起来会更顺口。ADD是动作(它执行加法)并且它对后面两个物品执行动作(登录器EAX和数据72A5)。然后再次,官方的说法是“助记”和“操作体”,所以当你看到这种分类时,记住它们是什么意思。
                        指令
                        这里是你将会使用的一长串指令:
                        MOV A,B=将B的值赋给A。“A”可以指一个登录器或是一个记忆地址。“B”指一个登录器,一个记忆地址或者一个数字。
                        NOP=无操作。最简单的指令,因为它叫电脑在一段时间内什么也不做。
                        JMP=跳到代码中的地址C,然后从那里开始继续代码。
                        CMP A,B=比较A和B。这条指令会竖一系列的“汇编旗”,完全不同于你在意的TSC的旗。
                        这些有条件的指令是为了检查汇编旗的变动。直接跟在CMP指令后使用它们。
                        JE C=如果A和B是平等的就跳到地址C(A和B从先前的CMP指令中来)。
                        JNE C=如果A和B不平等就跳到地址C。
                        JG C=如果A比B大就跳到C。
                        JGE C=如果A大于或等于B就跳到C。
                        JL C=如果A小于B就跳到C。
                        JLE C=如果A小于等于B就跳到C。
                        PUSH和POP对堆叠起作用。我稍后会介绍堆叠。
                        PUSH A=将A推到堆叠的顶部。A可以是一个数字,一个记忆地址或者保存数字的登录器。
                        POP A=消除堆叠顶部的值,将它赋给A。这个情况下,“A”指一个登录器或记忆地址。
                        数学操作:
                        INC A=增加登录器或记忆地址A数1。将结果赋给A。
                        DEC A=减少登录器或记忆地址A数1。将结果赋给A。
                        ADD A,B=将A,B加到一起。将结果赋给登录器(或者记忆地址)A。B可以是一个数字,登录器或是记忆地址。
                        SUB A,B=从A中减去B。将结果赋给A。
                        记忆地址的垃圾是什么?我们已经学了登录器和十六进制数,但记忆还没有。记忆将在后面几节课讲到。
                        也有乘除数字的方法,后面几节课会讲到。
                        我还没有给你所有的指令。指令有很多,所以如果你不知道其中一个有什么用,在OllyDbg中右键单击它,选“命令帮助”这个会准确告诉你指令起什么用,但它不会给非常详细的解释。
                        下一课:使用MOV


                        IP属地:福建22楼2016-06-29 17:39
                        回复
                          指示器和记忆
                          数字的赋值地址。大量的赋值地址。
                          记忆
                          当洞窟物语程序开始运行的时候,每个ASM地址都代表电脑记忆中的一个地址。其中一些地址可以修改(你可以使用像MOV这样的指令来存入/加载里面的地址)。其他的记忆地址在游戏运行中不能修改(只读地址)。
                          指示器
                          让我们再看一些ASM代码:
                          MOV EAX,12
                          MOV ECX,8002
                          MOV EDX,AA91BD
                          这些代码是做什么的?简单。它将十六进制数12,8002和AA91BD存到EAX,ECX和EDX里。
                          图1
                          这里每个盒子代表一个登录器。有绿色标签的部分是登录器的名字:EAX,ECX或EDX。
                          指示器是什么?可以是任何东西,比如一个登录器或是一个数字,能够“指向”一个数字能被修改的地址。
                          举个例子,MOV DWORD [49E6D0],60使用十六进制数49E6D0指向地址49E6D0,一个能存储一个DWORD大小的数据的地址。
                          图2
                          很好。所以MOV DWORD [49E6D0],60将数字60存到了地址49E6D0里。方括号的意思是“将这个数字当做地址使用”。
                          间接地址
                          间接地址是一个用登录器指代地址而不是数字的很有趣的项。假设EAX存着数字49E6E8。
                          那么MOV DWORD [EAX],100做什么?
                          图3
                          我们看到蓝色标签的盒子【EAX】和【49E6E8】是一样的。
                          在这种情况下,执行MOV DWORD [EAX],100和 MOV DWORD [49E6E8],100是一样的。
                          这两条指令都将数字100存进地址49E6E8。
                          图4
                          注意EAX本身没有被修改。EAX在指令后依然保存着数字49E6E8。当你将EAX或者其他登录器放进方框里时,登录器简单地将标签定义到一个盒子的盖子上。打个比方。
                          我们甚至可以像这样做一些更复杂的事情。看下面的代码:
                          MOV EDX,490000 ;store hex number 490000 into EDX.
                          MOV DWORD [EDX+9C6C],3 ;store hex number 3 into the address pointed to by EDX+9C6C.
                          哇啊……EDX加9C6C?想想看……如果EDX保存着490000,那么EDX+9C6C=499C6C。(如果你很混乱,就用Windows计算器来进行十六进制计算)。
                          图5
                          当EDX保存着490000的时候,MOV DWORD [EDX+9C6C],3和 MOV DWORD [499C6C],3是一样的。这个位于地址499C6C的DWORD大的数据现在有值3。哟。
                          甚至在 MOV DWORD [EDX+9C6C],3执行之后,EDX本身也没有被修改。现在还是储存着490000。登录器EDX(看用绿色标签标记的EDX)不是保存着499C6C,当然也不是数字3。
                          如果你想让EDX保存499C6C或三该怎么做?直接用MOV就好了。
                          MOV EDX,490000 ;store hex number 490000 into EDX.
                          MOV DWORD [EDX+9C6C],3 ;store 3 to address 499C6C. EDX still holds 490000!
                          MOV EDX,499C6C ;Now EDX actually holds 499C6C.
                          MOV EDX,3 ;Now EDX actually holds 3.
                          记忆到记忆存储:一次一个
                          还有一个我必须提到的关于记忆地址的事情。
                          假设你要把数字放进DWORD [450600]并将它复制到DWORD [49E670]。
                          看起来很直接。用MOV,对吗?
                          MOV DWORD [49E670],DWORD [450600] ;Store the number located in [450600] to [49E670]?
                          这没有效果。OllyDbg会说“常数超出范围”或者其他同样荒谬的东西。
                          记忆对记忆的存储不能直接使用。如果你想要将数字从 DWORD [450600]移到DWORD [49E670], 医药使用一个登录器(例如EAX)来保存数据。
                          MOV EAX,DWORD [450600] ;Store the number located in [450600] to EAX.
                          MOV DWORD [49E670],EAX ;Store the number located in EAX to [49E670].
                          所以记住——你不能在一个MOV指令中使用两个记忆地址(被称为操作数)。你需要一个登录器来运送数据。所以,记忆对记忆的存储需要至少2个MOV指令。
                          下一课:两级的生命胶囊


                          IP属地:福建24楼2016-07-01 16:15
                          回复
                            跳跃指令
                            使用代码移动
                            在之前的例子里,我们替换了指令,让北极星做出了不同的动作。但是我们需要去掉一些旧的指令来添加新的指令。怎样才能在不用替换大量旧代码的情况下,添加很多行新代码?你就要用到跳跃指令。
                            我们之前已经见过了跳跃,但是这里有一些新的例子:

                            从地址4937F7开始,程序会执行四条指令,然后跳跃到497000.跳跃之后,DEC EDX指令被执行费,接下来下面的指令就按顺序执行。
                            用跳跃命令的CMP
                            地址 指令 命令
                            004937F7 MOV EAX,0 ;Store 0 to EAX.
                            004937FC INC EAX ;Increase EAX by 1.
                            004937FD CMP EAX,50 ;Compare EAX with 50 (hex).
                            00493800 JGE 00450DE9 ;If EAX is greater than or equal to 50 (hex), jump to 450DE9.
                            00493806 PUSH 9955 ;If not, push 9955 onto the stack.
                            0049380B JMP SHORT 004937FC ;Jump to address 4937FC
                            上面的代码复杂了很多。大致看一下它做了什么:
                            代码将0存到EAX中,并增加一。
                            它检查 EAX是否比50大或者和50(16进制)一样大。就是十进制的 80。
                            如果EAX比 80(十进制)大或者一样大,代码就会跳到完全不同的地方(地址450DE9)。
                            如果不是,9955就会被推进堆叠,接下来代码就会稍微向后跳到INC EAX... CMP EAX,50...的循环中。
                            EAX就像一个从一到 80的计数器。当EAX最终到达 80到时候,代码跳到450DE9。
                            最终结果:9955被推到堆叠上79次(80次循环时,程序在它推动9955之前就跳到地址450DE9了)。

                            现在,绝对没有实际目的推动9955那么多次。即使如此,这也是非常好的循环代码的例子:一个东西不停地重复,直到某些情况发生为止。多亏了循环,我们没有必要写PUSH 9955 79次(这将占79行代码)。相对的我们只需要6行ASM代码!
                            JMP SHORT ?
                            JMP和JMP SHORT有什么不同?
                            JMP意味着你可以跳跃很长一段距离,但是JMP SHORT意味着跳跃短距离。JMP SHORT非常棒因为它比JMP占的空间更小。
                            (JMP SHORT占两个字节,但是一个跳跃根据跳跃的距离占五或六个,我记得很清楚)。
                            你永远也不要担心输入“JMP SHORT ”,只要输入JMP。如果有必要,OllyDbg会自动把JMP转换成JMP SHORT。这对其他类型的跳跃指令也有效。例如,使用JNE SHORT也有可能。
                            特别说一下,JMP SHORT最多可以向前跳跃 129字节(从JMP SHORT的开头开始),或者向后跳跃126字节。因为计数不总是那么容易的,所以你可能需要OllyDbg来完成。
                            下一课:呼叫和返回


                            IP属地:福建27楼2016-07-04 10:36
                            回复