《2022年2022年汇编语言零基础学习 .pdf》由会员分享,可在线阅读,更多相关《2022年2022年汇编语言零基础学习 .pdf(36页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩DEBUG,有时 CRACK 出一个小软件比完成一个程序更有成就感(就像学电脑先玩游戏一样)。某些高深的指令事实上只对有经验的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开始,你必须要先排除那些华丽复杂的命令,将注意力集中在最重要的几个指令上(CMP LOOP MOV JNZ) 。但是想在啰里吧嗦的教科书中完成上述目标,谈何容易,所以本人整理了这篇超浓缩(用 WINZIP
2、、WINRAR依次压迫,嘿嘿! )教程。大言不惭的说,看通本文,你完全可以 “ 不经意 ” 间在前辈或是后生卖弄一下DEBUG,很有成就感的, 试试看!那么这个接下来呢? Here we go! (阅读时看不懂不要紧,下文必有分解)因为汇编是通过 CPU 和内存跟硬件对话的,所以我们不得不先了解一下 CPU 和内存: (关于数的进制问题在此不提)是可以执行电脑所有算术逻辑运算与基本I/O 控制功能的一块芯片。一种汇编语言只能用于特定的CPU。也就是说,不同的CPU 其汇编语言的指令语法亦不相同。个人电脑由 1981年推出至今, 其CPU 发展过程为:8086802868038680486PEN
3、TIUM ,还有 AMD 、CYRIX 等旁支。后面兼容前面 CPU 的功能,只不过多了些指令(如多能奔腾的 MMX 指令集) 、增大了寄存器 (如386的32位 EAX) 、增多了寄存器 (如486的 FS) 。为确保汇编程序可以适用于各种机型,所以推荐使用 8086汇编语言,其兼容性最佳。 本文所提均为 8086汇编语言。寄存器( Register)是 CPU 内部的元件,所以在寄存器之间的数据传送非常快。用途: 1.可将寄存器内的数据执行算术及逻辑运算。2.存于寄存器内的地址可用来指向内存的某个位置,即寻址。3.可以用来读写数据到电脑的周边设备。 8086 有8个8位数据寄存器,这些 8
4、位寄存器可分别组成 16位寄存器: & :累加寄存器,常用于运算;名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 36 页 - - - - - - - - - &:基址寄存器,常用于地址索引;&:计数寄存器,常用于计数;&:数据寄存器,常用于数据传递。为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:(Code Segment) :代码段寄存器;(Data Segment ) :数据段寄存器;(Stack Segment ) :堆栈段寄存器;(Ext
5、ra Segment ) :附加段寄存器。当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS 来指向这些起始位置。 通常是将 DS 固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K 的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS 所指的 64K 内,这就是COM 文件不得大于 64K 的原因。 8086以内存做为战场,用寄存器做为军事基地,以加速工作。除了前面所提的寄存器外,还有一些特殊功能的寄存器: IP(Intruction Pointer) :指令指针寄存器,与CS 配合使用,可跟踪程序的执行过程;
6、SP(Stack Pointer) :堆栈指针,与SS配合使用,可指向目前的堆栈位置。BP(Base Pointer) :基址指针寄存器,可用作 SS的一个相对基址位置; SI(Source Index) :源变址寄存器可用来存放相对于 DS 段之源变址指针; DI(Destination Index) :目的变址寄存器,可用来存放相对于ES 段之目的变址指针。还有一个标志寄存器FR(Flag Register ),有九个有意义的标志,将在下文用到时详细说明。内存是电脑运作中的关键部分,也是电脑在工作中储存信息的地方。内存组织有许多可存放数值的储存位置,叫“ 地址” 。8086地址总线有20位
7、,所以 CPU 拥有达 1M 的寻址空间,这也是DOS 的有效控制范围,而8086能做的运算仅限于处理 16位数据,即只有 0到64K,所以,必须用分段寻址才能控制整个内存地址。完整的20位地址可分成两部份:1.段基址 (Segment):16位二进制数后面加上四个二进制,即一个16进制,变成 20位二进制数,可设定 1M 中任何一个 64K 段,通常记做 16位二进制数; 2.偏移量(Offset):直接使用 16位二进制数,指向段基址中的任何一个地址。如: 2222(段基址) :3333(偏移量),其实际的 20位名师资料总结 - - -精品资料欢迎下载 - - - - - - - - -
8、 - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 36 页 - - - - - - - - - 地址值为:25553。 除了上述营养要充分吸收外, 你还要知道什么是DOS、BIOS 功能调用,简单的说,功能调用类似于WIN95 API,相当于子程序。汇编写程序已经够要命了,如果不用MS、IBM 的子程序,这日子真是没法过了(关于功能调用详见电脑爱好者98年11期) 。编写汇编语言有两种主要的方法:1.使用 MASM 或 TASM 等编译器;2.使用除错程序DEBUG.COM。DEBUG 其实并不能算是一个编译器,它的主要用途在于除错,即修正汇编程序
9、中的错误。不过,也可以用来写短的汇编程序,尤其对初学者而言,DEBUG 更是最佳的入门工具。因为 DEBUG 操作容易:只要键入DEBUG 回车, A 回车即可进行汇编,过程简单,而使用编译器时, 必须用到文本编辑器、 编译器本身、LINK 以及 EXE2BIN 等程序,其中每一个程序都必须用到一系列相当复杂的命令才能工作,而且用编译器处理源程序,必须加入许多与指令语句无关的指示性语句, 以供编译器识别, 使用 DEBUG 可以避免一开始就碰到许多难以理解的程序行。DEBUG 除了能够汇编程序之外,还可用来检查和修改内存位置、载入储存和执行程序、以及检查和修改寄存器,换句话说, DEBUG 是
10、为了让我们接触硬件而设计的。 (8086常用指令用法将在每个汇编程序中讲解,限于篇幅,不可能将所有指令列出)。DEBUG 的的 A 命令可以汇编出简单的COM 文件,所以 DEBUG编写的程序一定要由地址100h (COM 文件要求)开始才合法。FOLLOW ME,SETP BY SETP(步步回车):输入 A100 ; 从 DS:100开始汇编2.输入 MOV DL,1 ; 将数值 01h 装入 DL 寄存器3.输入 MOV AH,2 ; 将数值 02h 装入 DL 寄存器4.输入 INT 21 ; 调用 DOS 21号中断 2号功能,用来逐个显示装入 DL 的字符5.输入 INT 20 ;
11、 调用 DOS 20号中断,终止程序,将控制权交回给 DEBUG 6.请按 Enter 键名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 36 页 - - - - - - - - - 7.现在已将汇编语言程序放入内存中了,输入G(运行) 8.出现结果:输出一个符号。 输出结果其实不是它, 因 WORD97无法显示原结果, 故找一赝品将就着。Program terminated normally 我们可以用命令将十六进制的机器码反汇编(Unassemble )成汇编指令。你
12、将发现每一行右边的汇编指令就是被汇编成相应的机器码,而8086实际上就是以机器码来执行程序。1.输入 U100,106 1FED:0100 B201 MOV DL,01 1FED:0102 B402 MOV AH,02 1FED:0104 CD21 INT 21 1FED:0106 CD20 INT 20 DEBUG 可以用命令来查看、改变寄存器内容。CS:IP 寄存器,保存了将执行指令地址。1.输入 R AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1FED ES=1FED SS=1FED CS=1FED
13、 IP=0100 NV UP EI PL NZ NA PO NC 1FED:0100 B201 MOV DL,01 当程序由 DS:100开始执行,那么终止程序时,DEBUG 会自动将IP 内容重新设定为 100。当你要将此程序做成一个独立的可执行文件,则可以用命令对该程序命名。但一定要为COM 文件,否则无法以DEBUG 载入。输入 N SMILE.COM ;我们得告诉 DEBUG 程序长度:程序从 100开始到 106,故占用 7 ;字节。我们利用 BX 存放长度值高位部分,而以CX 存放低位部名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - -
14、 - - - - 名师精心整理 - - - - - - - 第 4 页,共 36 页 - - - - - - - - - 分。2.输入 RBX ;查看 BX 寄存器的内容,本程序只有7个字节,故本步可省略3.输入 RCX;查看 CX 寄存器的内容4.输入 7;程序的字节数5.输入 W ;用命令将该程序写入(Write)磁盘中修行至此,我们便可以真正接触8086汇编指令了。当我们写汇编语言程序的时候,通常不会直接将机器码放入内存中,而是打入一串助记符号( Mnemonic Symbols) ,这些符号比十六进制机器码更容易记住,此之谓汇编指令。助记符号,告诉CPU 应执行何种运算。也就是说,助忆
15、符号所构成的汇编语言是为人设计的,而机器语言是对 PC 设计的。现在,我们再来剖析一个可以将所有ASCII 码显示出来的程序。1. 输入 DEBUG 2. 输入 A100 3输入 MOV CX,0100 ;装入循环次数MOV DL,00 ;装入第一个 ASCII 码,随后每次循环装入新码MOV AH,02 INT 21 INC DL ;INC:递增指令,每次将数据寄存器DL 内的数值加1 LOOP 0105 ;LOOP:循环指令,每执行一次LOOP,CX 值减1,并跳;到循环的起始地址 105,直到 CX 为0,循环停止INT 20 4.输入 G 即可显示所有 ASCII 码当我们想任意显示字
16、符串,如:UNDERSTAND ?,则可以使用DOS21H 号中断 9H 号功能。输入下行程序,存盘并执行看看:1.输入 A100 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 36 页 - - - - - - - - - MOV DX,109 ;DS:DX 字符串的起始地址MOV AH,9 ;DOS 的09h 功能调用INT 21 ;字符串输出INT 20 DB UNDERSTAND ?$;定义字符串在汇编语言中,有两种不同的指令:1.正规指令:如MOV 等,是属于
17、CPU 的指令,用来告诉CPU 在程序执行时应做些什么,所以它会以运算码( OP-code)的方式存入内存中; 2.伪指令:如 DB 等,是属于DEBUG 等编译器的指令,用来告诉编译器在编译时应做些什么。DB(Define Byte) 指令用来告诉 DEBUG 将单引号内的所有ASCII 码放入内存中。使用 9H 功能的字符串必须以 $结尾。用命令可用来查看DB伪指令将那些内容放入内存。6.输入 D100 1975:0100 BA 09 01 B4 09 CD 21 CD-20 75 6E 64 65 72 73 74 .!. underst 1975:0110 61 6E 64 24 8B
18、 46 F8 89-45 04 8B 46 34 00 64 19 and$.F.E.F4.d. 1975:0120 89 45 02 33 C0 5E 5F C9-C3 00 C8 04 00 00 57 56 .E.3._.WV 1975:0130 6B F8 0E 81 C7 FE 53 8B-DF 8B C2 E8 32 FE 0B C0 k.S.2. 1975:0140 74 05 33 C0 99 EB 17 8B-45 0C E8 D4 97 8B F0 89 t.3.E. 1975:0150 56 FE 0B D0 74 EC 8B 45-08 03 C6 8B 56 FE 5
19、E 5F V.t.E.V._ 1975:0160 C9 C3 C8 02 00 00 6B D8-0E 81 C3 FE 53 89 5E FE .k.S. 1975:0170 8B C2 E8 FB FD 0B C0 75-09 8B 5E FE 8B 47 0C 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 36 页 - - - - - - - - - E8 .u.G . 现在,我们来剖析另一个程序:由键盘输入任意字符串,然后显示出来。 db 20指示 DEBUG
20、保留20h 个未用的内存空间供缓冲区使用。输入 A100 MOV DX,0116 ;DS:DX 缓冲区地址,由 DB 伪指令确定缓冲区地址MOV AH,0A ;0Ah 号功能调用INT 21 ;键盘输入缓冲区MOV DL,0A ; 由于功能 Ah 在每个字符串最后加一个归位码 (0Dh由 Enter MOV AH,02 ;产生) ,使光标自动回到输入行的最前端,为了使新输出的INT 21 ;字符串不会盖掉原来输入的字符串,所以利用功能2h加一;个换行码 (OAh),使得光标移到下一行的的最前端。MOV DX,0118 ;装入字符串的起始位置MOV AH,09 ;9h 功能遇到 $符号才会停止输
21、出,故字符串最后必须加上INT 21 ;$,否则 9h 功能会继续将内存中的无用数据胡乱显示出来INT 20 DB 20 ;定义缓冲区送你一句话:学汇编切忌心浮气燥。客套话就不讲了。工欲善其事,必先利其器。与其说DEBUG 是编译器,倒不如说它是 “ 直译器 ” ,DEBUG 的 A 命令只可将一行汇编指令转成机器语言,且立刻执行。真正编译器(MASM )的运作是利用文本编辑器(EDIT 等)将汇编指令建成一个独立且附加名为.ASM 的文本文件,称源程序。它是MASM 程序的输入部分。 MASM 将输入的 ASM名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - -
22、- - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 36 页 - - - - - - - - - 文件,编译成 .OBJ 文件,称为目标程序。 OBJ 文件仅包含有关程序各部份要载入何处及如何与其他程序合并的信息,无法直接载入内存执行。链结程序 LINK 则可将 OBJ 文件转换成可载入内存执行(EXEcute)的EXE 文件。还可以用EXE2BIN ,将符合条件的 EXE 文件转成 COM 文件(COM 文件不但占用的内存最少,而且运行速度最快)。下面我们用 MASM 写一个与用 DEBUG 写的第一个程序功能一样的程序。用 EDIT 编辑一个 SMIL
23、E.ASM 的源程序文件。源程序 DEBUG 程序prognam segment assume cs:prognam org 100h A100 mov dl,1 mov dl,1 mov ah,2 mov ah,2 int 21h int 21 int 20h int 20 prognam ends end 比较一下:1.因为 MASM 会将所有的数值假设为十进制, 而 DEBUG则只使用十六进制,所以在源程序中,我们必须在有关数字后加上代表进制的字母,如 H 代表十六进制, D 代表十进制。若是以字母开头的十六进制数字,还必须在字母前加个0,以表示它是数,如 0AH。2.源程序增加五行叙述
24、: prognam segment 与 prognam ends 是成对的,用来告诉MASM 及 LINK , 此程序将放在一个称为PROGNAM(PROGram NAMe)的程序段内,其中段名(PROGNAM )可以任取,但其位置必须固定。assume cs:prognam 必须在程序的开头, 用来告诉编译器此程序所在段的位置放在 CS 寄存器中。end用来告诉 MASM , 程序到此结束 , ORG 100H作用相当于 DEBUG 的 A100,从偏移量 100开始汇编。 COM 文件的所名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - -
25、- - - 名师精心整理 - - - - - - - 第 8 页,共 36 页 - - - - - - - - - 有源程序都必须包含这五行,且必须依相同的次序及位置出现,这点东西记下就行,千篇一律。接着,我们用MASM 编译 SMILE.ASM 。输入 MASM SMILE 不用打入附加名 .ASM。Microsoft (R) Macro Assembler Version 5.10 Copyright (C) Microsoft Corp 1981, 1988. All rights reserved. Object filename SMILE.OBJ: 是否改动输出 OBJ 文件名,如
26、不改就 ENTER Source listing NUL.LST: 是否需要列表文件 (LST) ,不需要就ENTER Cross-reference NUL.CRF: 是否需要对照文件( CRF) ,不需要则 ENTER 50162 + 403867 Bytes symbol space free 0 Warning Errors 警告错误,表示编译器对某些语句不理解,通常是输入错误。0 Severe Errors 严重错误,会造成程序无法执行,通常是语法结构错误。如果没有一个错误存在, 即可生成 OBJ 文件。OBJ 中包含的是编译后的二进制结果,它还无法被DOS 载入内存中加以执行,必须
27、加以链结(Linking ) 。以 LINK 将 OBJ 文件( SMILE.OBJ)链结成 EXE 文件(SMILE.EXE )时, 。1.输入 LINK SMILE 不用附加名 OBJ Microsoft (R) Overlay Linker Version 3.64 Copyright (C) Microsoft Corp 1981, 1988. All rights reserved. Run File SMILE.EXE: 是否改动输出 EXE 文件名,如不改就ENTER List File NUL.MAP : 是否需要列表文件(MAP) ,不需要则ENTER Libraries .
28、LIB: 是否需要库文件,要就键入文件名,不要则名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 36 页 - - - - - - - - - ENTER LINK : warning L4021: no stack segment 由于 COM 文件不使用堆栈段,所以错误信息no stack segment 并不影响程序正常执行至此已经生成EXE 文件,我们还须使用EXE2BIN 将 EXE 文件(SMILE.EXE ) ,转换成COM 文件( SMILE.COM ) 。
29、输入EXE2BIN SMILE 产生 BIN 文件(SMILE.BIN ) 。其实 BIN 文件与 COM 文件是完全相同的,但由于DOS 只认 COM、EXE 及 BAT 文件,所以 BIN 文件无法被正确执行,改名或直接输入EXE2BIN SMILE SMILE.COM即可。现在,磁盘上应该有SMILE.COM 文件了,你只要在提示符号C: 下,直接输入文件名称SMILE ,就可以执行这个程序了。你是否觉得用编译器产生程序的方法,比 DEBUG 麻烦多了!以小程序而言,的确是如此,但对于较大的程序,你就会发现其优点了。我们再将 ASCII 程序以编译器方式再做一次,看看有无差异。首先,用E
30、DIT.COM 建立 ASCII.ASM 文件。prognam segment ; 定义段assume cs:prognam ; 把上面定义段的段基址放入CS mov cx,100h ; 装入循环次数mov dl,0 ; 装入第一个 ASCII 码,随后每次循环装入新码next: mov ah,2 int 21h inc dl ;INC :递增指令,每次将数据寄存器DL 内的数值加1 loop next ; 循环指令,执行一次, CX 减1,直到 CX 为0,循环停止int 20h prognam ends ; 段终止end ;汇编终止在汇编语言的源程序中,每一个程序行都包含三项元素:名师资料
31、总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 36 页 - - - - - - - - - start: mov dl,1 ;装入第一个 ASCII 码,随后每次循环装入新码标识符 表达式 注解在原始文件中加上注解可使程序更易理解,便于以后参考。每行注解以“ ;” 与程序行分离。编译器对注解不予理会,注解的数据不会出现在 OBJ、EXE 或 COM 文件中。由于我们在写源程序时,并不知道每一程序行的地址,所以必须以符号名称来代表相对地址,称为“ 标识符 ” 。我们通常在适当行
32、的适当位置上,键入标识符。标识符(label)最长可达31 个字节,因此我们在程序中,尽量以简洁的文字做为标识符。现在,你可以将此ASCII.ASM 文件编译成ASCII.COM 了。 1.MASM ASCII,2.LINK ASCII ,3.EXE2BIN ASCII ASCII.COM 。注意:当你以编译器汇编你设计的程序时,常会发生打字错误、标识符名称拼错、十六进制数少了、逻辑错误等。汇编老手常给新人的忠告是:最好料到自己所写的程序一定会有些错误(别人告诉我的);如果第一次执行程序后,就得到期望的结果,你最好还是在检查一遍,因为它可能是错的。原则上,只要大体的逻辑架构正确,查找程序中错误
33、的过程,与写程序本身相比甚至更有意思。写大程序时,最好能分成许多模块,如此可使程序本身的目的较单纯,易于撰写与查错,另外也可让程序中不同部份之间的界限较清楚,节省编译的时间。如果读程序有读不懂的地方最好用纸笔记下有关寄存器、内存等内容,在纸上慢慢比划,就豁然开朗了。下面我们将写一个能从键盘取得一个十进制的数值,并将其转换成十六进制数值而显示于屏幕上的“ 大程序 ” 。前言:要让 8086执行这样的功能,我们必须先将此问题分解成一连串的步骤,称为程序规划。首先,以流程图的方式,来确保整个程序在逻辑上没有问题(不用说了吧!什么语言都要有此步骤)。这种模块化的规划方式,称之为 “ 由上而下的程序规划
34、 ” 。而在真正写程序时,却是从最小的单位模块 (子程序)开始,当每个模块都完成之后, 再合并成大程序;这种大处著眼,小处著手的方式称为“ 由下而上的程序设计 ” 。我们的第一个模块是BINIHEX , 其主要用途是从 8086的 BX 寄存器名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 36 页 - - - - - - - - - 中取出二进制数,并以十六进制方式显示在屏幕上。注意:子程序如不能独立运行,实属正常。binihex segment assume cs:
35、binihex mov ch,4 ;记录转换后的十六进制位数(四位)rotate: mov cl,4 ;利用 CL 当计数器,记录寄存器数位移动次数rol bx,cl ;循环寄存器 BX 的内容,以便依序处理 4个十六进制数mov al,bl ;把 bx 低八位 bl 内数据转移至 al and al,0fh ;把无用位清零add al,30h ;把 AL 内数据加 30H,并存入 al cmp al,3ah ;与3ah比较jl printit ; 小于3ah则转移add al,7h ;把 AL 内数据加 30H,并存入 al printit:mov dl,al ; 把 ASCII 码装入 D
36、L mov ah,2 int 21h dec ch ;ch减一,减到零时,零标志置1 jnz rotate ;JNZ:当零标志未置 1,则跳到指定地址。即:不等,则转移int 20h ;从子程序退回主程序binihex ends end 利用循环左移指令 ROL 循环寄存器 BX(BX 内容将由第二个子程序提供)的内容,以便依序处理 4个十六进制数 :1. 利用 CL 当计数器,记录寄存器移位的次数。2.将 BX 的第一个十六进制值移到最右边。利用AND (逻辑 “ 与” 运算:对应位都为时,其结果为,其余情况为零)把不要的部份清零,得到结果:先将BL 值存入 AL 中,再利用 AND 以0F
37、h(00001111 )将 AL 的左边四位清零。由于到的ASCII 码为30h名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 36 页 - - - - - - - - - 到39h,而到之 ASCII 码为41h 到46h,间断了 7h,所以得到结果:若 AL 之内容小于 3Ah,则 AL 值只加30h,否则 AL 再加7h。ADD 指令会将两个表达式相加,其结果存于左边表达式内。标志寄存器(Flag Register)是一个单独的十六位寄存器, 有9个标志位,某些汇
38、编指令(大部份是涉及比较、算术或逻辑运算的指令)执行时,会将相关标志位置1或清0, 常碰到的标志位有零标志(ZF) 、符号标志( SF) 、溢出标志(OF)和进位标志( CF) 。 标志位保存了某个指令执行后对它的影响,可用其他相关指令, 查出标志的状态, 根据状态产生动作。 CMP 指令很像减法,是将两个表达式的值相减,但寄存器或内存的内容并未改变,只是相对的标志位发生改变而已:若AL 值小于3Ah,则正负号标志位会置 0,反之则置 1。 JL 指令可解释为:小于就转移到指定位置,大于、等于则向下执行。 CMP 和 JG 、JL 等条件转移指令一起使用,可以形成程序的分支结构,是写汇编程序常
39、用技巧。第二个模块 DECIBIN 用来接收键盘打入的十进制数,并将它转换成二进制数放于 BX 寄存器中,供模块 1 BINIHEX 使用。decibin segment assume cs:decibin mov bx,0 ;BX 清零newchar:mov ah,1 ; int 21h ;读一个键盘输入符号入al,并显示sub al,30h ;al减去30H,结果存于 al 中,完成 ASCII 码转二进制码jl exit ; 小于零则转移cmp al,9d jg exit ;左右则转移cbw ;8位 al 转换成 16位 ax xchg ax,bx ;互换 ax 和 bx 内数据mov
40、cx,10d ;十进制数 10入 cx mul cx ;表达式的值与 ax 内容相乘,并将结果存于ax 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 36 页 - - - - - - - - - xchg ax,bx add bx,ax jmp newchar ;无条件转移exit: int 20 ;回主程序decibin ends end CBW 实际结果是 :若 AL 中的值为正,则 AH 填入00h;反之,则AH 填入 FFh。XCHG 常用于需要暂时保留某个寄
41、存器中的内容时。当然,还得一个子程序( CRLF)使后显示的十六进制数不会盖掉先输入的十进制数。crlf segment assume cs:crlf mov dl,0dh ;回车的 ASCII 码0DH 入 DL mov ah,2 int 21h mov dl,0ah ;换行的 ASSII 码0AH 入 AH mov ah,2 int 21h int 20 ;回主程序crlf ends end 现在我们就可以将BINIHEX 、DECIBIN 及 CRLF 等模块合并成一个大程序了。首先,我们要将这三个模块子程序略加改动。然后,再写一段程序来调用每一个子程序。crlf proc near;m
42、ov dl,0dh mov ah,2 int 21h 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 36 页 - - - - - - - - - mov dl,0ah mov ah,2 int 21h ret crlf endp 类似 SEGMENT 与 ENDS 的伪指令,PROC与 ENDP 也是成对出现,用来识别并定义一个程序。其实,PROC 真正的作用只是告诉编译器:所调用的程序是属于近程(NEAR)或远程( FAR) 。 一般的程序是由DEBUG 直接调用的
43、,所以用 INT 20 返回,用 CALL 指令所调用的程序则改用返回指令RET,RET 会把控制权转移到栈顶所指的地址,而该地址是由调用此程序的CALL 指令所放入的。各模块都搞定了,然后我们把子程序组合起来就大功告成decihex segment ; 主程序assume cs:decihex org 100h mov cx,4 ;循环次数入 cx;由于子程序要用到cx,故子程序要将 cx入栈repeat: call decibin;调用十进制转二进制子程序call crlf ;调用添加回、换行符子程序call binihex ;调用二进制转十六进制并显示子程序call crlf loop
44、repeat ;循环4次,可连续运算 4次mov ah,4ch ; 调用 DOS21号中断 4c 号功能,退出程序,作用跟 INT 20H int 21H ; 一样,但适用面更广, INT20H 退不出时,试一下它decibin proc near push cx ; 将 cx 压入堆栈, ; exit: pop cx ;将 cx 还原; retdecibin endp binihex proc near push cx pop cx retbinihex endp crlf proc near 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - -
45、- - - - 名师精心整理 - - - - - - - 第 15 页,共 36 页 - - - - - - - - - push cx pop cx retcrlf endpdecihex ends end CALL 指令用来调用子程序,并将控制权转移到子程序地址,同时将 CALL 的下行一指令地址定为返回地址,并压入堆栈中。 CALL 可分为近程( NEAR)及远程( FAR)两种:1.NEAR:IP 的内容被压入堆栈中,用于程序与程序在同一段中。2.FAR:CS 、IP 寄存器的内容依次压入堆栈中 ,用于程序与程序在不同段中。PUSH、POP又是一对指令用于将寄存器内容压入、弹出,用来保
46、护寄存器数据,子程序调用中运用较多。 堆栈指针有个 “ 后进先出 ” 原则, 像 PUSH AX, PUSH BX POP BX ,POP AX 这样才能作到保护数据丝毫不差。汇编语言超浓缩教程到这要告一段落了,希望能奠定你独立设计的基础。而更多更好的技巧则全依赖你平时的积累了。祝你成功!分类: 汇编学习 嵌入式开发黑客技术上一篇:如何学习汇编语言下一篇:一直以为 lea和 mov 指令差不多的,今天算是知道了,顺便测试了下C 内联汇编的效率收藏到网摘:汇编教程 (1): 如何学习汇编2008-11-01 15:43 想想我自己玩电脑也是不少时间了,也经常在各大论坛灌水,得到过很多人的帮助。但
47、是非常遗憾的事一直都没有为别人贡献过什么,现在我有点时间所以写了几篇关于汇编的文章,我以后还会继续更新。路线是:先写点16 位汇编 32位汇编解密知识外挂制作。希望大家关注,同时多给点意见,在下将非常感激,同时希望大家多多回复不要让帖子沉下去。希望多多支持如果大家有什么问题可以给我发Email:我将尽全力帮助你解答问题!写这篇文章(我准备把他写成一个系列),我想讲述如何从零开始学汇编语言程序设计,请千万相信汇编其实是很简单的,只要自己努力一定是可以学会的。可能由于我的技术( 编程和写作 ) 也很不到家在很多方面都写的不是很好甚至是胡说八道( 但愿你不会这样认为 ) 。如果你对此有什么意见可以给
48、我发Email : 给我我将竭尽全力的回复每一封邮件同时希望大家多给我提提意见,让我把文章写的更好。 ! 这篇文章里不会有太多技术方面的东西,我想在这章先和大家一起探讨如何学习汇编的问题,也许有些内容让你觉得我很啰唆。那是以为我为了照顾大部分的读者所以写的比较详细。请大家多支持我,看了之后多给我意见。如果没有意外我会坚持每个礼拜发表一篇。今天写的是第一章,只是个引子,还没具体涉及到编程。罗云彬说的好啊,学汇编就像千军万马过独木桥,能够坚持到最后的很少。这个不禁让我想起了高考啊。汇编这东西如果你真的学精通的话可以让计算机做很多别人不能够做的事情,因此很多人都想学习汇编。名师资料总结 - - -精
49、品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 16 页,共 36 页 - - - - - - - - - 掌握这方面技术,对自身的提高确实有好处。你可以通过反汇编别人的程序跟踪别人的软件,了解别人的编程思路。通过了解别人的程序思路,使自己写出更加好的程序。而且写病毒,木马和外挂等等的一些软件都必须用汇编才能够写的漂亮。研究汇编还有助于掌握一些系统底层知识,系统底层知识绝对是构造起大型软件的坚实基础。许多程序发展,都经历了这一锻炼过程的。而大多数人可能认为汇编是一门高深的学问。很难学,我前几天在网上拿了个软件
50、给我朋友用。他问我用什么写的,我说用汇编。他不信以为汇编根本就写不出强大复杂的软件,其实这都是老皇历了( 现在的汇编其实我感觉和C差不多都是调用windows API 来编程 )。造成这种原因我觉得是以前在dos 下面用汇编来写程序太麻烦,所以给人的感觉就成了很复杂, ( 以前在 dos 下汇编没有很多 API 可以调用 ) 就将汇编神话了,造成初学者在心理上就承认了汇编很难学的”事实”其实不是这样现在其他编程语言可以做的比如C,用汇编做起来也不是很麻烦。 再一方面由于学习资料比较匮乏学。初学者一般不知从何下手,由于没方向,花费了大量时间和精力,走了不少弯路。这里我就给想学汇编的指下学习方向(