Emu8086利用指南中文.docx
- 文档编号:3128931
- 上传时间:2023-05-05
- 格式:DOCX
- 页数:34
- 大小:365.52KB
Emu8086利用指南中文.docx
《Emu8086利用指南中文.docx》由会员分享,可在线阅读,更多相关《Emu8086利用指南中文.docx(34页珍藏版)》请在冰点文库上搜索。
Emu8086利用指南中文
如何运行?
1.在开始菜单项选择在它的图标,或直接运行Emu8086.EXE2.在"FILE"菜单当选择"SAMPLE"3.点击"CompileandEmulate"按纽(或者按快捷键F5)4.点击"SingleStep"按纽(或者按快捷键F8),可以查看代码如何运行.
十进制系统目前利用最多的是十进制.十进制系统有10个数字0,1,2,3,4,5,6,7,8,9利用这些数字能表示任何数值,例如754这些数字是由每一名数字乘以“基数”的幂累加而成的(上一个例子中基数是10因为十进制中有十个数字)。
位置关于每一个数字是很重要的。
例如,你将上一个例子中的“7”放到结尾:
547数值就成为:
专门提示:
任何数字的0次幂都是1,0的0次幂也是1
二进制运算机没有人类伶俐(至少此刻是如此),制造一个只有开关或称为0,1两种状态的电子机械很容易。
运算机利用二进制系统,只有两个数字0,1基地为2每一名二进制数称作一名(BIT),4BIT组成一个半字节(NIBBLE),8BIT组成一个字节(BYTE),两个字节组成一个字(WORD),两个字组成一个双字(DOUBLEWORD)(很少利用):
适应上在一串二进制后面加上“b”,如此,咱们能够明白101b是二进制表示十进制的5。
二进制b表示十进制的165,计算方式如下:
十六进制系统十六进制系统利用16个数字0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F基底是16.十六进制超级紧凑,便于阅读。
将二进制转换为十六进制很容易,半字节(4bits)对应一名十六进制如下表
Decimal(base10)
Binary(base2)
Hexadecimal(base16)
0
0000
0
1
0001
1
2
0010
2
3
0011
3
4
0100
4
5
0101
5
6
0110
6
7
0111
7
8
1000
8
9
1001
9
10
1010
A
11
1011
B
12
1100
C
13
1101
D
14
1110
E
15
1111
F
适应上咱们在一个十六进制数的后面加上"H",以便和其他进制区别,如此咱们就明白5Fh是一个十六进制数表示十进制的 95。
适应上,咱们也在以字母开头(从A到F)的十六进制数前面加上"0" 例如:
0E120h.十六进制1234h 等于 4660:
十进制到另外进制的换算在换算中,将十进制数不断除以目标进制的基底,每一次都要记录下商和余数,直到商0。
余数用来表示结果。
下面是一个十进制39(基底是10)到十六进制(基底是16)的换算:
结果为 27H上例中所有的余数都小于10,没必要利用字母。
再举一个更复杂的例子:
十进制43868换算为十六进制:
结果是0AB5Ch,利用将大于9的数字替换成字母。
运用一样的原理,咱们能够换算为二进制(用2作除数),或是先换算成十六进制,再用 换算成二进制:
于是,取得二进制:
100b
有符号数对于十六进制数 0FFh 无法确信它是正数仍是负数,因为它能够表示十进制的"255"或 "-1"。
8位可以表示256个状态,于是,咱们能够假定前128个表示正数(从0到127),接下来的128个数(从128到256)表示负数。
若是想表示"-5",咱们从256中减去5,即 256-5=251。
用这种复杂的方式表示一个负数有着数学依据的,数学上"-5"加上"5"等于0。
当咱们将两个8位的数字 5和 251相加时,结果超过255,溢出处置为0!
128到256高位始终是1,那个能够作为数字符号的标记关于字(16位),16位有65536个状态,头32768个状态(从0到32767)用来表示正数,下面的32768个状态(从32767到65535)表示负数
Emu8086 带有数制转换工具,也能够计算各类数值表达式。
选择菜单Math项:
NumberConvertor(数制转换)能够实现任意数制之间的转换。
在文本框中填写源
数值,将自动转换到任意的数制。
能够作8位或16位转换。
ExpressionEvaluator(表达式计算)能够用来计算不同数制的计算和从一个进制到另一个进制的转换。
输入表达式,按下回车,结果就会以你选定的进制表示。
最长能够进行32位的计算。
当在Signed打钩选中时(除八进制和双字),最前面的一名将被认作是符号位。
如此以来,0FFFFFFFFh 将被以为是十进制的 -1。
例如,你计算 0FFFFh*10h+0FFFFh(8086CPU所能访问的最大内存地址)。
若是你选中Signed和Word 选项,结果是 -17 (因为表达式被以为是 (-1)*16+(-1))。
若是想依照无符号数计算,请不要选择 Signed 表达式为 65535*16+65535 计算结果将是1114095一样你能够利用NumberConvertor将非十进制换算为有符号的十进制,然后依照十进制计算。
支持如下运算:
~not (invertsallbits).
*multiply.
/divide.
%modulus.
+sum.
-subtract(andunary-).
< >>shiftright. &bitwiseAND. ^bitwiseXOR. |bitwiseOR. 二进制必需有“b”作结尾,例如00011011b十六进制必需有"h"作结尾,另外,本地一名是字母时,最前面必需加上0,例如: 0ABCDh八进制必需有"o"作结尾,例如: 77o 什么是汇编语言? 汇编语言是底层编程语言。 为了学习这门语言,你需要关于运算机结构有所了解。 运算机系统模型如下: 系统总线systembus(图中黄色部份)是将运算机各个部份连接到一路的部件。 CPU是运算机的心脏,大部份的运算都是在CPU中完成的。 RAM是读取而且寄存将要执行的程序的地址。 CPU内部 通用寄放器8086CPU有8个通用寄放器,每一个寄放器都有自己的名称: AX累加寄放器accumulatorregister(分为AH/AL). BX基址寄放器baseaddressregister(分为BH/BL). CX计数寄放器countregister(分为CH/CL). DX数据寄放器dataregister(分为DH/DL). SI源变址寄放器sourceindexregister. DI目的变址寄放器destinationindexregister. BP基址指针寄放器basepointer. SP堆栈寄放器stackpointer. 编程中,由程序员决定通用寄放器的具体用途。 寄放器的要紧目的是保留数值(变量)。 上面提到的寄放器是16位的,意思是: 001b(二进制),或12345(十进制形式)。 4个通用寄放器(AX,BX,CX,DX)在利历时分为两个8位寄放器,例如假设AX=001b,AH=00110000bAL=00111001b。 当你修改其中任意8位值,整个16位寄放器的值一样改变。 一样关于其他的3个寄放器,“H”表示高8位,“L”表示低8位。 寄放器在CPU内部,访问中它们速度远远超过内存。 因为,访问内存需要通过系统总线,因现在刻要长一些。 而访问寄放器中的数据几乎不需要时刻。 于是,编程中,应当尽可能在寄放器中保留数据。 尽管寄放器很小,而且这些寄放器都有具体用途,但他们仍然是寄存计算中临时数据的好地址。 段寄放器 CS代码段寄放器,用来寄存当前正在运行的指令 DS数据段寄放器,用来寄存当前运行程序所用的数据 ES附加段寄放器,由程序员决定用途 SS堆栈段寄放器,指出堆栈所在区域 尽管允许在段寄放器中寄存任何数据,可是这决不是一个好主意。 段寄放器有着超级专门的目的--指出能够访问内存块的地址。 段寄放器与通用寄放器协同工作就能够够访问任意的内存区域。 例如,若是咱们打算访问物理地址是12345h(十六进制)的内存单元,咱们应设置DS=1230hSI=0045h如此以来,咱们便能访问超过一个寄放器(16位)所能表示的内存地址的范围。 CPU计算物理地址的方式是将段寄放器乘以10H在加上一个特定的通用寄放器。 (1230h*10h+45h=12345h): 这种,由两个寄放器生成的地址被称为有效地址(effectiveaddress) 默许下,BX,SI及DI与DS协同工作,BPSP与SS寄放器协同工作。 其余的通用寄放器不能形成有效地址! 一样,尽管BX能够形成有效地址,可是BHBL不能! 操纵寄放IP指令指针寄放器instructionpointer、FlagsRegister状态标志寄放器 IP始终同CS协同工作,指出当前执行的指令。 FlagsRegister完成一次数学运算后,由CPU自动修改,通过它能够取得当前结果类型,也能够作为跳转语句条件。 通常你无法直接访问它们。 寻址方式 咱们能够通过下面的四个寄放器来寻址BX,SI,DI,BP. 通过计算[]符号中的值,咱们能够访问到不同内存单元的值。 具体组合请看下表: [BX+SI][BX+DI][BP+SI][BP+DI] [SI][DI]d16(variableoffsetonly)[BX] [BX+SI]+d8[BX+DI]+d8[BP+SI]+d8[BP+DI]+d8 [SI]+d8[DI]+d8[BP]+d8[BX]+d8 [BX+SI]+d16[BX+DI]+d16[BP+SI]+d16[BP+DI]+d16 [SI]+d16[DI]+d16[BP]+d16[BX]+d16 d8-表示8位偏移量d16-表示16位偏移量偏移量可以是一个立即数或者是一个变量的偏移,或者二者兼备。 这取决于编译器如何计算单独的立即数。 偏移量可以在[]符号里面或者外面,这不影响编译器生成相同的机器码。 偏移量是一个有符号数,可以是正数或者负数。 一般说来,8位或者16位,对于编译后的结果是有影响的。 例如,假定DS=100,BX=30,SI=70。 如下寻址方式[BX+SI]+25计算物理地址为100*16+30+70+25=1725默认下,DS寄存器应用在除了BP寄存器之外的所有物理地址计算中,寄存器是和SS寄存器一起工作的。 用过下面的表,你可以和轻松记住谁和谁是关联在一起使用的。 上表中,你能够从每一列当选择一个或忽略任意一个列。 比如,能够看到,BX和BP始终可不能选到一路。 SI和DI可不能选到一路。 这是一个计算地址模式[BX+5]段寄放器(CS,DS,SS,ES)中数值被称作"段偏移"。 目的寄放器(BX,SI,DI,BP)中数值被称作"偏移量" 比如,ds中数值为1234h,si中数值为7890h,能够记作1234: 7890 物理地址为1234h*10h+7890h=19BD0h在编译进程中利用如下声明数据类型 BYTEPTR-表示字节;WORDPTR-表示字(2个字节)例如: BYTEPTR[BX];按字节访问;WORDPTR[BX];按字访问Emu8086允许利用如下更简练的前缀b.-等价于上面的BYTEPTR;w.-等价于上面的WORDPTR有时,编译器可以自动计算出数据类型,但是如果一个参与运算的数是立即数,这种方法就不可靠了。 MOV指令 将第二个操作数(源)拷贝到第一个操作数(目的)指定位值,源操作数能够是当即数,通用寄放器或内存单元,目的寄放器能够是通用寄放器或内存单元,源和目的必需是一样大小,要么都是字节要么都是字 操作类型如下: MOVREG,memoryMOVmemory,REGMOVREG,REGMOVmemory,immediateMOVREG,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,b,等等. mov 指令只支持如下段寄存器: MOVSREG,memoryMOVmemory,SREGMOVREG,SREGMOVSREG,REG SREG: DS,ES,SS,注意CS只能作操作源REG: AX,BX,CX,DX,AH,AL,BL,BH,CH,CL,DH,DL,DI,SI,BP,SP.memory: [BX],[BX+SI+7],variable,等等 MOV指令不能用来设置CS和IP寄放器的值。 下面是一个使用MOV指令的例子: #MAKE_COM# ; 表示,这个是一个com程序ORG100h ;COM程序必须的MOVAX,0B800h ;将ax设置为B800h.MOVDS,AX ;将AX值拷贝到DS.MOVCL,'A' ;将ASCII码'A'的值传送到cl,这个值是41h.MOVCH,01011111b ;将ch设置为二进制的01011111bMOVBX,15Eh ; 将BX设置成15Eh.MOV[BX],CX ;将CX放到bx指出的内存单元B800: 015ERET ;返回操作系统 你能够将上面的程序贴入Emu8086代码编辑器,接下来按下[complieandemulate] (或按F5)模拟窗口将显示那个程序已经调入,点击[singlestep]观看寄放器数值转变,你能够猜到 ";" 表示注释,编译器忽略在";"后面的一切,程序终止后,你能够看到如下窗口 事实上,上面程序是将字符直接写入显示内存。 通过上面的例子,你能够发觉MOV 指令是超级有效的。 变量 变量是一个内存地址。 关于编程者来讲,利用诸如名称为“var1”如此的变量保留数据远远比利用5a73: 235b如此的地址容易的多。 专门是当你利用10个以上的变量的时侯。 编译器支持这两种变量BYTE和WORD.(字节和字) 声明变量的方法: nameDBvalue名称DB值nameDWvalue名称DW值DB-staysforDefineByte.DW-staysforDefineWord.name-可以是任何字母与数字构成,但是必须由字母开头。 可以通过不命名来声明一个没有名称的的变量(这个变量只有地址,没有名称) value-可以是任何数值支持三种进制(十六进制,二进制和十进制),你可以使用"? "符号表示初始值没有确定。 你可能从第二章了解到,MOV指令是将数值从源拷贝到目的。 让咱们再看一个MOV指令的例子 #MAKE_COM# ORG100h MOVAL,var1 MOVBX,var2 RET;stopstheprogram. VAR1DB7 var2DW1234h 将上面的代码拷贝到emu8086源程序编辑器中,按下F5键编译并在模拟器中执行。 你会看到如下画面 从画面能够看出,反编译后的代码同源程序很相似,不同的是变量被具体的内存地址取代。 当编译器生成机械代码它会自动将变量名称用该变量的廉价量代替。 默许情形下,DS寄放器寄存段偏移(当执行com文件的时侯,DS寄放器的值同CS寄放器(代码段)的值一样)。 内存第一列是偏移(offset),第二列是一个十六进制值(hexadecimalvalue),第三列是十进制(decimalvalue),最后一列是ASCII字符。 编译器是非大小写灵敏的,因此“VAR1”同“var1”都是同一个变量。 VAR1变量的偏移是0108h,物理地址是0b56: 0108var2变量的偏移是0109h,物理地址是0b56: 0109 那个变量是字,它占用2字节。 那个地址假定低字节寄存在低地址,因此34h位于12h前面。 你可以看到,在RET指令后面还有一些指令,这样是因为反编译工具无法判断数据从什么地方开始。 同样,你可以写出直接使用DB的程序. #MAKE_COM# ORG100h DB0A0h DB08h DB01h DB8Bh DB1Eh DB09h DB01h DB0C3h DB7 DB34h DB12h 将上面的代码拷贝到emu8086原代码编辑器,按下F5键编译,并在模拟器中运行,你能够看到一样的反汇编结果,取得一样的功能。 依照上面,你能够猜想,编译器将源程序转化为一些字节的集合,那个集合被称作机械代码(machinecode),处置器知道他们,而且执行它们。 ORG100是一个编译指令(它告知编译器如何处置源代码)当你利用变量的时侯,这条指令专门重要。 它通知编译器可执行程序将被调入偏移量是100h(256字节)的位置,有了它,编译器就能够够计算出所有变量的正确地址,然后用这些地址(偏移量)来代替变量名称。 上面的这些指令可不能真正的编译为任何机械代码。 为何可执行程序老是被装入偏移量100h? 操作系统在CS寄放器(代码段)存储着程序信息,比如命令行方式下的参数等等。 尽管上面只是一个COM文件的例子,EXE文件调入在偏移量0000的位置,他利用特定的段保留变量。 咱们在下面会学习到关于EXE文件的知识。 数组数组能够看做是变量链。 一个字符串是一个字节数组的例子,其中每一个字符都看成一个ASCII码的值(0....255)下面是一些概念数组的例子 aDB48h,65h,6Ch,6Ch,6Fh,00h bDB'Hello',0b是一个数组,当编译器发觉引用了字符串值后,会自动将这些字符转化为对应的字节。 下面图表表示的确实是声明数组后在内存中的散布: 你能够利用方括号做下标直接访问到数组中的值,例如: MOVAL,a[3]同样,你还可以使用任意一个内存索引寄存器BX,SI,DI,BP,例如: MOVSI,3MOVAL,a[SI]若是你想声明比较复杂的数组,你能够利用DUP指令形式如下numberDUP(value(s))number-重复的数量(任意常数) value-将要复制的表达式例如: cDB5DUP(9)就相当于如下概念: cDB9,9,9,9,9另外一个例子: dDB5DUP(1,2)等同于dDB1,2,1,2,1,2,1,2,1,2固然,若是需要寄存超过255或小于-128的数值,你还能够利用DW来代替DB。 可是DW不能用于声明字符串。 DUP命令展开后不能超过1020个字符(上一个例子中展开以后是13个字符),若是需要声明请将它们分成两行(如此,内存中取得的仍然是一个大数组)。 取得变量地址LEA指令(LoadEffectiveAddress读取有效地址)或OFFSET指令。 OFFSET和LEA二者都能够取得变量的偏移量。 LEA在利用中更有效,这是因为它能返回索引变量的地址。 取得变量地址在很多情形下是超级有效的,例如你打算向一个进程传递参数。 注意: 在编译进程中利用如下声明数据类型BYTEPTR-表示字节;WORDPTR-表示字(2个字节)例如: BYTEPTR[BX];按字节访问;WORDPTR[BX];按字访问Emu8086允许利用如下更简练的前缀 b.-等价于上面的BYTEPTR;w.-等价于上面的WORDPTR有时,编译器能够自动计算出数据类型,可是若是一个参与运算的数是当即数,这种方式就不靠得住了。 第一个例子: ORG100h MOVAL,VAR1;将变量var1的数值放入al以便检查 LEABX,VAR1;将var1的地址存入BX. MOVBYTEPTR[BX],44h;修改变量var1的内容 MOVAL,VAR1;将变量VAR1的数值放入AL以便检查 RET VAR1DB22h END 下面是另外一个例子,用OFFSET指令代替LEA: ORG100h MOVAL,VAR1;将变量VAR1的值放入AL以便检查. MOVBX,OFFSETVAR1;将变量VAR1的地址放入BX. MOVBYTEPTR[BX],44h;修改变量VAR1内容 MOVAL,VAR1;将变量VAR1的值放入AL以便检查. RET VAR1DB22h END 上面例子的功能相同。 这些语句: LEABX,VAR1MOVBX,OFFSETVAR1都将生成同样的机器代码: MOVBX,num,num是16位变量偏移 请注意,只有这些寄放器能够放入方括号中(作为内存指针)BX,SI,DI,BP(请参考本教程前述章节)常量常量同变量很相似,可是它一直存在。 概念一个变量以后,它的值可不能改变。 利用EQU概念常量: nameequ<任意表达式>例如: kEQU5MOVAX,k 上面的例子等同于如下代码: MOVAX,5 在程序执行进程中你能够选择模拟器"View"菜单下的"Variables" 你能够点一个变量然后设置Elements属性为数组大小来查看数组。 汇编语言关于数据类型并非严格,如此以来所有的变量都能够被看作是数组。 变量能够显示为以下进制 HEX-十六进制hexadecimal(基底16). BIN-二进制(基底2). OCT-八进制(基底8). SIGNED-有符号十进制(基底10). UNSIGNED-无符号十进制(基底10). CHAR-ASCII码(一共有256个符号,其中一些符号是不可见的). 程序运行的时侯,你能够通过双击它来编辑变量值,或选中以后点Edit按钮。 十六进制数值以"h"结尾,二进制以"b"结尾,八进制以"o"结尾,十进制没有结尾。 字符串用如此的方式表示: 'helloworld',0(结尾以0表示) 数组依照如下输入: 1,2,3,4,5 (数组能够是一组字节或字,这取决于你想以字节仍是字的方式编辑)表达式会自动计算,例如,输入如下表达式5+2会自动计算为7。 等等.... 中断中断是一系列功能挪用。 这些功能挪用使得编程加倍容易。 比如,你想在打印机上输出一个字符,你只需要简单的挪用中断
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Emu8086 利用 指南 中文