说明:
1. 这篇教程原文分为8帖,后继的会在不久的将来面世.
2. 原帖并没有标题,标题是翻译的时候加上去的.
3. 由于原作者是俄罗斯人,英语不是太好(有语法错误),有些语句我是根据自己的理解翻译过来的.
4. 不知道有前辈翻译过这个没有?至少我在google上没有找到.
5. 希望这个对你有用.
一 概览
这本书为那些像本人一样渴求知识而不得的人而写.
这套教程的风格是通过练习得出结论,而不是依据结论来做练习 .换句话说,这篇教程包含很多的例子和练习.深入学习本教程理论最好的方法是做所有的练习,以及试验所有的例子.
这本教程并不讲汇编语言编程,我们讲的是"OpCode".
What "OpCode" is?
这是课程要解决的主要问题,现在我给一个简短的回答.
当我们在源代码中写入"lod**",在编译阶段汇编器(如 ml.exe)遇到"lod**",它会在可执行文件(或.obj文件)中用一个字节ACh来替代它.
ACh就是所谓的OpCode,"lod**"则是助记符(mnemonic).
助记符"lod**"对汇编器ml.exe说,"给我用字节ACh替换lod**".处理器并不知道lod**是什么.当寄存器EIP指向ACh字节时,处理器解码器对字节ACh解码,通过这个字节处理器就知道程序要将寄存器ESI指向的一个字节的内容送入AL寄存器.
OpCode就是如此简单.
你可能会说:一个助记符是某个特定的操作码的别称.
但是,事实并没有如此简单.对于"lod**"这个特定的助记符来说,它确实对应ACh,并且操作码ACh也唯一确定助记符"lod**".然而并非所有的情形都是这样.我们很快会见到"为什么不"的例子.
就像现实生活中一个名称往往并不唯一对应一个事物一样,OpCode和助记符的关系如下:不同的OpCode可能有同样的助记符;一个OpCode可能有几个助记符对应.有些事情可能很简单但却会吓倒初学者,在不久的将来我将会做详细的解释.
查看OpCode或mnemonics的方法有很多种,我认为最快且最好的方法是使用调试器.我将在OllyDbg中试验所有的例子.
Exersize1. 在调试器中输入助记符和OpCode
1. 用OD打开任意一个Win32可执行文件,加载完成后在代码窗口中双击某一行,在弹出的指令输入对话框中输入lod**回车,你将看到(类似下面的内容):
0040108C> AC LODS [BYTE DS:ESI]
第一列(0040108c)是指令在内存中的地址,第二列(AC)是OpCode,第三列(LODS [BYTE DS:ESI])是OpCode AC的助记符.
2. 你可以试着输入一些你其他的助记符,并观察他们的OpCode.
3. 按CTRL + e,你将看到一个对话框,在HEX + 00 对应的文本框中输入 AC回车,可以看到第二列和第三列如下:
AC LODS [BYTE DS:ESI]
4. 试着输入一些其他的OpCode,并观察对应的助记符.
Exersize2. 一个助记符对应一个OpCode吗?
1. 按CTRL+ e,输入OpCode 90,回车,可以看到OD将90认为是 NOP:
0040108E 90 NOP
2. 输入助记符 "NOP",同样看到:
0040108E 90 NOP
3. 输入助记符 XCHG EAX, EAX
糟糕! OllyDbg并没有插入我们的指令,而是用NOP代替!!!
不用着急,这是OllyDbg的问题,当看到OpCode 90的时候它总是显示NOP,而不是 xchg eax,eax.对我们来说这两个助记符"xchg eax,eax"和"nop"都显示90h.
由此可见,一个事物(OpCode)不只对应一个名字(助记符).
我再重复一次:在计算机世界里有的只是OpCode,助记符只是这些OpCode的名字,这些助记符组成的系统就是汇编语言,助记符并不完美,因为没有完美的语言--任何语言的描述和现实总是有或多或少的区别的.
在我们得出某些结论之前,我们先来做第二部分的练习.
Exersize3.
1. 输入助记符 add eax,1 ,你将看到
0040108E 83C0 01 add eax,1
2. 输入OpCode 05 01000000 ,我们将惊奇的发现
0040108E 05 01000000 add eax,1
同样的助记符但是不一样的OpCode!
事实上它们不仅大小不同,结构也不一样.第一个(83C0 01)3字节长,包含3个域;第二个(05 01000000)5字节长,但只有两个域.
在我们学习这些域之前,我们先来想一想:当你看着这两个OpCOde:
83C0 01
05 01000000
你是否想到:
第一个OpCode中 01和第二个OpCode中 01000000 是加到 EAX 的立即数?
既然助记符向OpCode可以有多种转换的方式,那么到底什么OpCode将会被插入exe文件中?这是由什么决定的呢?
答案是:这是由汇编器决定的.
当我们在数据段中写入一些值时,我们往往会使用:somevar db 0AH,0DH;而在代码段中我们不需要输入名字而只需定义值:db ACH.所以你可以用16进制写代码段,比如用
Mov esi,offset somedata Mov esi,offset comedata
Lod** 代替 db ACH
好了,又到了我断开网络的时候了,我必须把我所写发送出去,否则我什么也不能提交.下次我们将从OpCode的结构开始,只是一个介绍而已,还涉及OpCOde的一些重要而一般的特性.你将发现这是多么的易学和实用.
原文链接
- 标 题:【翻译】The Svin 的OpCode教程
- 作 者:xiep
- 时 间:2008-06-13 18:37:34
- 链 接:http://bbs.pediy.com/showthread.php?t=66501