|
如果只知道易语言,那只能编一点小程序。
但是如果要写网游辅助,那就必须 先会读内存中的血蓝 ,物址等等~
查它们的工具就是CE了。
以下是关于CE的一些基本知识。
明天CE之每天一篇。。。将教大家 查找自己的背包地址。
如果有超过十个回复 的话~~
如果有些人没有锁贴的话~~~
原文由Dark Byte(CE作者)发表,Smidge204补充
大多数人认为汇编很难学,但事实上它很简单,在这个教程我将试图解释一些基本的汇编语言如何工作。
处理器以内存和寄存器来工作,寄存器类似内存但比内存快得多,寄存器有EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI,还有段寄存器,(还有一个叫EIP,这个是指令指针,它指示下一条将要执行的指令)
一些例子:
sub ebx,eax (ebx=00000005,eax=00000002)
让我们把它分成更基本的成分:
操作码,参数1,参数2
操作码是一个指令告诉处理器做什么,在这个例子里是让储存在EBX里面的数值,减少储存在EAX中的这个数。
在这个例子中EBX=5而EAX=2,所以这个指令执行后EBX的值应该是3(5-2)
还有请注意:当你看到操作码和两个参数的时候,第一个参数是指令的目标,而第二个参数则是来源。
sub [esi+13],ebx(ebx=00000003,esi=008AB100)
在这个例子里,你可看到第一个参数有一个方括号,这意思是说用一个内存的位置来代替寄存器,内存的位置由方括号中的内容指定,在这个例子里是esi+13(注意13是十六进制数)
因为ESI=008AB100,所以所指的地址是008AB113。
这条指令让保存在008AB113这个地址上的数值,减少保存在EBX上的数量,即3。
如果在008AB113位置上的数值是100,那么执行这个指令后,008AB113位置上的数值将会是97。
sub [esi+13],63 (esi=008AB100)
这个几乎和上一个完全一样,只不过是用直接数值取代寄存器。
记住了63实际上是99,因为指令中写的永远都是十六进制。
假设008AB113这个位置上的数值是100(用十六进制表示是64),执行这个指令后008AB113位置上的数值将会是1(100-99)。
sub ebx,[esi+13] (ebx=00000064 esi=008ab100)
这个指令让储存在EBX上的数值,减少在008AB113里面储存的数值(ESI+13=008AB100+13=008AB113,你没忘记吧)
上面直到这里都只使用SUB这个指令,但处理器能理解的指令其实很多很多。
让我们来看看MOV这个最常用的指令吧,虽然它的名字是MOVE(移动)数据,但它其实只是把数据从一个位置复制到另一个位置罢了。
MOV工作起来也和SUB完全一样,第一个参数是目标,第二个参数是来源。
举例:
MOV eax,ebx(eax=5,ebx=12)
把储存在EBX的数值复制到EAX里面
所以,如果这条指令被执行,那么EAX里面的数值会是12(并且EBX里面仍然是12)
MOV [edi+16],eax (eax=00000064, edi=008cd200)
这个指令把保存在EAX里面的数值(十六进制数64,也即十进制的100)放到EDI+16(008CD200+16=008CD216)这个位置。
所以执行这个指令之后,储存在008CD216这个位置上的数值将会是100(十六进制数64)
就象你看到的,它工作起来也和SUB指令一样。
然后,还有一些指令只有一个参数,例如INC和DEC。
举例:
inc eax :EAX中的数值加1
dec ecx :ECX中的数值减1
dec [ebp]: 将EBP所指的内存地址处的数值减1
现在我只讲32位寄存器(EAX,EBX,ECX......),但其实还有16位寄存器和8位寄存器可以使用的,16位寄存器是:AX,BX,CX,DX,SP,BP,SI,DI;8位寄存器是:AH,AL,BH,BL,CH,CL,DH,DL。
请注意当你改变了AH或AL寄存器时你也同时改变了AX寄存器,并且如果你改变了AX寄存器你也同时改变了EAX,其他的BL+BH+BX+EBX,CH+CL+CX+ECX,DH+DL+DX+EDX也一样。
(CCB注:以AX为例,AX是一个十六位寄存器,而AH是八位寄存器,它是指AX寄存器的高八位,而AL则是指AX的低八位。而32位的CPU增加了32位的寄存器,即EAX是在AX的基础上再加十六位,举例说明:
如果EAX的数值是(二进制):
EAX 00000000000000001101000100100111
那么
AX 1101000100100111
而AH,AL则分别是:
AH 11010001
AL 00100111
即AX包含AH和AL,而EAX包含AX,当然也包含AH和AL,不过WINDOWS上的程序一般比较少使用8位和16位寄存器)
你可以几乎完全一样地使用这些不同的寄存器,但它们只改变1(8位寄存器)或2(16位寄存器)字节,而不是改变4(32位寄存器)字节。
举例
dec al:8位寄存器AL减1
sub [esi+12],al:将储存在[ESI+12]所指位置上的一个1字节数值,减少AL寄存器中的数值
mov al,[esi+13]:将[ESI+13]所指的位置上的1字节数值,放到AL寄存器中
请注意,将16位和8位寄存器用来指示内存地址这是完全不可能的,例如:mov [al+12],0 是错误的。
其实还有64位和128位寄存器,但我不想讨论它们,因为它们比较难于使用,并且不能用于那些可以用于32位寄存器的指令。
那么,还有JUMP(跳转),LOOP(循环)和CALL(调用)
JMP:
JMP指令简单地修改指令指针(EIP)到JMP所指的位置并且继续执行下去。
跳转里面还有条件跳转,它只在特定的条件成立时才改变指令指针。(例如根据比较指令(CMP)的结果来设置跳转)
JA=大于则跳转
JNA=不大于则跳转
JB=小于则跳转
JE=如果相等刚跳转
JC=如果进位(进位标志置位)刚跳转
还有好多其他的条件跳转
LOOP:
循环指令和跳转指令差不多都是跳转到内存的其他位置去执行,不同的是它只有在ECX寄存器非0时才跳转。
(CCB注:也就是说,ECX是个循环的计数器,比如当循环开始时,ECX里面的数值是3,那么执行一次循环后,ECX会自动减1,并且跳到前面重复循环,第二次执行后ECX又再减1,当ECX为0的,不再跳回去执行)
当然,循环也有条件循环:
LOOPE:当ECX非0,并且“零标志”没有置位时循环
LOOPZ:和LOOPE相同
LOOPNE:当ECX非0,并且“零标志”被置位时循环
LOOPNZ:的LOOPNZ相同
(CCB注:CPU中有另一个特有的寄存器,零标志是这个特殊的寄存器中的一个“位(BIT)”,很多转向指令例如跳转,循环等都会根据这个特殊的寄存器中的某些位来做为条件,例如这里的零标志位和上面的进位标志,一般一个标志位上是1时即被置位,而该位为0时为没有置位)
我想我还得解释一下什么是标志,它是处理器中的一些位,可以用来检查前一指令的一些条件,好象“cmp al,12”如果AL=12那么零标志位被设置为TURE(真),否则零标志位被设置为FALSE(假)。
CALL:
调用其实和跳转一样,除了它使用堆栈来返回(即返回原处继续执行)。
解释一下堆栈:
堆栈是由ESP寄存器为指针所指的内存位置,你可以使用PUSH命令把数值压进堆栈,并且使用POP指令将数值弹出。当你使用PUSH时ESP寄存器会减少,并且把数值放置到ESP所指的位置。当你使用POP时会把数值弹出到POP指令的参数所指的位置,并且ESP寄存器数值增加。简言之,就是最后压堆栈的数据最先出来,倒数第二个压进去的,第二个出来。
(CCB:堆栈的特点就是“后进先出”,想象一下,一个单车道的停车场,第一辆车停到最里面,第二辆车又停进去,然后第三辆车再开进去停在最外面,要出来的时候,是不是第三辆车要开出来之后,第二辆才能出来?要第二辆车开出来之后,第一辆开进去的才能出来?)
RET:
当CALL调用时会把(返回后要执行的)下一条指令的地址压进堆栈,RET(返回)就跳转到这个位置执行(即把指令指针设置到这个位置)。
(CALL调用时)执行到一定地方会遇到RET指令,就会跳转到储存在堆栈中的位置中去执行。(CALL把下一条指令的位置压进堆栈,而RET就把这个位置弹出来并跳到那里执行)
这就是最基本的汇编教程,如果你有什么有关汇编的问题,请提问,我会尽量回答。
如果你想得到更详细的信息,这里有个很好的文件:
http://podgoretsky.com/ftp/Docs/ ... /Intel/24547111.pdf
注:理解括号中的数值的用法这一点非常有用,因为以后在使用CE时要用到指针(它可以解决大多数游戏的DMA(动态内存定位)的问题,如果你能看得懂什么汇编指令在修改你找到的数值的话)。
----------------------------------------------------------
“标志位”是保存在一个特殊寄存器中的一些BIT的集合,如果某个BIT是1,即是说这个标志被“置位”,如果是0即是说它被“清除”,正确地说,标志位告诉你处理器中所有的内部状态并给你更多关于前一指令执行的信息。
标志位有三种:状态标志告诉你最后一条指令执行的结果,控制标志告诉你处理器将会怎样,而系统标志告诉你,你的程序执行时的内部环境。
标志寄存器有32个位:(S=状态标志,C=控制标志,X=系统标志)
代码:
0 S 进位标志
1 (保留)
2 S 奇偶标志
3 (保留)
4 S 辅助进位标志
5 (保留)
6 S 零标志
7 S 符号标志
8 X 陷阱标志
9 X 允许中断标
10 C 方向标志
11 S 溢出标志
12 X I/O特权标志(12及13位)
13 X
14 X 嵌套任务标志
15 (保留)
16 X 复原标志
17 X 虚拟8086标志
18 X 对齐检验标志
19 X 虚拟中断标志
20 X 虚拟中断未决标志
21-31 (保留)
让我们看看状态标志,因为这些比较经常用到。
溢出(进位):
当一个操作(加、减、乘等)产生的结果太大,不能存进寄存器或内存位置时,进位标志置位(否则的话,则自动清除该标志位)。例如你使用一个16位寄存器,而你的指令产生的结果数值大于16位,则进位标志被置位。
符号:
当结果为负数时被置位,如果是正数则清除。这个是一个数值的符号位的镜像。(CCB注:就是与结果数值的最高位相同)
零标志:
如果操作结果为0则此位被置位。
辅助进位:
与进位标志相同,但它对待寄存器或内存是以3-BITS(位)而不是普通的8,16或32位,这个用于BCD(二进制编码的十进制数)方面的东西,其他地方根本没什么用。
进位标志:
当第一个BIT超过寄存器/内存的限制时,进位标志被置位。举例来说,mov al, 0xFF,然后add al,1 将会导致进位,因为第九个BIT被设置,而且要注意,溢出标志和零标志也会被设置,而符号标志会被清除。 |
评分
-
参与人数 1 | 魅力 +6 |
金币 +4 |
收起
理由
|
穷人木木
| + 6 |
+ 4 |
我们非常欢迎来帮助大家学习的人, 又同时欢 ... |
查看全部评分
|