我爱秘籍论坛

 找回密码
 加入论坛

QQ登录

只需一步,快速开始

扫一扫,访问微社区

CE:最优秀的游戏修改工具入门:修改器制作傻瓜教程说说:你最想要找的修改器以前游戏玩我们,现在我们玩游戏
进阶:游戏修改视频教程导航必备:超2400款游戏秘籍下载:超5000款游戏修改器必读:论坛金币获得方法
查看: 7033069|回复: 3795
打印 上一主题 下一主题

[分享] CEAA教程:A Very In Depth Tutorial on Auto Assembler(译)

  [复制链接]
跳转到指定楼层
发表于 2011-1-7 22:51:12 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
本帖最后由 cn_zou 于 2011-1-8 13:52 编辑

此文很适合AA入门,看上去很长,但作者一直用一种比较诙谐的讲述方式,读下来并不难,而且本文的内容一点都不难。
本人英语渣,出现误译及错别字请多包涵。
原文地址:http://forum.cheatengine.org/viewtopic.php?t=95363

------------------------------
内容表
------------------------------

I. 介绍
II. 寄存器
II.a 32位寄存器
II.b 16位寄存器
III. 指令
III.a JMP
III.b MOV
III.c Push/Pop + The Stack
III.d alloc/label/registersymbol
III.e Call and Ret
III.f 其他
IV. Array of Bytes
V. 结尾
VI. 人员名单/致谢词
  
额外内容: 写一个脚本  
  
------------------------------
I. 介绍
------------------------------
'哟,我猜你在读这个是因为下面两件事中的一个。
  
1) 你正在试图学习自动汇编 (我不会叫你菜鸟,因为每个人都是从哪里开始的,对吧 =) )
or
2) 你想测试你的自动汇编知识 (作为扩展)。
  
那么,如果你是前者,那就慢慢的体会好每个部分,并且在继续进行前确认自己已经明白了这章。

Dark  Byte wrote:
大多数人都认为AA很难,其实它可容易了。

来自CE作者自己的话

如果是后者,那我不会给你提任何的建议,即使我想帮忙。如果你发现有什么错了,或者含糊或者认为我可以做的更好,请告诉我。我一直处于自我学习的状态! 等等!别问,我知道你在想什么。

  You  wrote:
  为什么我非要听一个还在学习的人的话?

好,我来告诉你,我的朋友。即使我仍然在学习,我了解AA,并且我认为与你分享知识是一件很棒的事。 =)

Edit: 这个是很久以前写的,但是现在我学到了很多,并且已经重新检查了。

现在,让我们投身入奇幻的电脑世界

------------------------------
II. 寄存器
------------------------------

这些也许你已经在一些脚本中看到过,它们被非常广泛的使用。有两种寄存器被使用,接下来来进行讲解。  

---------------
II.a 32 Bit
---------------

首先,我将解释每个寄存器是如何得到它们的名字的,这会帮助你记住它们哪个是哪个。首先,以E开头 (如果你注意了下面,你会发现所有的寄存器都是以E开头的) 它告诉你这个寄存器是32位寄存器。而A,B,C,D的含义你看完描述就能明显得体会到了。像SI, DI, BP,SP,IP也是一样。在 EAX, EBX, ECX, EDX后面的X,他简单的表示已经没有更多的字母了。有点像一个 NOP 命令 (之后你将读到)。如果你注意了,你会发现每个32位寄存器都是3个字母。  

EAX: 累加器(Acculmulator register)。能够用来当存储器
EBX: 从前, 它是个基础寄存器,但现在只是个闲着的存储器
ECX: 计数器(Counting register)。也能用来当存储器
EDX: 数据寄存器(Data register)。 跟之前三个一样,能用来当存储器。
ESI: 源址变址寄存器(SourceIndex register)。 是字符串形式的指针变量,但你现在还不用担心那部分。 能够用来当存储器。
EDI: 目的变址寄存器(DestinyIndex register)。又一次,能够当作存储器,并且是个字符串形式的指针变量, 但别担心。
EBP: 机制指针寄存器(Base Pointer register)。 是用来临时存储ESP, 当然也可以像常规的存储器那样使用。
ESP: 原址指针寄存器(Source Pointer register)。它在堆栈里指向寄存器和地址(这个内容待会再说)。  
EIP: 指令指针寄存器(Instruction Pointer register)。 错误的使用会使你正在试图修改的程序崩溃。

---------------
II.b 16 Bit
---------------

16位寄存器和32位寄存器很相似,他们间有两个区别。一是,32位寄存器名字是三个字母,而16位寄存器是两个字母。还有一件事就是16位寄存器比32位寄存器多但别担心。16位寄存器我们一般都用不上。

AX: 参照 EAX
BX: 参照EBX
CX: 参照ECX
DX: 参照EDX
SI: 参照ESI
DI: 参照EDI
BP: 参照EBP
SP: 参照ESP
IP: 参照EIP

---------------

关于寄存器的内容还很多。 如果你想学习更多关于寄存器的只是, 那就去拜Google大神吧。 对于绝大多数的学习者来说求知欲都是很重要的。

------------------------------
III. 命令
------------------------------

当今,什么语言没有它自己的函数和命令呢? 与英文相比,命令像个单词,而操作代码像个句子。操作代码并不难,比如:

  Code:  
  jmp 00123EAA


关于操作代码你应该知道两点。

首先, 在操作码里,一般都会有个地址或者寄存器,以及一个显而易见的命令。地址是Hex形式的,是Hexadecimal的缩写。Hexadecimal是16进制数。 就如同10进制那样。

按照这种思路想一想。如同上面提到的那样,我们一般使用十进制。这就意味着我们在一个列里不能有“10”, 因为它占了两个地方。 而16进制,10至15都可以放在一个列里头。但是你会发现,“10”并没有出现在列里头。

先冷静, 这是因为在Hex进制里,10是用A表示的,而11是用B,直到15是F。再往后,它就是10,然后11,直到1F, 如果超过了20(十进制)就得从15(十六进制)往后算。有个简单的转换方法就是用操作系统自带的计算器,这里不赘述了。

还有,每一个地址都有它的操作码和字节码。这个字节数就是代表操作码是什么, 每一个命令都一一对应已经定义好的字节码。我知道那些常用函数的字节码是什么,如果你想知道那些字节码的话,你还是指望别人吧,推荐去拜Google大神 =)
  
最后,想注释很方便。 要注释的话, 就把"//"放在命令后边或某块空处,然后打上你想打的。如果你不打 "//" ,那电脑就会以为你在打命令呢。

现在,让我们来了解每个命令都是干啥的。
---------------
III.a JMP
---------------

JMP 命令是最常使用的命令之一 (就如同 MOV 那样, 接下来会讲)。 也许你在操作码和脚本里看到的"JMP" 不像"MOV" 那么多,那是因为 JMP 命令有很多变种。下面就是列表。  

JMP: 始终跳转(Always jump to)
JE/JZ: 相等则跳转(Jump to if equal)
JNE/JNZ: 不等则跳转(Jump to if not equal)
JA: 无符号大于则跳转( Jump to if Above)
JG: 有符号大于则跳转(Jump to if Greater)
JNA: 无符号不大于则跳转(Jump to if not Above)
JNG: 有符号不大于则跳转(Jump to if not Greater)
JB: 无符号小于则跳转(Jump to if Below)
JL: 有符号小于则跳转(Jump to if Lower)
JNB: 无符号不小于则跳转(Jump to if not Below)
JNL: 有符号不小于则跳转(Jump to if not Lower)
JAE: 无符号大于等于则跳转(Jump to if Above or Equal)  
JGE: 有符号大于等于则跳转(Jump to if Greater orEqual)
JNAE: 无符号不大于等于则跳转(Jump to if not Above orEqual (即 JB) )
JNGE: 有符号不大于等于则跳转(Jump to if not greaterthan or Equal (即JL) )

现在你大致了解了,应该有些疑惑。 "Jump to if greater"或者JG都是条件跳转。 条件跳转都如同它们名字所描述的那样,会在条件成立的情况下跳转。通常,都会有CMP或者其他的比较函数在上面,这个待会再提。以上大抵就是JMP的故事。  

---------------
III.b MOV
---------------

前文已经提过, MOV 命令是最被广泛实用的命令,因为它是那么给力。 下面就是MOV的例子:


  Code:
  mov eax,ebx

这个的意思是 "把ebx里存的地址放到eax里"。注意在两个寄存器之间还有个逗号,而不是空格。 最开始这可能有些令人费解,但是它真的很容易,下面来好好解释一下。  

"Mov"是"move"的意思。 寄存器自身表示"这个寄存器里存的地址"。 基本上来说, "把ebx里存的地址放到eax的地址里面去", 这会把eax之前的值覆盖并彻底消灭掉。=D你可以通过这个方法复制ebx并把它粘贴到eax里。  

另一种Mov命令。


  Code:
  mov eax,[ebx]

这个的意思是把ebx里面的值存到eax所存的地址里,很简单, 把寄存器或者地址用[]那么一括,就表示寄存器或者地址的值了。
下面这段代码什么效果都没有。


Code:
  mov [eax],[ebx]

没效果,上面的代码啥用没有。你不能!你不能直接把一个值存在另一个值里面。你可以间接得先把值存在其他的东西里 ;) 参考下面的代码。


  Code:
  
  push eax                      //
先让eax入栈这个待会解释
  mov eax,[0100200A]      //
把值0100200A存到eax
  mov [ebx],eax              //
(0100200A) 存到ebx的值里面
  pop eax                       //
然后让eax出栈,这个也待会讲

解释这个是为了MOV函数。继续...

评分

参与人数 11金币 +89 鲜花 +3 收起 理由
一天仪式 + 1 赞一个!
加油!奥利奥 + 1 感谢您的分享!
shenhao6019 + 1 感谢您的分享!
1300371669 + 1
ty1106576 + 1 原创作品,加分鼓励!
WZ1998914 + 1 S
现实是一种无奈 + 1 ..
aa8384890 + 1 谢谢LZ无私的翻译
wujia + 1 简单易懂,不错。
我爱秘籍 + 30 加精,功德无量的好事
w110112117 + 50 + 3 辛苦了

查看全部评分

本帖被以下淘专辑推荐:

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏70 转播转播 分享分享2 分享淘帖1
推荐
发表于 2011-1-9 13:45:34 | 只看该作者
  LZ辛苦了       英语不好        上CE的论坛等于看天书
  这篇我收藏了

点评

不错饿  发表于 2012-3-7 17:38
回复 支持 4 反对 1

使用道具 举报

推荐
发表于 2015-9-2 18:59:20 | 只看该作者
加油,支持你哦,哈哈哈哈哈哈
回复 支持 1 反对 0

使用道具 举报

推荐
发表于 2015-5-26 16:46:00 | 只看该作者
终于知道这些脚本的含义了,受教了
回复 支持 1 反对 0

使用道具 举报

推荐
 楼主| 发表于 2011-1-7 22:53:03 | 只看该作者
本帖最后由 cn_zou 于 2011-1-8 14:38 编辑

------------------------------
Bonus. Writing a Script
------------------------------
   
既然你读了教程,那也应该很了解了,但你还是想知道更多。 我明白, 就如同我体会过的—遗憾。我不认为有任何关于写脚本的教程是我用的上的。

  Code:  
  [ENABLE]
  alloc(AutoAssembler,1024)
  alloc(SayWhat,1024)
  alloc(WooHoo,1024)
  label(Continue)
  registersymbol(WooHoo)
  
  AutoAssembler:
  mov eax,02
  cmp eax,03
  jne Continue
  je SayWhat
  
  Continue:
  cmp eax,[WooHoo]
  
  SayWhat:
  jmp 0
  [DISABLE]
  dealloc(AutoAssembler)
  dealloc(SayWhat)
  dealloc(WooHoo)
  unregistersymbol(WooHoo)
  

还记得之前的这个脚本吗? 现在让我们用我们所学的大量内容把它弄完整。

  Code:
  [ENABLE]
  alloc(AutoAssembler,1024)
  alloc(SayWhat,1024)
  alloc(WooHoo,1024)
  label(Continue)
  registersymbol(WooHoo)
  
  AutoAssembler:
  mov eax,02
  cmp eax,03
  jne Continue
  je SayWhat
  
  Continue:
  cmp eax,[WooHoo]
  
  SayWhat:
  jmp 0
  
  [DISABLE]
  dealloc(AutoAssembler)
  dealloc(SayWhat)
  dealloc(WooHoo)
  unregistersymbol(WooHoo)
  

对于脚本你需要有些东西, 一个你试图hack的程序的真实内存的地址。 无论如何, 它都不能是一个随机的地址, 或者是一些你不希望它发生但是会导致其发生的地址(崩溃,也许)。这个地址对于这件事很重要。
但是为什么我们需要一个地址? 就如同之前我所说的,alloc 函数在你的程序中分配一块未使用内存。因为这是未使用的,程序不会访问这里,所以,你要让程序访问它。
当你干预这些地址时,你需要注意一些至关重要的事情。第一, 你必须用与源码相同总量的字节。 如何知道一个操作码字节的数量呢? 简单,看在地址和操作码中间,那儿应该有一堆两个一组两个一组的字符,他们被称为Array of Bytes。
  
nop 函数对于这种情况非常有帮助。就如同我之前解释的那样,它的含义是“无操作”。并且它只用一个字节。这意味着,如果你用不了所有的字节位置,那你就可以用nop把它填满。
当填字节时你可能会遇到三种情况。我已经描述了第一种你的代码比源码少的情况。剩下两种情况的一个是,你的代码所占的字节数和源码字节数相等,一切刚刚好。
但最后一种情况有些令人困惑,那就是你的代码的字节比源码的多。现在,你的代码的字节会把下面的代码字节覆盖,直到字节的位置够用。

为什么我们不玩Minesweeper呢? 一段时间之前,我还在学习写脚本的时候,我写了一小段代码(我还是我,但那时我还知道的很少)。

  Code:  
  [enable]
  alloc(WhatNowMinesweeper,256)   //分配...
  alloc(ChiliDog,4)
  label(ReturnHere)  
  registersymbol(ChiliDog)               //注册...
  
  ChiliDog:
  dd 0                                         //用于参考引用,表示ChiliDog的值是从0开始
  
  01002FF5:                                 //这个地址是为MineSweeper写入时间的
  jmp WhatNowMinesweeper            //我重写了操作码,让它跳转到我的脚本  
  nop                                          //填充了最后的字节
  ReturnHere:                               //这个是干什么的我待会告诉你
  
  WhatNowMinesweeper:                //我的实际代码
  push eax                                   //保存eax, 我们不这么做就会有问题
  mov eax,[ChiliDog]                      //把ChiliDog的值传入eax
  mov [0100579C],eax                   //把存有ChiliDog值的eax存入时间
  pop eax                                    //让eax出栈,因为我们已经用完了
  jmp ReturnHere                          //跳转到ReturnHere, 待会解释
  
  [disable]
  dealloc(WhatNowMinesweeper)     //取消分配内存
  dealloc(ChiliDog)
  unregistersymbol(ChiliDog)           //反注册标识
  
  01002FF5:                                //这是我修改来跳入我的代码的地址
  inc [0100579C]                          //这是源操作码用以防止崩溃
  

现在,最最先要做的。我要告诉你"ReturnHere"是什么。 如你所知,一个被告知要执行一个操作码的程序进程,他们会自动移动到下一个操作码,然后继续。 这就如同一个无限的轮回。这样,如果我们弄了条死路,即代码之后已经没有代码了,那这个程序几乎就会崩溃。因此, 我们要让它执行过我们的代码之后再返回到调用跳转之后的位置上,这样代码就可以继续了—并且我们也不会崩溃! =D
关于写脚本还有很多内容。 请自由的提问并且评论你是否喜欢。 =)

评分

参与人数 2金币 +2 收起 理由
chentca + 1 相当的喜欢!
qxs8 + 1 辛苦了~~~很有帮助~~谢谢了~

查看全部评分

回复 支持 1 反对 0

使用道具 举报

推荐
 楼主| 发表于 2011-1-7 22:51:50 | 只看该作者
本帖最后由 cn_zou 于 2011-1-8 14:20 编辑

---------------
III.c Push and Pop + The Stack
---------------
  
你已经看了上面的Push和Pop 命令的用法。等等!我是尤里!我能读你的思想!

  You  wrote:
  那个push和pop都是干啥的?还有啥是stack?


好,你读了前文, 在"Push"之后,我是这么注释的。


  Code:
    //Push eax onto the stack (让eax入栈)


这个基本上就是把eax存到堆栈里。而pop eax 基本上就是把eax从堆栈中清除。CEF的Skyone写了一个非常非常好的关于堆栈的解释,我甚至无法容忍自己不让你像我那样获得对此学习的快乐;)

  Skyone  wrote:  
堆栈是用来存放可变的空白的值。它就如同: 你有用来做作业的一张纸, 但是之后你的朋友打电话叫你给Phil打电话,他的电话是 555-6405。 你慌了,没地方记啊,所以你把它写在了作业本上了。  之后你撂下电话, 就可以把Phil's电话写在电话薄上了。 在写完号码之后, 你就把号码从作业本用橡皮擦掉了, 然后打电话给Phil,并且继续做作业。
把值push to stack  (入栈)就是 "在作业本上写下Phil的电话号码" 而pop就是 "把电话号码录入到电话薄上,  然后再从作业本上擦掉。"



继续...

---------------
III.d Alloc/Label/RegisterSymbol
---------------

我一般喜欢用两种方法来区分Auto Assembler脚本

1) 简单的地址改变

如同下面的简单代码:

  Code:
  
  [enable]

  00ABC123:
  mov eax,ebx
  [disable]
  00ABC123:
  mov ebx,eax

  
这是在改变地址00ABC123里面的操作码。
  
但是也有非常复杂的脚本,就如同dICE 或 pID00的脚本。 (我不会在这里介绍, 因为那真的没什么必要去学)
  
在非常复杂的脚本当中,你会在最顶上看到某些函数,(注意,我并没有经常使用)在一个复杂的脚本当中通常会出现"alloc","label"函数,有时还会出现"registersymbol"。

````````````
Label
````````````
我认为"label"函数是三个函数中最有重要的。 他能够允许你用在脚本中使用"label"定义的变量,如同下面这样。 (摸丸:label用于定义用于跳转的标签)


  Code:  
  
  label(Continue)
  
  AutoAssembler:
  mov eax,02
  cmp eax,03
  jne Continue
  je SayWhat
  
  Continue:
  //...
  //...
  
  SayWhat:
  jmp 0 //insta-crash! =D
  


首先应该注意此脚本的一些问题,这个脚本没有 "alloc" 函数, 之后我就讲

接着,如果你明白为什么程序执行了对应jne的label,那你做得不错。

注意所有的labels(跳转标签)都在我的脚本中定义了,否则他们不会编译。

````````````
Alloc
````````````

现在开始讲解"alloc"函数。 它是用来按照你的设想来分配X量的内存的函数 (hence,alloc,allocate)。 这些内存不是那些用过的, 而是那些你在运行程序中可以覆盖的没有被使用的内存。 就如同我说的,它会分配X量的内存。 X是个字节数的变量。1024bytes, 或者1 kb(kilobyte) 一般就足够你用了。现在我们了解了alloc函数,让我来演示下如何来使用它,并利用之前所学到的一切。(摸丸:按照尺寸划分一块内存,并给它起个名字)


  Code:

  alloc(AutoAssembler,1024)
  alloc(SayWhat,1024)
  label(Continue)
  
  AutoAssembler:
  mov eax,02
  cmp eax,03
  jne Continue
  je SayWhat
  
  Continue:
  //...
  
  SayWhat:
  jmp 0
  


注意为什么我不这么做


  Code:  
   label(AutoAssembler)

或者


  Code:
  label(SayWhat)


因为当用alloc划分出内存的时候,他们在Cheat Engine的词典中就自动得已经定义好了,便于我们调用。

````````````
RegisterSymbol
````````````
最后,函数"registersymbol"。 它可以添加你Cheat Table中你注册的标志。注意,你始终需要去为它分配内存。让我们在我们的脚本中试一试。


  Code:
  alloc(AutoAssembler,1024)
  alloc(SayWhat,1024)
  alloc(WooHoo,1024)
  label(Continue)
  registersymbol(WooHoo)
  
  AutoAssembler:
  mov eax,02
  cmp eax,03
  jne Continue
  je SayWhat
  
  Continue:
  cmp eax,[WooHoo]
  
  SayWhat:
  jmp 0
  


````````````
Counterparts
````````````

现在,让我们来继续最后的一小段: the counterparts。
  
有两种使用AutoAssembler script的方法。第一种,你可以注入一些东西。第二种,你可以把它添加到Cheat Table中。如果你决定要把它填到cheat table (当今大多数脚本都是如此), 那你的代码需要enable和disable两部分代码,如下。


  Code:

  [ENABLE]
  alloc(AutoAssembler,1024)
  alloc(SayWhat,1024)
  alloc(WooHoo,1024)
  label(Continue)
  registersymbol(WooHoo)
  
  AutoAssembler:
  mov eax,02
  cmp eax,03
  jne Continue
  je SayWhat
  
  Continue:
  cmp eax,[WooHoo]
  [DISABLE]
  

  
现在,你会注意到,Disable部分什么也没有,不过一会就不会了!;)
  
你在Disable部分中所想达到的就是:撤销你在Enable部分中所做的。
如何撤销内存分配和注册中的标记。现在,我感觉有个问题要来了

You  wrote:
  你是怎么办的?


简单来说,我的朋友。通过dealloc和 unregister symbol 函数! 哦,等等又有问题要来了。

"那label怎么办?" 你问?

嗯,没必要去撤销label。 =) 这意味着在Disable部分中,你大概要从开始那段中扔掉一半的代码! =)
  
那我们为什么不把学的加进脚本里呢?


  Code:  
  
  [ENABLE]
  alloc(AutoAssembler,1024)
  alloc(SayWhat,1024)
  alloc(WooHoo,1024)
  label(Continue)
  registersymbol(WooHoo)
  
  AutoAssembler:
  mov eax,02
  cmp eax,03
  jne Continue
  je SayWhat
  
  Continue:
  cmp eax,[WooHoo]
  [DISABLE]
  dealloc(AutoAssembler)
  dealloc(SayWhat)
  dealloc(WooHoo)
  unregistersymbol(WooHoo)
  

哦这儿...还有个问题。


  You  wrote:
  为什么你不用那个"1024"了?

因为计算机知道你分配的AutoAssembler是大小为1024 bytes 的 (我们就把它当个例子试一试吧),你只是需要deallocAutoAssembler,它就知道应该取消分配AutoAssembler的全部1024 bytes了。(很抱歉,解释的有些迷糊)

点评

学识太低.无法读懂.  发表于 2013-8-7 06:51
值得学习  发表于 2012-3-8 12:05
厉害  发表于 2012-3-3 15:08

评分

参与人数 2金币 +2 收起 理由
shenhao6019 + 1 感谢您的分享!
ty1106576 + 1 感谢您的分享!

查看全部评分

回复 支持 1 反对 0

使用道具 举报

3784
发表于 2018-1-16 17:06:51 | 只看该作者
终于知道这些脚本的含义了,受教了终于知道这些脚本的含义了,受教了
回复 支持 反对

使用道具 举报

3783
发表于 2017-12-19 19:10:48 | 只看该作者
好教程,楼主有多辛苦了
回复 支持 反对

使用道具 举报

3782
发表于 2017-11-28 18:51:00 | 只看该作者
谢谢,可以解惑好多汇编指令
回复 支持 反对

使用道具 举报

3781
发表于 2017-10-21 10:29:46 | 只看该作者
6666666
回复

使用道具 举报

3780
发表于 2017-8-12 18:43:11 | 只看该作者
新人感觉好晕啊
回复 支持 反对

使用道具 举报

3779
发表于 2017-8-12 18:42:03 | 只看该作者
理论知识好多
回复 支持 反对

使用道具 举报

3778
发表于 2017-7-28 23:54:12 | 只看该作者
这篇教程是给不懂汇编的人看的
回复 支持 反对

使用道具 举报

3777
发表于 2017-7-10 22:19:39 | 只看该作者
看来要学的东西还很多,多谢分享
回复 支持 反对

使用道具 举报

3776
发表于 2017-7-6 18:09:09 | 只看该作者
我·德天
回复

使用道具 举报

3775
发表于 2017-4-11 11:23:06 | 只看该作者
学到不少东西
回复 支持 反对

使用道具 举报

3774
发表于 2017-4-11 10:32:51 | 只看该作者
我要好好学习
回复 支持 反对

使用道具 举报

3773
发表于 2017-3-13 19:59:13 | 只看该作者
支持啊啊啊啊啊啊啊啊
回复 支持 反对

使用道具 举报

3772
发表于 2016-11-17 19:54:30 | 只看该作者
不错的文章的。。
回复 支持 反对

使用道具 举报

3771
发表于 2016-11-16 13:56:49 | 只看该作者
谢谢分享 点赞
回复 支持 反对

使用道具 举报

3770
发表于 2016-10-4 12:41:34 | 只看该作者
汇编good
我的交给老湿了
回复 支持 反对

使用道具 举报

3769
发表于 2016-8-14 14:20:17 | 只看该作者
好东西,mark一下,慢慢来学习
回复 支持 反对

使用道具 举报

3768
发表于 2016-4-9 08:57:34 | 只看该作者
解决两个分开 科技股份可两排楼房方刚方刚改款卡罗为国vg
回复 支持 反对

使用道具 举报

3767
发表于 2016-2-14 20:44:17 | 只看该作者
走过看过没学会
回复 支持 反对

使用道具 举报

3766
发表于 2016-1-21 21:18:57 | 只看该作者
翻译辛苦了,感谢提供官方教程
回复 支持 反对

使用道具 举报

3765
发表于 2016-1-20 16:09:14 | 只看该作者
由衷的感谢楼主
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入论坛

本版积分规则

QQ|Archiver|手机版|小黑屋|我爱秘籍论坛  

GMT+8, 2019-3-27 11:21 , Processed in 0.153419 second(s), 38 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表