ImageVerifierCode 换一换
格式:DOCX , 页数:35 ,大小:559.69KB ,
资源ID:7758819      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7758819.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Emu8086教程.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Emu8086教程.docx

1、Emu8086教程%-最详细的emu教程-%Emu8086集源代码编辑器,汇编反汇编工具以及可以运行debug的模拟器(虚拟机器)于一身,它优于一般编译器的地方在于提供了一个虚拟的80x86环境,拥有自己一套独立的“硬件”,可以完成一些纯软件编译器无法完成的功能例如Led显示,交通灯,步进电机等等,而且动态调试(DEBUG)时非常方便。简单的例子:安装完成后选择 菜单栏中的文件 examples stepper motor 在编辑框出现了相应的源码。点击compile编译选择一个文件保存保存完之后会弹出一个对话框点击run按钮则程序开始运行调试时主控界面如下:再次点击run可以停止运行单击re

2、load可以从头开始执行程序单击single step 可以单步调试。单击step back可以返回到上一条指令(这个功能也是一般调试器没有的)。界面左边是寄存器栏,这里可以动态的观察每一步的执行结果点击主控界面下面的screen可以显示模拟输出窗口单击source可以查看源码窗口Reset相当于上面的reload键。单击aux会出现一个菜单选择第一项memory可以观察程序内存区数值的变化。选择stop on condition 可以设置条件断点:上面的设定当ax的值是0x0006是断下来单击run按钮可以看到断下来的时候ax值正好等于6单击vars可以查看运行过程中变量的变化。Debug可

3、以更详细的显示每一步的调试结果通过Stack(堆栈)可以观察函数调用的过程Flags显示标志寄存器的值。如果刚刚执行的那一条指令修改了哪个标志位的值则以红色显示。可以到这个网址去下载:目前网上很多人找这个软件的破解版。其实根本不用破解。只要在用户名一栏输入任意的字符注册码的前三位输入“112”就可以绕过注册认证了。至于为什么我就不多说了有兴趣的可以看一下我在看雪论坛发表的一篇文章:下面是在XX文库下载的一篇基础教程希望能对大家有所帮助。如何运行?在开始菜单选在它的图标,或者直接运行Emu8086EXE在FILE菜单中选择SAMPLE点击Compile and Emulate按纽(或者按快捷键F

4、)点击Single Step按纽(或者按快捷键F),可以查看代码如何运行十进制系统目前使用最多的是十进制十进制系统有个数字, 利用这些数字能表示任何数值,例如这些数字是由每一位数字乘以“基数”的幂累加而成的(上一个例子中基数是10 因为十进制中有十个数字)。位置对于每一个数字是很重要的。例如,你将上一个例子中的“7”放到结尾:547数值就成为:特别提醒:任何数字的0次幂都是1,0的0次幂也是1二进制计算机没有人类聪明(至少现在是这样),制造一个只有开关或者称为 0,1 两种状态的电子机器很容易。计算机使用二进制系统,只有两个数字 0, 1基地为2每一位二进制数称作一位(BIT),4 BIT 组

5、成一个半字节(NIBBLE),8BIT组成一个字节(BYTE),两个字节组成一个字(WORD),两个字组成一个双字(DOUBLE WORD)(很少使用):习惯上在一串二进制后面加上“b”,这样,我们可以知道101b是二进制表示十进制的5。二进制10100101b表示十进制的165,计算方法如下:十六进制系统十六进制系统使用16个数字0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F基底是 16. 十六进制非常紧凑,便于阅读。将二进制转换为十六进制很容易,半字节(4bits) 对应一位十六进制如下表Decimal(base 10)Binary(base

6、2)Hexadecimal(base 16)000000100011200102300113401004501015601106701117810008910019101010A111011B121100C131101D141110E151111F习惯上我们在一个十六进制数的后面加上 H,以便和其他进制区别, 这样我们就知道 5Fh是一个十六进制数表示十进制的 95。习惯上,我们也在以字母开头(从到)的十六进制数前面 加上0例如: 0E120h. 十六进制 1234h 等于4660:十进制到另外进制的换算 在换算中,将十进制数不断除以目标进制的基底,每一次都要记录下商和余数,直到商。 余数用来

7、表示结果。下面是一个十进制(基底是)到十六进制(基底是)的换算:结果为27H上例中所有的余数都小于,不必使用字母。再举一个更复杂的例子:十进制 43868 换算为十六进制:结果是 0AB5Ch, 使用 上面提到的表 将大于的数字替换成字母。 运用同样的原理,我们可以换算为二进制(用作除数),或者是先换算成十六进制,再用上面的表换算成二进制:于是,得到二进制: 1010101101011100b 有符号数 对于十六进制数0FFh无法确定它是正数还是负数,因为它可以表示十进制的255 或者 - 1。位可以表示个状态,于是,我们可以假定前个表示正数(从0到127),接下来的个数(从128到256)表

8、示负数 。如果想表示- 5,我们从中减去,即 256 - 5 = 251。用这种复杂的方法表示一个负数有着数学依据的,数学上- 5 加上 5等于。当我们将两个位的数字5 和251相加时,结果超过,溢出处理为!128到256高位始终是,这个可以作为数字符号的标记 对于字(位),位有65536个状态,头个状态(从0到32767)用来表示正数,下面的个状态(从32767到65535) 表示负数Emu8086带有数制转换工具,也可以计算各种数值表达式。选择菜单 Math 项: Number Convertor (数制转换)可以实现任意数制之间的转换。在文本框中填写源 数值,将自动转换到任意的数制。 可

9、以作 8 位 或者 16 位转换。Expression Evaluator(表达式计算)可以用来计算不同数制的计算以及从一个进制到另一个进制的转换。输入表达式,按下回车,结果就会以你选定的进制表示。最长可以进行位的计算。当在Signed打钩选中时(除了八进制和双字),最前面的一位将被认作是符号位。这样以来,0FFFFFFFFh将被认为是十进制的。例如,你计算0FFFFh * 10h + 0FFFFh ( 8086 CPU所能访问的最大内存地址)。如果你选中Signed 和 Word选项,结果是-17(因为表达式被认为是(-1) * 16 + (-1) )。如果想按照无符号数计算,请不要选择Si

10、gned表达式为65535 * 16 + 65535计算结果将是1114095 同样你可以使用Number Convertor将非十进制换算为有符号的十进制,然后根据十进制计算。支持如下运算: not (inverts all bits).* multiply./ divide.% modulus.+ sum.- subtract (and unary -). shift right.& bitwise AND. bitwise XOR.| bitwise OR.二进制必须有“”作结尾,例如00011011b 十六进制必须有h作结尾,另外,当地一位是字母时,最前面必须加上,例如:0ABCDh八

11、进制必须有o作结尾,例如:77o什么是汇编语言? 汇编语言是底层编程语言。为了学习这门语言,你需要对于计算机结构有所了解。计算机系统模型如下:系统总线 system bus(图中黄色部分)是将计算机各个部分连接到一起的部件。CPU是计算机的心脏,大部分的运算都是在CPU中完成的。RAM是读取并且存放将要执行的程序的地方。CPU内部 通用寄存器8086CPU有8个通用寄存器,每一个寄存器都有自己的名称: AX 累加寄存器 accumulator register(分为 AH / AL). BX 基址寄存器 base address register (分为 BH / BL). CX 计数寄存器

12、count register(分为 CH / CL ). DX 数据寄存器 data register (分为 DH / DL). SI 源变址寄存器 source index register. DI 目的变址寄存器 destination index register. BP 基址指针寄存器 base pointer. SP 堆栈寄存器 stack pointer. 编程中,由程序员决定通用寄存器的具体用途。寄存器的主要目 的是保存数值(变量)。上面提到的寄存器是16位的,意思是:0011000000111001b (二进制),或者12345(十进制形式)。4个通用寄存器(AX, BX,

13、CX, DX) 在使用时分为两个8位寄存器,例如 假设AX= 0011000000111001b,AH=00110000b AL=00111001b。当你修改其中任意8位值,整个16位寄存器的值同样改变。同样对于其他的3个寄存器,“H”表示高8位,“L”表示低8位。寄存器在CPU内部,访问中它们速度远远超过内存。因为,访问内存需要经过系统总线,所以时间要长一些。而访问寄存器中的数据几乎不需要时间。于是,编程中,应当尽量在寄存器中保存数据。虽然寄存器很小,并且这些寄存器都有具体用途,但他们依然是存放计算中临时数据的好地方。段寄存器 CS 代码段寄存器,用来存放当前正在运行的指令 DS 数据段寄存

14、器,用来存放当前运行程序所用的数据 ES 附加段寄存器,由程序员决定用途 SS 堆栈段寄存器,指出堆栈所在区域 尽管容许在段寄存器中存放任何数据,但是这决不是 一个好主意。段寄存器有着非常特别的目的指出可以访问内存块的地址。段寄存器与通用寄存器协同工作就可以访问任意的内存区域。例如,如果我们打算访问物理地址是12345h(十六进制)的内存单元,我们应设置DS = 1230h SI = 0045h 这样以来,我们便能访问超过一个寄存器(16位)所能表示的内存地址的范围。CPU计算物理地址的方法是将段寄存器乘以10H在加上一个特定的通用寄存器。(1230h * 10h + 45h = 12345h

15、):这种,由两个寄存器生成的地址被称为有效地址 (effective address)默认下,BX, SI 及 DI 与 DS协同工作,BP SP 与 SS 寄存器协同工作。其余的通用寄存器不能形成有效地址!同样,尽管BX可以形成有效地址,但是BH BL不能!控制寄存IP 指令指针寄存器 instruction pointer 、Flags Register 状态标志寄存器 IP 始终同CS 协同工作,指出当前执行的指令。 Flags Register 完成一次数学运算后,由CPU自动修改,通过它可以得到当前结果类型,也可以作为跳转语句条件。通常你无法直接访问它们。寻址方式 我们可以通过下面的

16、四个寄存器来寻址 BX, SI, DI, BP.通过计算符号中的值,我们可以访问到不同内存单元的值。具体组合请看下表:BX + SIBX + DIBP + SIBP + DISIDId16 (variable offset only)BXBX + SI + d8BX + DI + d8BP + SI + d8BP + DI + d8SI + d8DI + d8BP + d8BX + d8BX + SI + d16BX + DI + d16BP + SI + d16BP + DI + d16SI + d16DI + d16BP + d16BX + d16d8 - 表示位偏移量 d16 - 表示位

17、偏移量偏移量可以是一个立即数或者是一个变量的偏移,或者二者兼备。这取决于编译器如何计算单独的立即数。偏移量可以在符号里面或者外面,这不影响编译器生成相同的机器码。偏移量是一个有符号数,可以是正数或者负数。一般说来,8位或者16位,对于编译后的结果是有影响的。例如,假定 DS = 100, BX = 30, SI = 70。如下寻址方式 BX + SI + 25 计算物理地址为100 * 16 + 30 + 70 + 25 = 1725默认下,DS 寄存器应用在除了BP寄存器之外的所有物理地址计算中,寄存器是和SS寄存器一起工作的。用过下面的表,你可以和轻松记住谁和谁是关联在一起使用的。上表中,

18、你可以从每一列中选择一个或者忽略任意一个列。比如,可以看到,BX 和 BP始终不会选到一起。SI 和 DI不会选到一起。这是一个计算地址模式BX+5 段寄存器(CS, DS, SS, ES) 中数值被称作 段偏移 。目的寄存器(BX, SI, DI, BP) 中数值被称作偏移量 比如,ds中数值为1234h,si中数值为7890h,可以记作 1234:7890物理地址为 1234h * 10h + 7890h = 19BD0h在编译过程中使用如下声明数据类型 BYTE PTR - 表示字节 ; WORD PTR - 表示字(2个字节)例如:BYTE PTR BX ;按字节访问 ; WORD P

19、TR BX ;按字访问Emu8086 容许使用如下更简洁的前缀b. - 等价于上面的 BYTE PTR ; w. - 等价于上面的 WORD PTR有时,编译器可以自动计算出数据类型,但是如果一个参与运算的数是立即数,这种方法就不可靠了。MOV 指令 将第二个操作数(源)拷贝到第一个操作数(目的)指定位值 ,源操作数可以是立即数,通用寄存器或者内存单元,目的寄存器可以是通用寄存器或者内存单元 ,源和目的必须是同样大小,要么都是字节要么都是字 操作类型如下:MOV REG, memoryMOV memory, REGMOV REG, REGMOV memory, immediateMOV REG

20、, immediate REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.memory: BX, BX+SI+7,变量, 等等immediate: 5, -24, 3Fh, 10001101b, 等等.mov指令只支持如下段寄存器:MOV SREG, memoryMOV memory, SREGMOV REG, SREGMOV SREG, REGSREG: DS, ES, SS, 注意 CS 只能作操作源REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL,

21、DI, SI, BP, SP.memory: BX, BX+SI+7, variable, 等等MOV指令不能用来设置CS和IP寄存器的值。 下面是一个使用 MOV 指令的例子:#MAKE_COM# ; 表示,这个是一个com程序ORG 100h ;COM 程序必须的MOV AX, 0B800h ; 将ax设置为 B800h.MOV DS, AX ; 将 AX 值拷贝到 DS.MOV CL, A ; 将ASCII 码 A的值传送到cl,这个值是 41h.MOV CH, 01011111b ; 将ch设置为二进制的01011111bMOV BX, 15Eh ; 将 BX 设置成 15Eh.MOV

22、 BX, CX ; 将 CX 放到 bx 指出的内存单元 B800:015ERET ; 返回操作系统你可以将上面的程序贴入Emu8086代码编辑器,接下来按下complie and emulate(或者按F5) 模拟窗口将显示这个程序已经调入,点击single step观察寄存器数值变化,你可以猜到;表示注释,编译器忽略在;后面的一切,程序结束后,你可以看到如下窗口事实上,上面程序是将字符直接写入显示内存。通过上面的例子,你可以发现 MOV指令是非常有用的。变量变量是一个内存地址。对于编程者来说,使用诸如名称为“var1”这样的 变量保存数据远远比使用5a73:235b这样的地址容易的多。特别

23、是当你使用10个以上的变量的时侯。编译器支持这两种变量 BYTE 和 WORD.(字节和字)声明变量的方法:name DB value 名称 DB 值name DW value 名称 DW 值DB - stays for Define Byte.DW - stays for Define Word.name 可以是任何字母与数字构成,但是必须由字母开头。可以通过不命名来声明一个 没有名称的的变量(这个变量只有地址,没有名称)value - 可以是任何数值支持三种进制(十六进制,二进制和十进制),你可以使用?符号表示初始值没有确定。 你可能从第二章了解到, MOV 指令是将数值从源拷贝到目的。

24、让我们再看一个 MOV 指令的例子#MAKE_COM#ORG 100hMOV AL, var1MOV BX, var2RET ; stops the program.VAR1 DB 7var2 DW 1234h将上面的代码拷贝到emu8086源程序编辑器中,按下F5键编译 并在模拟器中执行。你会看到如下画面从画面可以看出,反编译后的代码同源程序很相似,不同的是变量被具体的内存地址取代。当编译器生成机器代码它会自动将变量名称用该变量的便宜量代替。默认情况下,DS 寄存器存放段偏移(当执行com文件的时侯,DS 寄存器的值同 CS 寄存器(代码段)的值一样)。内存第一列是偏移(offset),第二

25、列是一个十六进制值(hexadecimal value),第三列是十进制(decimal value),最后一列是 ASCII 字符。编译器是非大小写敏感的,所以 “VAR1” 同 “var1” 都是同一个变量。VAR1变量的偏移是0108h,物理地址是0b56:0108var2 变量的偏移是0109h,物理地址是 0b56:0109这个变量是字,它占用2字节。这里假定低字节存放在低地址,所以34h位于12h前面。你可以看到,在RET指令后面还有一些指令,这样是因为反编译工具无法判断数据从什么地方开始。同样,你可以写出直接使用DB的程序.#MAKE_COM#ORG 100hDB 0A0hDB

26、08hDB 01hDB 8BhDB 1EhDB 09hDB 01hDB 0C3hDB 7DB 34hDB 12h将上面的代码拷贝到emu8086原代码编辑器,按下F5键编译,并在模拟器中运行,你可以看到同样的反汇编结果,得到同样的功能。根据上面,你可以猜测,编译器将源程序转化为一些字节的集合,这个集合被称作机器代码(machine code),处理器懂得他们,并且执行它们。ORG 100是一个编译指令(它告诉编译器如何处理源代码)当你使用变量的时侯,这条指令特别重要。它通知编译器可执行程序将被调入偏移量是100h(256字节)的位置,有了它,编译器就可以计算出所有变量的正确地址,然后用这些地址

27、(偏移量)来代替变量名称。上面的这些指令不会真正的编译为任何机器代码。为何可执行程序总是被装入偏移量100h?操作系统在CS寄存器(代码段)存储着程序信息,比如命令行方式下的参数等等。尽管上面只是一个COM文件的例子,EXE文件调入在偏移量0000的位置,他使用特定的段保存变量。我们在下面会学习到关于EXE文件的知识。数组数组可以看作是变量链。一个字符串是一个字节数组的例子,其中每一个字符都当作一个ASCII码的值(0.255)下面是一些定义数组的例子 a DB 48h, 65h, 6Ch, 6Ch, 6Fh, 00hb DB Hello, 0 b是一个数组,当编译器发现引用了字符串值后,会自

28、动将这些字符转化为对应的字节。下面图表表示的就是声明数组后在内存中的分布:你可以使用方括号做下标直接访问到数组中的值,例如:MOV AL, a3 同样,你还可以使用任意一个内存索引寄存器BX, SI, DI, BP,例如:MOV SI, 3MOV AL, aSI如果你想声明比较复杂的数组,你可以使用DUP指令 形式如下number DUP ( value(s) ) number - 重复的数量(任意常数)value - 将要复制的表达式例如:c DB 5 DUP(9) 就相当于如下定义:c DB 9, 9, 9, 9, 9 另外一个例子:d DB 5 DUP(1, 2) 等同于d DB 1,

29、2, 1, 2, 1, 2, 1, 2, 1, 2 当然,如果需要存放超过255或者小于128的数值,你还可以使用DW来代替 DB。但是DW不能用于声明字符串。DUP命令展开后不能超过1020个字符(上一个例子中展开之后是13个字符),如果需要声明请将它们分成两行(这样,内存中得到的仍然是一个大数组)。取得变量地址 LEA指令(Load Effective Address 读取有效地址)或者OFFSET指令。OFFSET 和 LEA二者都能够获得变量的偏移量。LEA在使用中更有效,这是因为它能返回索引变量的地址。取得变量地址在很多情况下是非常有用的,例如你打算向一个过程传递参数。注意:在编译过程中使用如下声明数据类型 BYTE PTR - 表示字节 ;WORD PTR - 表示字(2个字节)例如:BYTE PTR BX ;按字节访问 ; WORD PTR BX ;按字访问Emu8086 容许使用如下更简洁的前缀b. - 等价于上面的 BYTE PTR ;w. - 等价于上面的 WORD PT

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1