收藏 分享(赏)

汇编语言超浓缩教程65387.doc

上传人:dzzj200808 文档编号:2335395 上传时间:2018-09-10 格式:DOC 页数:10 大小:60.50KB
下载 相关 举报
汇编语言超浓缩教程65387.doc_第1页
第1页 / 共10页
汇编语言超浓缩教程65387.doc_第2页
第2页 / 共10页
汇编语言超浓缩教程65387.doc_第3页
第3页 / 共10页
汇编语言超浓缩教程65387.doc_第4页
第4页 / 共10页
汇编语言超浓缩教程65387.doc_第5页
第5页 / 共10页
点击查看更多>>
资源描述

1、汇编语言超浓缩教程所有电脑语言写出的程序运行时在内存中都以机器码方式存储,机器码可以被比较准确的翻译成汇编语言,这是因为汇编语言兼容性最好,故几乎所有跟踪、调试工具(包括 WIN95/98 下)都是以汇编示人的。汇编直接与硬件打交道,如果你想搞通程序在执行时在电脑中的来龙去脉,也就是搞清电脑每个组成部分究竟在干什么、究竟怎么干?一个真正的硬件发烧友,不懂这些可不行。 对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩 DEBUG,有时 CRAC

2、K 出一个小软件比完成一个程序更有成就感(就像学电脑先玩游戏一样)。某些高深的指令事实上只对有经验的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开始,你必须要先排除那些华丽复杂的命令,将注意力集中在最重要的几个指令上(CMP LOOP MOV JNZ)。看通本文,你完全可以 “不经意” 间在前辈或是后生卖弄一下DEBUG,很有成就感的,试试看!那么这个接下来呢? Here we go!因为汇编是通过 CPU 和内存跟硬件对话的,所以我们不得不先了解一下CPU 和内存:是可以执行电脑所有算术逻辑运算与基本 I/O 控制功能的一块芯片。一种汇编语言只能用于特定的 CPU。也就

3、是说,不同的 CPU 其汇编语言的指令语法亦不相同。个人电脑由 1981 年推出至今,其 CPU 发展过程为:8086802868038680486PENTIUM ,还有 AMD、CYRIX 等旁支。后面兼容前面 CPU 的功能,只不过多了些指令(如多能奔腾的 MMX 指令集)、增大了寄存器(如 386 的 32 位 EAX)、增多了寄存器(如 486 的 FS)。为确保汇编程序可以适用于各种机型,所以推荐使用 8086 汇编语言,其兼容性最佳。本文所提均为 8086 汇编语言。寄存器(Register)是 CPU 内部的元件,所以在寄存器之间的数据传送非常快。用途:1.可将寄存器内的数据执行

4、算术及逻辑运算。2.存于寄存器内的地址可用来指向内存的某个位置,即寻址。3.可以用来读写数据到电脑的周边设备。8086 有 8 个 8 位数据寄存器,这些 8 位寄存器可分别组成 16 位寄存器:定义段assume cs:prognam ; 把上面定义段的段基址放入 CSmov cx,100h ; 装入循环次数mov dl,0 ; 装入第一个 ASCII 码,随后每次循环装入新码next: mov ah,2int 21hinc dl ;INC:递增指令,每次将数据寄存器 DL 内的数值加 1loop next ; 循环指令,执行一次,CX 减 1,直到 CX 为 0,循环停止int 20hpr

5、ognam ends ;段终止end ;汇编终止在汇编语言的源程序中,每一个程序行都包含三项元素:start: mov dl,1 ;装入第一个 ASCII 码,随后每次循环装入新码标识符 表达式 注解在原始文件中加上注解可使程序更易理解,便于以后参考。每行注解以“;”与程序行分离。编译器对注解不予理会,注解的数据不会出现在OBJ、EXE 或 COM 文件中。由于我们在写源程序时,并不知道每一程序行的地址,所以必须以符号名称来代表相对地址,称为“标识符” 。我们通常在适当行的适当位置上,键入标识符。标识符(label)最长可达 31 个字节,因此我们在程序中,尽量以简洁的文字做为标识符。现在,你

6、可以将此 ASCII.ASM 文件编译成 ASCII.COM 了。1.MASM ASCII, 2.LINK ASCII,3.EXE2BIN ASCII ASCII.COM。注意:当你以编译器汇编你设计的程序时,常会发生打字错误、标识符名称拼错、十六进制数少了、逻辑错误等。汇编老手常给新人的忠告是:最好料到自己所写的程序一定会有些错误(别人告诉我的);如果第一次执行程序后,就得到期望的结果,你最好还是在检查一遍,因为它可能是错的。原则上,只要大体的逻辑架构正确,查找程序中错误的过程,与写程序本身相比甚至更有意思。写大程序时,最好能分成许多模块,如此可使程序本身的目的较单纯,易于撰写与查错,另外也

7、可让程序中不同部份之间的界限较清楚,节省编译的时间。如果读程序有读不懂的地方最好用纸笔记下有关寄存器、内存等内容,在纸上慢慢比划,就豁然开朗了。 下面我们将写一个能从键盘取得一个十进制的数值,并将其转换成十六进制数值而显示于屏幕上的“大程序” 。前言:要让 8086 执行这样的功能,我们必须先将此问题分解成一连串的步骤,称为程序规划。首先,以流程图的方式,来确保整个程序在逻辑上没有问题(不用说了吧!什么语言都要有此步骤)。这种模块化的规划方式,称之为“由上而下的程序规划”。而在真正写程序时,却是从最小的单位模块(子程序)开始,当每个模块都完成之后,再合并成大程序;这种大处著眼,小处著手的方式称

8、为“由下而上的程序设计” 。我们的第一个模块是 BINIHEX,其主要用途是从 8086 的 BX 寄存器中取出二进制数,并以十六进制方式显示在屏幕上。注意:子程序如不能独立运行,实属正常。binihex segmentassume cs:binihexmov ch,4 ;记录转换后的十六进制位数(四位)rotate: mov cl,4 ;利用 CL 当计数器,记录寄存器数位移动次数rol bx,cl ;循环寄存器 BX 的内容,以便依序处理 4 个十六进制数mov al,bl ;把 bx 低八位 bl 内数据转移至 aland al,0fh ;把无用位清零add al,30h ;把 AL 内

9、数据加 30H,并存入 alcmp al,3ah ;与 3ah 比较jl printit ;小于 3ah 则转移add al,7h ;把 AL 内数据加 30H,并存入 alprintit:mov dl,al ;把 ASCII 码装入 DLmov ah,2int 21hdec ch ;ch 减一,减到零时,零标志置 1jnz rotate ;JNZ:当零标志未置 1,则跳到指定地址。即:不等,则转移int 20h ;从子程序退回主程序binihex endsend利用循环左移指令 ROL 循环寄存器 BX(BX 内容将由第二个子程序提供)的内容,以便依序处理 4 个十六进制数:1. 利用 CL

10、 当计数器,记录寄存器移位的次数。2.将 BX 的第一个十六进制值移到最右边。利用 AND (逻辑“与” 运算:对应位都为时,其结果为,其余情况为零)把不要的部份清零,得到结果:先将 BL 值存入 AL 中,再利用 AND 以 0Fh(00001111)将 AL 的左边四位清零。由于到的 ASCII 码为 30h 到 39h,而到之 ASCII 码为 41h 到46h,间断了 7h,所以得到结果:若 AL 之内容小于 3Ah,则 AL 值只加 30h,否则 AL 再加 7h。ADD 指令会将两个表达式相加,其结果存于左边表达式内。标志寄存器(Flag Register)是一个单独的十六位寄存器

11、,有 9 个标志位,某些汇编指令(大部份是涉及比较、算术或逻辑运算的指令)执行时,会将相关标志位置 1 或清 0, 常碰到的标志位有零标志(ZF)、符号标志(SF)、溢出标志(OF)和进位标志(CF )。 标志位保存了某个指令执行后对它的影响,可用其他相关指令,查出标志的状态,根据状态产生动作。CMP 指令很像减法,是将两个表达式的值相减,但寄存器或内存的内容并未改变,只是相对的标志位发生改变而已:若 AL 值小于 3Ah,则正负号标志位会置 0,反之则置 1。 JL 指令可解释为:小于就转移到指定位置,大于、等于则向下执行。CMP 和JG 、JL 等条件转移指令一起使用,可以形成程序的分支结

12、构,是写汇编程序常用技巧。第二个模块 DECIBIN 用来接收键盘打入的十进制数,并将它转换成二进制数放于 BX 寄存器中,供模块 1 BINIHEX 使用。decibin segmentassume cs:decibinmov bx,0 ;BX 清零newchar:mov ah,1 ;int 21h ;读一个键盘输入符号入 al,并显示sub al,30h ;al 减去 30H,结果存于 al 中,完成 ASCII 码转二进制码jl exit ;小于零则转移cmp al,9djg exit ;左右则转移cbw ;8 位 al 转换成 16 位 axxchg ax,bx ;互换 ax 和 bx

13、 内数据mov cx,10d ;十进制数 10 入 cxmul cx ;表达式的值与 ax 内容相乘,并将结果存于 axxchg ax,bxadd bx,axjmp newchar ;无条件转移exit: int 20 ;回主程序decibin endsendCBW 实际结果是:若 AL 中的值为正,则 AH 填入 00h;反之,则 AH 填入FFh。XCHG 常用于需要暂时保留某个寄存器中的内容时。当然,还得一个子程序(CRLF)使后显示的十六进制数不会盖掉先输入的十进制数。crlf segmentassume cs:crlfmov dl,0dh ;回车的 ASCII 码 0DH 入 DLm

14、ov ah,2int 21hmov dl,0ah ;换行的 ASSII 码 0AH 入 AHmov ah,2int 21hint 20 ;回主程序crlf endsend现在我们就可以将 BINIHEX、DECIBIN 及 CRLF 等模块合并成一个大程序了。首先,我们要将这三个模块子程序略加改动。然后,再写一段程序来调用每一个子程序。crlf proc near;mov dl,0dhmov ah,2int 21hmov dl,0ahmov ah,2int 21hretcrlf endp类似 SEGMENT 与 ENDS 的伪指令,PROC 与 ENDP 也是成对出现,用来识别并定义一个程序。

15、其实,PROC 真正的作用只是告诉编译器:所调用的程序是属于近程(NEAR)或远程(FAR)。 一般的程序是由 DEBUG 直接调用的,所以用 INT 20 返回,用 CALL 指令所调用的程序则改用返回指令RET,RET 会把控制权转移到栈顶所指的地址,而该地址是由调用此程序的 CALL 指令所放入的。各模块都搞定了,然后我们把子程序组合起来就大功告成decihex segment ;主程序assume cs:decihexorg 100hmov cx,4 ;循环次数入 cx;由于子程序要用到 cx,故子程序要将 cx 入栈repeat: call decibin;调用十进制转二进制子程序c

16、all crlf ;调用添加回、换行符子程序call binihex ;调用二进制转十六进制并显示子程序call crlfloop repeat ;循环 4 次,可连续运算 4 次mov ah,4ch ; 调用 DOS21 号中断 4c 号功能,退出程序,作用跟 INT 20Hint 21H ; 一样,但适用面更广,INT20H 退不出时,试一下它decibin proc near push cx ;将 cx 压入堆栈,; exit: pop cx ;将 cx 还原; retdecibin endp binihex proc near push cx pop cx retbinihex end

17、p crlf proc nearpush cx pop cx retcrlf endpdecihex ends endCALL 指令用来调用子程序,并将控制权转移到子程序地址,同时将CALL 的下行一指令地址定为返回地址,并压入堆栈中。 CALL 可分为近程(NEAR)及远程(FAR)两种:1.NEAR:IP 的内容被压入堆栈中,用于程序与程序在同一段中。2.FAR:CS 、IP 寄存器的内容依次压入堆栈中,用于程序与程序在不同段中。PUSH、POP 又是一对指令用于将寄存器内容压入、弹出,用来保护寄存器数据,子程序调用中运用较多。堆栈指针有个“后进先出” 原则,像 PUSH AX,PUSH BXPOP BX,POP AX 这样才能作到保护数据丝毫不差。汇编语言超浓缩教程到这要告一段落了,希望能奠定你独立设计的基础。而更多更好的技巧则全依赖你平时的积累了。祝你成功!

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报