黑客X档案官方论坛's Archiver

pdzhu 发表于 2008-4-24 19:43

汇编语言超浓缩教程

[color=#000000][font=宋体]“[/font][font=Times New Roman] [/font][font=宋体]哎哟,哥们儿,还捣鼓汇编呢?那东西没用,兄弟用[/font][font=Times New Roman]VB"[/font][font=宋体]钓[/font][font=Times New Roman]"[/font][font=宋体]一个[/font][font=Times New Roman]API[/font][font=宋体]就够你忙活个十天半月的,还不一定搞出来。”此君之言倒也不虚,那吾等还有无必要研他一究呢?(废话,当然有啦!要不然你写这篇文章干嘛。)别急,别急,让我把这个中原委慢慢道来:一、所有电脑语言写出的程序运行时在内存中都以机器码方式存储,机器码可以被比较准确的翻译成汇编语言,这是因为汇编语言兼容性最好,故几乎所有跟踪、调试工具(包括[/font][font=Times New Roman]WIN95/98[/font][font=宋体]下)都是以汇编示人的,如果阁下对[/font][font=Times New Roman]CRACK[/font][font=宋体]颇感兴趣……;二、汇编直接与硬件打交道,如果你想搞通程序在执行时在电脑中的来龙去脉,也就是搞清电脑每个组成部分究竟在干什么、究竟怎么干?一个真正的硬件发烧友,不懂这些可不行。三、如今玩[/font][font=Times New Roman]DOS[/font][font=宋体]的多是“高手”,如能像吾一样混入(我不是高手)“高手”内部,不仅可以从“高手”朋友那儿套些黑客级“机密”,还可以自诩“高手”尽情享受强烈的虚荣感[/font][font=Times New Roman]--#$%& [/font][font=宋体]“醒醒[/font][font=Times New Roman]![/font][font=宋体]”[/font][font=Times New Roman] [/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩[/font][font=Times New Roman]DEBUG[/font][font=宋体],有时[/font][font=Times New Roman]CRACK[/font][font=宋体]出一个小软件比完成一个程序更有成就感(就像学电脑先玩游戏一样)。某些高深的指令事实上只对有经验的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开始,你必须要先排除那些华丽复杂的命令,将注意力集中在最重要的几个指令上([/font][font=Times New Roman]CMP LOOP MOV JNZ[/font][font=宋体]……)。但是想在啰里吧嗦的教科书中完成上述目标,谈何容易,所以本人整理了这篇超浓缩(用[/font][font=Times New Roman]WINZIP[/font][font=宋体]、[/font][font=Times New Roman]WINRAR[/font][font=宋体]…依次压迫,嘿嘿!)教程。大言不惭的说,看通本文,你完全可以“不经意”间在前辈或是后生卖弄一下[/font][font=Times New Roman]DEBUG[/font][font=宋体],很有成就感的,试试看!那么――这个接下来呢?――[/font][font=Times New Roman] Here we go[/font][font=宋体]!(阅读时看不懂不要紧,下文必有分解)[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  因为汇编是通过[/font][font=Times New Roman]CPU[/font][font=宋体]和内存跟硬件对话的,所以我们不得不先了解一下[/font][font=Times New Roman]CPU[/font][font=宋体]和内存:(关于数的进制问题在此不提)[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  CPU是可以执行电脑所有算术╱逻辑运算与基本[/font][font=Times New Roman] I/O [/font][font=宋体]控制功能的一块芯片。一种汇编语言只能用于特定的[/font][font=Times New Roman]CPU[/font][font=宋体]。也就是说,不同的[/font][font=Times New Roman]CPU[/font][font=宋体]其汇编语言的指令语法亦不相同。个人电脑由[/font][font=Times New Roman]1981[/font][font=宋体]年推出至今,其[/font][font=Times New Roman]CPU[/font][font=宋体]发展过程为:[/font][font=Times New Roman]8086[/font][font=宋体]→[/font][font=Times New Roman]80286[/font][font=宋体]→[/font][font=Times New Roman]80386[/font][font=宋体]→[/font][font=Times New Roman]80486[/font][font=宋体]→[/font][font=Times New Roman]PENTIUM [/font][font=宋体]→……,还有[/font][font=Times New Roman]AMD[/font][font=宋体]、[/font][font=Times New Roman]CYRIX[/font][font=宋体]等旁支。后面兼容前面[/font][font=Times New Roman]CPU[/font][font=宋体]的功能,只不过多了些指令(如多能奔腾的[/font][font=Times New Roman]MMX[/font][font=宋体]指令集)、增大了寄存器(如[/font][font=Times New Roman]386[/font][font=宋体]的[/font][font=Times New Roman]32[/font][font=宋体]位[/font][font=Times New Roman]EAX[/font][font=宋体])、增多了寄存器(如[/font][font=Times New Roman]486[/font][font=宋体]的[/font][font=Times New Roman]FS[/font][font=宋体])。为确保汇编程序可以适用于各种机型,所以推荐使用[/font][font=Times New Roman]8086[/font][font=宋体]汇编语言,其兼容性最佳。[/font][/color]
[color=#000000][font=宋体]本文所提均为[/font][font=Times New Roman]8086[/font][font=宋体]汇编语言。寄存器([/font][font=Times New Roman]Register[/font][font=宋体])是[/font][font=Times New Roman]CPU[/font][font=宋体]内部的元件,所以在寄存器之间的数据传送非常快。用途:[/font][/color]
[font=Times New Roman][color=#000000]1.
[/color][/font][font=宋体][color=#000000]可将寄存器内的数据执行算术及逻辑运算。[/color][/font]
[font=Times New Roman][color=#000000]2.
[/color][color=#000000]2.[/color][/font][font=宋体][color=#000000]存于寄存器内的地址可用来指向内存的某个位置,即寻址。[/color][/font]
[font=Times New Roman][color=#000000]3.
[/color][color=#000000]3.[/color][/font][font=宋体][color=#000000]可以用来读写数据到电脑的周边设备。[/color][/font]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=Times New Roman]8086 [/font][font=宋体]有[/font][/color][b][font=Times New Roman]8[/font][/b][b][font=宋体]个[/font][font=Times New Roman]8[/font][/b][b][font=宋体]位数据寄存器[/font][/b][color=#000000][font=宋体],这些[/font][font=Times New Roman]8[/font][font=宋体]位寄存器可分别组成[/font][font=Times New Roman]16[/font][font=宋体]位寄存器:[/font][/color]
[color=#000000][font=宋体]AH[/font][font=Times New Roman]&[/font][font=宋体]AL=AX:累加寄存器,常用于运算;[/font][/color]
[color=#000000][font=宋体]BH[/font][font=Times New Roman]&[/font][font=宋体]BL=BX:基址寄存器,常用于地址索引;[/font][/color]
[color=#000000][font=宋体]CH[/font][font=Times New Roman]&[/font][font=宋体]CL=CX:计数寄存器,常用于计数;[/font][/color]
[color=#000000][font=宋体]DH[/font][font=Times New Roman]&[/font][font=宋体]DL=DX:数据寄存器,常用于数据传递。[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]为了运用所有的内存空间,[/font][font=Times New Roman]8086[/font][/color][font=宋体][color=#000000]设定了[/color][b]四个段寄存器[/b][color=#000000],专门用来保存段地址:[/color][/font]
[color=#000000][font=宋体]CS([/font][font=Times New Roman]Code Segment[/font][font=宋体]):代码段寄存器;[/font][/color]
[color=#000000][font=宋体]DS([/font][font=Times New Roman]Data Segment[/font][font=宋体]):数据段寄存器;[/font][/color]
[color=#000000][font=宋体]SS([/font][font=Times New Roman]Stack Segment[/font][font=宋体]):堆栈段寄存器;[/font][/color]
[color=#000000][font=宋体]ES([/font][font=Times New Roman]Extra Segment[/font][font=宋体]):附加段寄存器。[/font][/color]
[font=宋体][color=#000000]当一个程序要执行时,就要决定[/color][b]程序代码、数据和堆栈[/b][color=#000000]各要用到内存的哪些位置,通过设定段寄存器[/color][/font][color=#000000][font=Times New Roman] CS[/font][font=宋体],[/font][font=Times New Roman]DS[/font][font=宋体],[/font][font=Times New Roman]SS [/font][font=宋体]来指向这些起始位置。通常是将[/font][font=Times New Roman]DS[/font][font=宋体]固定,而根据需要修改[/font][font=Times New Roman]CS[/font][font=宋体]。所以,程序可以在可寻址空间小于[/font][font=Times New Roman]64K[/font][font=宋体]的情况下被写成任意大小。[/font][font=Times New Roman] [/font][font=宋体]所以,程序和其数据组合起来的大小,限制在[/font][font=Times New Roman]DS [/font][font=宋体]所指的[/font][font=Times New Roman]64K[/font][font=宋体]内,这就是[/font][font=Times New Roman]COM[/font][font=宋体]文件不得大于[/font][font=Times New Roman]64K[/font][font=宋体]的原因。[/font][font=Times New Roman]8086[/font][font=宋体]以内存做为战场,用寄存器做为军事基地,以加速工作。[/font][/color]
[font=宋体][color=#000000]除了前面所提的寄存器外,还有一些特殊功能的寄存器:[/color][/font]
[color=#000000][font=Times New Roman]IP[/font][font=宋体]([/font][font=Times New Roman]Intruction Pointer[/font][font=宋体]):指令指针寄存器,与[/font][font=Times New Roman]CS[/font][font=宋体]配合使用,可跟踪程序的执行过程;[/font][font=Times New Roman]SP[/font][font=宋体]([/font][font=Times New Roman]Stack Pointer[/font][font=宋体]):堆栈指针,与[/font][font=Times New Roman]SS[/font][font=宋体]配合使用,可指向目前的堆栈位置。[/font][/color]
[color=#000000][font=Times New Roman]BP[/font][font=宋体]([/font][font=Times New Roman]Base Pointer[/font][font=宋体]):基址指针寄存器,可用作[/font][font=Times New Roman]SS[/font][font=宋体]的一个相对基址位置;[/font][/color]
[color=#000000][font=Times New Roman]SI[/font][font=宋体]([/font][font=Times New Roman]Source Index[/font][font=宋体]):源变址寄存器可用来存放相对于[/font][font=Times New Roman]DS[/font][font=宋体]段之源变址指针;[/font][/color]
[color=#000000][font=Times New Roman]DI[/font][font=宋体]([/font][font=Times New Roman]Destination Index[/font][font=宋体]):目的变址寄存器,可用来存放相对于[/font][font=Times New Roman] ES [/font][font=宋体]段之目的变址指针。[/font][font=Times New Roman]FR[/font][font=宋体]([/font][font=Times New Roman]Flag Register[/font][font=宋体]):[/font][font=Times New Roman] [/font][font=宋体]标志寄存器,有九个有意义的标志,将在下文用到时详细说明。[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  内存是电脑运作中的关键部分,也是电脑在工作中储存信息的地方。内存组织有许多可存放数值的储存位置,叫“地址”。[/font][font=Times New Roman]8086[/font][/color][b][font=宋体]地址总线有[/font][font=Times New Roman]20[/font][/b][b][font=宋体]位[/font][/b][color=#000000][font=宋体],所以[/font][font=Times New Roman]CPU[/font][font=宋体]拥有达[/font][font=Times New Roman]1M[/font][font=宋体]的寻址空间,这也是[/font][font=Times New Roman]DOS[/font][font=宋体]的有效控制范围,而[/font][/color][b][font=Times New Roman]8086[/font][/b][b][font=宋体]能做的运算仅限于处理[/font][font=Times New Roman]16[/font][/b][b][font=宋体]位数据[/font][/b][color=#000000][font=宋体],即只有[/font][font=Times New Roman]0[/font][font=宋体]到[/font][font=Times New Roman]64K[/font][font=宋体],所以,必须用[b]分段寻址[/b]才能控制整个内存地址。[/font][/color]
[color=#000000][font=宋体]完整的[/font][font=Times New Roman]20[/font][font=宋体]位地址可分成两部份:[/font][/color]
[color=#000000][font=Times New Roman]1.[/font][font=宋体]段基址[/font][font=Times New Roman](Segment)[/font][font=宋体]:[/font][font=Times New Roman]16[/font][font=宋体]位二进制数后面加上四个二进制0,即一个[/font][font=Times New Roman]16[/font][font=宋体]进制0,变成[/font][font=Times New Roman]20[/font][font=宋体]位二进制数,可设定[/font][font=Times New Roman]1M[/font][font=宋体]中任何一个[/font][font=Times New Roman]64K[/font][font=宋体]段,通常记做[/font][font=Times New Roman]16[/font][font=宋体]位二进制数;[/font][/color]
[color=#000000][font=Times New Roman]2.[/font][font=宋体]偏移量[/font][font=Times New Roman](Offset)[/font][font=宋体]:直接使用[/font][font=Times New Roman]16[/font][font=宋体]位二进制数,指向段基址中的任何一个地址。如:[/font][font=Times New Roman]2222[/font][font=宋体](段基址)[/font][font=Times New Roman]:3333[/font][font=宋体](偏移量),其实际的[/font][font=Times New Roman]20[/font][font=宋体]位地址值为:[/font][font=Times New Roman]25553[/font][font=宋体]。[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]除了上述营养要充分吸收外,你还要知道什么是[/font][font=Times New Roman]DOS[/font][font=宋体]、[/font][font=Times New Roman]BIOS[/font][font=宋体]功能调用,简单的说,功能调用类似于[/font][font=Times New Roman]WIN95 API[/font][font=宋体],相当于子程序。汇编写程序已经够要命了,如果不用[/font][font=Times New Roman]MS[/font][font=宋体]、[/font][font=Times New Roman]IBM[/font][font=宋体]的子程序,这日子真是没法过了(关于功能调用详见《电脑爱好者》[/font][font=Times New Roman]98[/font][font=宋体]年[/font][font=Times New Roman]11[/font][font=宋体]期)。[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[font=宋体][color=#000000]  编写汇编语言有两种主要的方法:[/color][/font]
[color=#000000][font=Times New Roman]1. [/font][font=宋体]使用[/font][font=Times New Roman]MASM[/font][font=宋体]或[/font][font=Times New Roman]TASM[/font][font=宋体]等编译器;[/font][/color]
[color=#000000][font=Times New Roman]2. [/font][font=宋体]使用除错程序[/font][font=Times New Roman]DEBUG.COM[/font][font=宋体]。[/font][/color]
[font=Times New Roman][color=#000000]DEBUG[/color][/font][font=宋体][color=#000000]其实并不能算是一个编译器,它的主要用途在于除错,即修正汇编程序中的错误。不过,[/color][b]也可以用来写短的汇编程序[/b][color=#000000],尤其对初学者而言,[/color][/font][color=#000000][font=Times New Roman]DEBUG [/font][font=宋体]更是最佳的入门工具。因为[/font][font=Times New Roman]DEBUG[/font][font=宋体]操作容易:只要键入[/font][font=Times New Roman]DEBUG[/font][font=宋体]回车,[/font][font=Times New Roman]A[/font][font=宋体]回车即可进行汇编,过程简单,而使用编译器时,必须用到文本编辑器、编译器本身、[/font][font=Times New Roman]LINK[/font][font=宋体]以及[/font][font=Times New Roman]EXE2BIN[/font][font=宋体]等程序,其中每一个程序都必须用到一系列相当复杂的命令才能工作,而且用编译器处理源程序,必须加入许多与指令语句无关的指示性语句,以供编译器识别,使用[/font][font=Times New Roman] DEBUG [/font][font=宋体]可以避免一开始就碰到许多难以理解的程序行。[/font][font=Times New Roman]DEBUG [/font][font=宋体]除了能够汇编程序之外,还可用来检查和修改内存位置、载入储存和执行程序、以及检查和修改寄存器,换句话说,[/font][font=Times New Roman]DEBUG[/font][font=宋体]是为了让我们接触硬件而设计的。([/font][font=Times New Roman]8086[/font][font=宋体]常用指令用法将在每个汇编程序中讲解,限于篇幅,不可能将所有指令列出)。[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  [/font][font=Times New Roman]DEBUG[/font][font=宋体]的的[/font][font=Times New Roman]A[/font][font=宋体]命令可以汇编出简单的[/font][font=Times New Roman]COM[/font][font=宋体]文件,所以[/font][font=Times New Roman]DEBUG[/font][font=宋体]编写的程序一定要由地址[/font][font=Times New Roman] 100h[/font][font=宋体]([/font][font=Times New Roman]COM[/font][font=宋体]文件要求)开始才合法。[/font][font=Times New Roman]FOLLOW ME[/font][font=宋体],[/font][font=Times New Roman]SETP BY SETP[/font][font=宋体](步步回车):[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  输入[/font][font=Times New Roman] A100 [/font][font=宋体];[/font][font=Times New Roman] [/font][font=宋体]从[/font][font=Times New Roman]DS[/font][font=宋体]:[/font][font=Times New Roman]100[/font][font=宋体]开始汇编[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]2.[/font][font=宋体]输入[/font][font=Times New Roman] MOV DL,1 [/font][font=宋体];[/font][font=Times New Roman] [/font][font=宋体]将数值[/font][font=Times New Roman] 01h [/font][font=宋体]装入[/font][font=Times New Roman] DL [/font][font=宋体]寄存器[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]3.[/font][font=宋体]输入[/font][font=Times New Roman] MOV AH,2 [/font][font=宋体];[/font][font=Times New Roman] [/font][font=宋体]将数值[/font][font=Times New Roman] 02h [/font][font=宋体]装入[/font][font=Times New Roman] AH [/font][font=宋体]寄存器[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]4.[/font][font=宋体]输入[/font][font=Times New Roman] INT 21 [/font][font=宋体];[/font][font=Times New Roman] [/font][font=宋体]调用[/font][font=Times New Roman]DOS 21[/font][font=宋体]号中断[/font][font=Times New Roman]2[/font][font=宋体]号功能,用来逐个显示装入[/font][font=Times New Roman]DL[/font][font=宋体]的字符[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]5.[/font][font=宋体]输入[/font][font=Times New Roman] INT 20 [/font][font=宋体];[/font][font=Times New Roman] [/font][font=宋体]调用[/font][font=Times New Roman]DOS 20[/font][font=宋体]号中断,终止程序,将控制权交回给[/font][font=Times New Roman] DEBUG[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]6.[/font][font=宋体]请按[/font][font=Times New Roman] Enter [/font][font=宋体]键[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]7.[/font][font=宋体]现在已将汇编语言程序放入内存中了,输入[/font][font=Times New Roman] G([/font][font=宋体]运行[/font][font=Times New Roman])[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]8.[/font][font=宋体]出现结果:输出一个符号。[/font][/color]
[color=#000000][font=宋体]  ㄖ[/font][font=Times New Roman] [/font][font=宋体]←输出结果其实不是它,因[/font][font=Times New Roman]WORD97[/font][font=宋体]无法显示原结果,故找一赝品将就着。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]Program terminated normally[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[font=宋体][color=#000000]  我们可以用U命令将[/color][b]十六进制的机器码[/b][color=#000000]反汇编([/color][/font][color=#000000][font=Times New Roman]Unassemble[/font][font=宋体])成汇编指令。你将发现每一行右边的汇编指令就是被汇编成相应的机器码,而[/font][font=Times New Roman]8086[/font][font=宋体]实际上就是以机器码来执行程序。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1.[/font][font=宋体]输入[/font][font=Times New Roman] U100,106[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1FED:0100 B201 MOV DL,01[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1FED:0102 B402 MOV AH,02[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1FED:0104 CD21 INT 21[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1FED:0106 CD20 INT 20[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]DEBUG[/font][/color][font=宋体][color=#000000]可以用[/color][b]R命令[/b][color=#000000]来查看、改变寄存器内容。[/color][/font][color=#000000][font=Times New Roman]CS[/font][font=宋体]:[/font][font=Times New Roman]IP[/font][font=宋体]寄存器,保存了将执行指令地址。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1.[/font][font=宋体]输入[/font][font=Times New Roman]R[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]DS=1FED ES=1FED SS=1FED CS=1FED IP=0100 NV UP EI PL NZ NA PO NC[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1FED:0100 B201 MOV DL,01[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  当程序由[/font][font=Times New Roman]DS[/font][font=宋体]:[/font][font=Times New Roman]100[/font][font=宋体]开始执行,那么终止程序时,[/font][font=Times New Roman]DEBUG[/font][font=宋体]会自动将[/font][font=Times New Roman]IP[/font][font=宋体]内容重新设定为[/font][font=Times New Roman]100[/font][font=宋体]。当你要将此程序做成一个独立的可执行文件,则可以用N命令对该程序命名。但一定要为[/font][font=Times New Roman]COM[/font][font=宋体]文件,否则无法以[/font][font=Times New Roman]DEBUG[/font][font=宋体]载入。[/font][/color]
[color=#000000][font=宋体]  输入[/font][font=Times New Roman]N SMILE.COM [/font][font=宋体];我们得告诉[/font][font=Times New Roman]DEBUG[/font][font=宋体]程序长度:程序从[/font][font=Times New Roman]100[/font][font=宋体]开始到[/font][font=Times New Roman]106[/font][font=宋体],故占用[/font][font=Times New Roman]7[/font][font=宋体]字节。我们利用[/font][font=Times New Roman]BX[/font][font=宋体]存放长度值高位部分,而以[/font][font=Times New Roman]CX[/font][font=宋体]存放低位部分。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]2.[/font][font=宋体]输入[/font][font=Times New Roman]RBX[/font][font=宋体];查看[/font][font=Times New Roman] BX [/font][font=宋体]寄存器的内容,本程序只有[/font][font=Times New Roman]7[/font][font=宋体]个字节,故本步可省略[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]3.[/font][font=宋体]输入[/font][font=Times New Roman] RCX[/font][font=宋体];查看[/font][font=Times New Roman] CX [/font][font=宋体]寄存器的内容[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]4.[/font][font=宋体]输入[/font][font=Times New Roman]7[/font][font=宋体];程序的字节数[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]5.[/font][font=宋体]输入[/font][font=Times New Roman]W[/font][font=宋体];用W命令将该程序写入([/font][font=Times New Roman]Write[/font][font=宋体])磁盘中[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体][size=10.5pt]  修行至此,我们便可以真正接触[/size][/font][size=10.5pt]8086[/size][font=宋体][size=10.5pt]汇编指令了。[/size][/font]
[font=宋体][size=10.5pt]当我们写汇编语言程序的时候,通常不会直接将机器码放入内存中,而是打入一串助记符号([/size][/font][size=10.5pt]Mnemonic Symbols[/size][font=宋体][size=10.5pt]),这些符号比十六进制机器码更容易记住,此之谓汇编指令。助记符号,告诉[/size][/font][size=10.5pt]CPU[/size][font=宋体][size=10.5pt]应执行何种运算。[/size][/font]
[font=宋体][size=10.5pt]也就是说,助忆符号所构成的汇编语言是为人设计的,而机器语言是对[/size][/font][size=10.5pt]PC[/size][font=宋体][size=10.5pt]设计的。[/size][/font][/color]

pdzhu 发表于 2008-4-24 19:44

[color=#000000][font=宋体]现在,我们再来剖析一个可以将所有[/font][font=Times New Roman]ASCII[/font][font=宋体]码显示出来的程序。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1. [/font][font=宋体]输入[/font][font=Times New Roman] DEBUG[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]2. [/font][font=宋体]输入[/font][font=Times New Roman] A100[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]3[/font][font=宋体].输入[/font][font=Times New Roman] MOV CX,0100 [/font][font=宋体];装入循环次数[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]MOV DL,00 [/font][font=宋体];装入第一个[/font][font=Times New Roman]ASCII[/font][font=宋体]码,随后每次循环装入新码[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]MOV AH,02[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]INT 21[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]INC DL [/font][font=宋体];[/font][font=Times New Roman]INC[/font][font=宋体]:递增指令,每次将数据寄存器[/font][font=Times New Roman] DL [/font][font=宋体]内的数值加[/font][font=Times New Roman] 1[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]LOOP 0105 [/font][font=宋体];[/font][font=Times New Roman]LOOP[/font][font=宋体]:循环指令,每执行一次[/font][font=Times New Roman]LOOP[/font][font=宋体],[/font][font=Times New Roman]CX[/font][font=宋体]值减[/font][font=Times New Roman]1[/font][font=宋体],并跳到循环的起始地址[/font][font=Times New Roman]105[/font][font=宋体],直到[/font][font=Times New Roman]CX[/font][font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体],循环停止[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]INT 20[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]4.[/font][font=宋体]输入[/font][font=Times New Roman] G[/font][font=宋体]即可显示所有[/font][font=Times New Roman]ASCII[/font][font=宋体]码[/font][/color]
[font=宋体][color=#000000] [/color][/font]
[color=#000000][font=宋体]  当我们想任意显示字符串,如:[/font][font=Times New Roman]UNDERSTAND[/font][font=宋体]?,则可以使用[/font][font=Times New Roman]DOS21H[/font][font=宋体]号中断[/font][font=Times New Roman]9H[/font][font=宋体]号功能。输入下行程序,存盘并执行看看:[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1.[/font][font=宋体]输入[/font][font=Times New Roman] A100[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] MOV DX,109 [/font][font=宋体];[/font][font=Times New Roman]DS:DX [/font][font=宋体]=[/font][font=Times New Roman] [/font][font=宋体]字符串的起始地址[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] MOV AH,9 [/font][font=宋体];[/font][font=Times New Roman]DOS[/font][font=宋体]的[/font][font=Times New Roman]09h[/font][font=宋体]功能调用[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]INT 21 [/font][font=宋体];字符串输出[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]INT 20[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]DB 'UNDERSTAND[/font][font=宋体]?[/font][font=Times New Roman]$'[/font][font=宋体];定义字符串[/font][font=Times New Roman] [/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[font=宋体][color=#000000]  在汇编语言中,有两种不同的指令:[/color][/font]
[color=#000000][font=Times New Roman]1. [/font][font=宋体]正规指令:如[/font][font=Times New Roman] MOV [/font][font=宋体]等,是属于[/font][font=Times New Roman]CPU[/font][font=宋体]的指令,用来告诉[/font][font=Times New Roman]CPU[/font][font=宋体]在程序执行时应做些什么,所以它会以运算码([/font][font=Times New Roman]OP-code[/font][font=宋体])的方式存入内存中;[/font][/color]
[color=#000000][font=Times New Roman]2. [/font][font=宋体]伪指令:如[/font][font=Times New Roman]DB[/font][font=宋体]等,是属于[/font][font=Times New Roman]DEBUG[/font][font=宋体]等编译器的指令,用来告诉编译器在编译时应做些什么。[/font][font=Times New Roman]DB[/font][font=宋体]([/font][font=Times New Roman]Define Byte[/font][font=宋体])指令用来告诉[/font][font=Times New Roman]DEBUG [/font][font=宋体]将单引号内的所有[/font][font=Times New Roman]ASCII [/font][font=宋体]码放入内存中。使用[/font][font=Times New Roman] 9H [/font][font=宋体]功能的字符串必须以[/font][font=Times New Roman]$[/font][font=宋体]结尾。用D命令可用来查看[/font][font=Times New Roman]DB[/font][font=宋体]伪指令将那些内容放入内存。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]6.[/font][font=宋体]输入[/font][font=Times New Roman] D100[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1975:0100 BA 09 01 B4 09 CD 21 CD-20 75 6E 64 65 72 73 74 ......!. underst[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1975:0110 61 6E 64 24 8B 46 F8 89-45 04 8B 46 34 00 64 19 and$.F..E..F4.d.[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1975:0120 89 45 02 33 C0 5E 5F C9-C3 00 C8 04 00 00 57 56 .E.3.^_.......WV[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1975:0130 6B F8 0E 81 C7 FE 53 8B-DF 8B C2 E8 32 FE 0B C0 k.....S.....2...[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1975:0140 74 05 33 C0 99 EB 17 8B-45 0C E8 D4 97 8B F0 89 t.3.....E.......[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1975:0150 56 FE 0B D0 74 EC 8B 45-08 03 C6 8B 56 FE 5E 5F V...t..E....V.^_[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1975:0160 C9 C3 C8 02 00 00 6B D8-0E 81 C3 FE 53 89 5E FE ......k.....S.^.[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1975:0170 8B C2 E8 FB FD 0B C0 75-09 8B 5E FE 8B 47 0C E8 .......u..^..G..[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  现在,我们来剖析另一个程序:由键盘输入任意字符串,然后显示出来。[/font][font=Times New Roman]db 20[/font][font=宋体]指示[/font][font=Times New Roman]DEBUG[/font][font=宋体]保留[/font][font=Times New Roman]20h[/font][font=宋体]个未用的内存空间供缓冲区使用。[/font][/color]
[color=#000000][font=宋体]  输入[/font][font=Times New Roman]A100[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] MOV DX,0116 [/font][font=宋体];[/font][font=Times New Roman]DS:DX [/font][font=宋体]=[/font][font=Times New Roman] [/font][font=宋体]缓冲区地址,由[/font][font=Times New Roman]DB[/font][font=宋体]伪指令确定缓冲区地址[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]MOV AH,0A [/font][font=宋体];[/font][font=Times New Roman]0Ah [/font][font=宋体]号功能调用[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]INT 21 [/font][font=宋体];键盘输入缓冲区[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]MOV DL,0A [/font][font=宋体];由于功能[/font][font=Times New Roman]Ah[/font][font=宋体]在每个字符串最后加一个归位码([/font][font=Times New Roman]0Dh[/font][font=宋体]由[/font][font=Times New Roman] Enter[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]MOV AH,02 [/font][font=宋体];产生),使光标自动回到输入行的最前端,为了使新输出的[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]INT 21 [/font][font=宋体];字符串不会盖掉原来输入的字符串,所以利用功能[/font][font=Times New Roman]2h[/font][font=宋体]加一[/font][/color]
[color=#000000][font=宋体]  ;个换行码[/font][font=Times New Roman](OAh)[/font][font=宋体],使得光标移到下一行的的最前端。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]MOV DX,0118 [/font][font=宋体];装入字符串的起始位置[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]MOV AH,09 [/font][font=宋体];[/font][font=Times New Roman]9h[/font][font=宋体]功能遇到[/font][font=Times New Roman]$[/font][font=宋体]符号才会停止输出,故字符串最后必须加上[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]INT 21 [/font][font=宋体];[/font][font=Times New Roman]$[/font][font=宋体],否则[/font][font=Times New Roman]9h[/font][font=宋体]功能会继续将内存中的无用数据胡乱显示出来[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]INT 20[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]DB 20 [/font][font=宋体];定义缓冲区[/font][font=Times New Roman] [/font][/color]
[font=宋体][color=#000000]  送你一句话:学汇编切忌心浮气燥。[/color][/font]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  客套话就不讲了。工欲善其事,必先利其器。与其说[/font][font=Times New Roman]DEBUG [/font][font=宋体]是编译器,倒不如说它是“直译器”,[/font][font=Times New Roman]DEBUG[/font][font=宋体]的[/font][font=Times New Roman]A[/font][font=宋体]命令只可将一行汇编指令转成机器语言,且立刻执行。真正编译器([/font][font=Times New Roman]MASM[/font][font=宋体])的运作是利用文本编辑器([/font][font=Times New Roman]EDIT[/font][font=宋体]等)将汇编指令建成一个独立且附加名为[/font][font=Times New Roman].ASM[/font][font=宋体]的文本文件,称源程序。它是[/font][font=Times New Roman]MASM [/font][font=宋体]程序的输入部分。[/font][font=Times New Roman]MASM[/font][font=宋体]将输入的[/font][font=Times New Roman]ASM[/font][font=宋体]文件,编译成[/font][font=Times New Roman].OBJ[/font][font=宋体]文件,称为目标程序。[/font][font=Times New Roman]OBJ[/font][font=宋体]文件仅包含有关程序各部份要载入何处及如何与其他程序合并的信息,无法直接载入内存执行。链结程序[/font][font=Times New Roman]LINK[/font][font=宋体]则可将[/font][font=Times New Roman]OBJ[/font][font=宋体]文件转换成可载入内存执行([/font][font=Times New Roman]EXEcute[/font][font=宋体])的[/font][font=Times New Roman]EXE[/font][font=宋体]文件。还可以用[/font][font=Times New Roman]EXE2BIN[/font][font=宋体],将符合条件的[/font][font=Times New Roman]EXE[/font][font=宋体]文件转成[/font][font=Times New Roman]COM[/font][font=宋体]文件([/font][font=Times New Roman]COM [/font][font=宋体]文件不但占用的内存最少,而且运行速度最快)。[/font][/color]
[color=#000000][font=宋体]  下面我们用[/font][font=Times New Roman]MASM[/font][font=宋体]写一个与用[/font][font=Times New Roman]DEBUG[/font][font=宋体]写的第一个程序功能一样的程序。[/font][/color]
[color=#000000][font=宋体]  用[/font][font=Times New Roman]EDIT[/font][font=宋体]编辑一个[/font][font=Times New Roman]SMILE.ASM[/font][font=宋体]的源程序文件。[/font][/color]
[color=#000000][font=宋体]  源程序[/font][font=Times New Roman] DEBUG [/font][font=宋体]程序[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]prognam segment[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]assume cs:prognam[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]org 100h A100[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov dl,1 mov dl,1[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov ah,2 mov ah,2[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]int 21h int 21[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]int 20h int 20[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]prognam ends[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]end[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[font=宋体][color=#000000]  比较一下:[/color][/font]
[color=#000000][font=Times New Roman]1. [/font][font=宋体]因为[/font][font=Times New Roman]MASM[/font][font=宋体]会将所有的数值假设为十进制,而[/font][font=Times New Roman]DEBUG[/font][font=宋体]则只使用十六进制,所以在源程序中,我们必须在有关数字后加上代表进制的字母,如[/font][font=Times New Roman]H[/font][font=宋体]代表十六进制,[/font][font=Times New Roman]D[/font][font=宋体]代表十进制。若是以字母开头的十六进制数字,还必须在字母前加个[/font][font=Times New Roman]0[/font][font=宋体],以表示它是数,如[/font][font=Times New Roman]0AH[/font][font=宋体]。[/font][/color]
[color=#000000][font=Times New Roman]2. [/font][font=宋体]源程序增加五行叙述:[/font][font=Times New Roman]prognam segment [/font][font=宋体]与[/font][font=Times New Roman] prognam ends [/font][font=宋体]是成对的,用来告诉[/font][font=Times New Roman] MASM [/font][font=宋体]及[/font][font=Times New Roman]LINK[/font][font=宋体],此程序将放在一个称为[/font][font=Times New Roman]PROGNAM(PROGram NAMe)[/font][font=宋体]的程序段内,其中段名([/font][font=Times New Roman]PROGNAM[/font][font=宋体])可以任取,但其位置必须固定。[/font][font=Times New Roman]assume cs:prognam [/font][font=宋体]必须在程序的开头,用来告诉编译器此程序所在段的位置放在[/font][font=Times New Roman]CS[/font][font=宋体]寄存器中。[/font][font=Times New Roman]end[/font][font=宋体]用来告诉[/font][font=Times New Roman]MASM[/font][font=宋体],程序到此结束[/font][font=Times New Roman], ORG 100H[/font][font=宋体]作用相当于[/font][font=Times New Roman]DEBUG[/font][font=宋体]的[/font][font=Times New Roman]A100[/font][font=宋体],从偏移量[/font][font=Times New Roman]100[/font][font=宋体]开始汇编。[/font][font=Times New Roman]COM [/font][font=宋体]文件的所有源程序都必须包含这五行,且必须依相同的次序及位置出现,这点东西记下就行,千篇一律。接着,我们用[/font][font=Times New Roman]MASM[/font][font=宋体]编译[/font][font=Times New Roman]SMILE.ASM[/font][font=宋体]。[/font][/color]
[color=#000000][font=宋体]  输入[/font][font=Times New Roman] MASM SMILE [/font][font=宋体]←不用打入附加名[/font][font=Times New Roman].ASM[/font][font=宋体]。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]Microsoft (R) Macro Assembler Version 5.10[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]Copyright (C) Microsoft Corp 1981, 1988. All rights reserved.[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]Object filename [SMILE.OBJ]: [/font][font=宋体]←是否改动输出[/font][font=Times New Roman]OBJ[/font][font=宋体]文件名,如不改就[/font][font=Times New Roman]ENTER[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]Source listing [NUL.LST]: [/font][font=宋体]←[/font][font=Times New Roman] [/font][font=宋体]是否需要列表文件([/font][font=Times New Roman]LST[/font][font=宋体]),不需要就[/font][font=Times New Roman]ENTER[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]Cross-reference [NUL.CRF]: [/font][font=宋体]←是否需要对照文件([/font][font=Times New Roman]CRF[/font][font=宋体]),不需要则[/font][font=Times New Roman]ENTER[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]50162 + 403867 Bytes symbol space free[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]0 Warning Errors [/font][font=宋体]←警告错误,表示编译器对某些语句不理解,通常是输入错误。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]0 Severe Errors [/font][font=宋体]←严重错误,会造成程序无法执行,通常是语法结构错误。[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  如果没有一个错误存在,即可生成[/font][font=Times New Roman]OBJ[/font][font=宋体]文件。[/font][font=Times New Roman]OBJ[/font][font=宋体]中包含的是编译后的二进制结果,它还无法被[/font][font=Times New Roman] DOS[/font][font=宋体]载入内存中加以执行,必须加以链结([/font][font=Times New Roman]Linking[/font][font=宋体])。以[/font][font=Times New Roman]LINK[/font][font=宋体]将[/font][font=Times New Roman]OBJ[/font][font=宋体]文件([/font][font=Times New Roman]SMILE.OBJ[/font][font=宋体])链结成[/font][font=Times New Roman] EXE [/font][font=宋体]文件([/font][font=Times New Roman]SMILE.EXE[/font][font=宋体])时,。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]1.[/font][font=宋体]输入[/font][font=Times New Roman] LINK SMILE [/font][font=宋体]←不用附加名[/font][font=Times New Roman]OBJ[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]Microsoft (R) Overlay Linker Version 3.64[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]Copyright (C) Microsoft Corp 1981, 1988. All rights reserved.[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]Run File [SMILE.EXE]: [/font][font=宋体]←[/font][font=Times New Roman] [/font][font=宋体]是否改动输出[/font][font=Times New Roman]EXE[/font][font=宋体]文件名,如不改就[/font][font=Times New Roman]ENTER[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]List File [NUL.MAP]: [/font][font=宋体]←[/font][font=Times New Roman] [/font][font=宋体]是否需要列表文件([/font][font=Times New Roman]MAP[/font][font=宋体]),不需要则[/font][font=Times New Roman]ENTER[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]Libraries [.LIB]: [/font][font=宋体]←是否需要库文件,要就键入文件名,不要则[/font][font=Times New Roman]ENTER[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]LINK : warning L4021: no stack segment[/font][font=宋体]←[/font][font=Times New Roman] [/font][font=宋体]由于[/font][font=Times New Roman]COM[/font][font=宋体]文件不使用堆栈段,所以错误信息[/font][/color]
[color=#000000][font=宋体]  ←[/font][font=Times New Roman]"no stack segment"[/font][font=宋体]并不影响程序正常执行[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  至此已经生成[/font][font=Times New Roman]EXE[/font][font=宋体]文件,我们还须使用[/font][font=Times New Roman]EXE2BIN [/font][font=宋体]将[/font][font=Times New Roman]EXE[/font][font=宋体]文件([/font][font=Times New Roman]SMILE.EXE[/font][font=宋体]),转换成[/font][font=Times New Roman]COM[/font][font=宋体]文件([/font][font=Times New Roman]SMILE.COM[/font][font=宋体])。输入[/font][font=Times New Roman]EXE2BIN SMILE[/font][font=宋体]产生[/font][font=Times New Roman] BIN [/font][font=宋体]文件([/font][font=Times New Roman]SMILE.BIN[/font][font=宋体])。其实[/font][font=Times New Roman] BIN [/font][font=宋体]文件与[/font][font=Times New Roman] COM [/font][font=宋体]文件是完全相同的,但由于[/font][font=Times New Roman]DOS[/font][font=宋体]只认[/font][font=Times New Roman]COM[/font][font=宋体]、[/font][font=Times New Roman]EXE[/font][font=宋体]及[/font][font=Times New Roman]BAT[/font][font=宋体]文件,所以[/font][font=Times New Roman]BIN[/font][font=宋体]文件无法被正确执行,改名或直接输入[/font][font=Times New Roman] EXE2BIN SMILE SMILE.COM[/font][font=宋体]即可。现在,磁盘上应该有[/font][font=Times New Roman] SMILE.COM [/font][font=宋体]文件了,你只要在提示符号[/font][font=Times New Roman]C[/font][font=宋体]:[/font][font=Times New Roman]>[/font][font=宋体]下,直接输入文件名称[/font][font=Times New Roman] SMILE [/font][font=宋体],就可以执行这个程序了。[/font][/color]

pdzhu 发表于 2008-4-24 19:45

[color=#000000][font=宋体]你是否觉得用编译器产生程序的方法,比[/font][font=Times New Roman] DEBUG [/font][font=宋体]麻烦多了!以小程序而言,的确是如此,但对于较大的程序,你就会发现其优点了。我们再将[/font][font=Times New Roman]ASCII[/font][font=宋体]程序以编译器方式再做一次,看看有无差异。首先,用[/font][font=Times New Roman]EDIT.COM[/font][font=宋体]建立[/font][font=Times New Roman] ASCII.ASM [/font][font=宋体]文件。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]prognam segment ;[/font][font=宋体]定义段[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]assume cs:prognam ;[/font][font=宋体]把上面定义段的段基址放入[/font][font=Times New Roman] CS[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov cx,100h ; [/font][font=宋体]装入循环次数[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov dl,0 ; [/font][font=宋体]装入第一个[/font][font=Times New Roman]ASCII[/font][font=宋体]码,随后每次循环装入新码[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]next: mov ah,2[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] int 21h[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] inc dl ;INC[/font][font=宋体]:递增指令,每次将数据寄存器[/font][font=Times New Roman] DL [/font][font=宋体]内的数值加[/font][font=Times New Roman] 1[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]loop next ; [/font][font=宋体]循环指令,执行一次,[/font][font=Times New Roman]CX[/font][font=宋体]减[/font][font=Times New Roman]1[/font][font=宋体],直到[/font][font=Times New Roman]CX[/font][font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体],循环停止[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]int 20h[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] prognam ends ;[/font][font=宋体]段终止[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]end ;[/font][font=宋体]汇编终止[/font][/color]
[font=宋体][color=#000000]  在汇编语言的源程序中,每一个程序行都包含三项元素:[/color][/font]
[color=#000000][font=宋体]   [/font][font=Times New Roman] start: mov dl,1 [/font][font=宋体];装入第一个[/font][font=Times New Roman]ASCII[/font][font=宋体]码,随后每次循环装入新码[/font][/color]
[color=#000000][font=宋体]   [/font][font=Times New Roman] [/font][font=宋体]标识符[/font][font=Times New Roman] [/font][font=宋体]表达式[/font][font=Times New Roman] [/font][font=宋体]注解[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  在原始文件中加上注解可使程序更易理解,便于以后参考。每行注解以“;”与程序行分离。编译器对注解不予理会,注解的数据不会出现在[/font][font=Times New Roman]OBJ[/font][font=宋体]、[/font][font=Times New Roman]EXE[/font][font=宋体]或[/font][font=Times New Roman]COM[/font][font=宋体]文件中。由于我们在写源程序时,并不知道每一程序行的地址,所以必须以符号名称来代表相对地址,称为“标识符”。我们通常在适当行的适当位置上,键入标识符。标识符([/font][font=Times New Roman]label[/font][font=宋体])最长可达[/font][font=Times New Roman]31 [/font][font=宋体]个字节,因此我们在程序中,尽量以简洁的文字做为标识符。现在,你可以将此[/font][font=Times New Roman]ASCII.ASM [/font][font=宋体]文件编译成[/font][font=Times New Roman] ASCII.COM [/font][font=宋体]了。[/font][font=Times New Roman]1.MASM ASCII[/font][font=宋体],[/font][font=Times New Roman]2.LINK ASCII[/font][font=宋体],[/font][font=Times New Roman]3.EXE2BIN ASCII ASCII.COM[/font][font=宋体]。[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  注意:当你以编译器汇编你设计的程序时,常会发生打字错误、标识符名称拼错、十六进制数少了h、逻辑错误等。汇编老手常给新人的忠告是:最好料到自己所写的程序一定会有些错误(别人告诉我的);如果第一次执行程序后,就得到期望的结果,你最好还是在检查一遍,因为它可能是错的。原则上,只要大体的逻辑架构正确,查找程序中错误的过程,与写程序本身相比甚至更有意思。写大程序时,最好能分成许多模块,如此可使程序本身的目的较单纯,易于撰写与查错,另外也可让程序中不同部份之间的界限较清楚,节省编译的时间。如果读程序有读不懂的地方最好用纸笔记下有关寄存器、内存等内容,在纸上慢慢比划,就豁然开朗了。[/font][font=Times New Roman] [/font][font=宋体]  下面我们将写一个能从键盘取得一个十进制的数值,并将其转换成十六进制数值而显示于屏幕上的“大程序”。前言:要让[/font][font=Times New Roman]8086[/font][font=宋体]执行这样的功能,我们必须先将此问题分解成一连串的步骤,称为程序规划。首先,以流程图的方式,来确保整个程序在逻辑上没有问题(不用说了吧!什么语言都要有此步骤)。这种模块化的规划方式,称之为“由上而下的程序规划”。而在真正写程序时,却是从最小的单位模块(子程序)开始,当每个模块都完成之后,再合并成大程序;这种大处著眼,小处著手的方式称为“由下而上的程序设计”。[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  我们的第一个模块是[/font][font=Times New Roman]BINIHEX[/font][font=宋体],其主要用途是从[/font][font=Times New Roman]8086[/font][font=宋体]的[/font][font=Times New Roman]BX[/font][font=宋体]寄存器中取出二进制数,并以十六进制方式显示在屏幕上。注意:子程序如不能独立运行,实属正常。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] binihex segment[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] assume cs:binihex[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov ch,4 ;[/font][font=宋体]记录转换后的十六进制位数(四位)[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]rotate: mov cl,4 ;[/font][font=宋体]利用[/font][font=Times New Roman]CL[/font][font=宋体]当计数器,记录寄存器数位移动次数[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]rol bx,cl ;[/font][font=宋体]循环寄存器[/font][font=Times New Roman]BX[/font][font=宋体]的内容,以便依序处理[/font][font=Times New Roman]4[/font][font=宋体]个十六进制数[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov al,bl ;[/font][font=宋体]把[/font][font=Times New Roman]bx[/font][font=宋体]低八位[/font][font=Times New Roman]bl[/font][font=宋体]内数据转移至[/font][font=Times New Roman]al[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]and al,0fh ;[/font][font=宋体]把无用位清零[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]add al,30h ;[/font][font=宋体]把[/font][font=Times New Roman]AL[/font][font=宋体]内数据加[/font][font=Times New Roman]30H[/font][font=宋体],并存入[/font][font=Times New Roman]al[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]cmp al,3ah ;[/font][font=宋体]与[/font][font=Times New Roman]3ah[/font][font=宋体]比较[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]jl printit ;[/font][font=宋体]小于[/font][font=Times New Roman]3ah[/font][font=宋体]则转移[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]add al,7h ;[/font][font=宋体]把[/font][font=Times New Roman]AL[/font][font=宋体]内数据加[/font][font=Times New Roman]30H[/font][font=宋体],并存入[/font][font=Times New Roman]al[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]printit:mov dl,al ;[/font][font=宋体]把[/font][font=Times New Roman]ASCII[/font][font=宋体]码装入[/font][font=Times New Roman]DL[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov ah,2[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] int 21h[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] dec ch ;ch[/font][font=宋体]减一,减到零时,零标志置[/font][font=Times New Roman]1[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]jnz rotate ;JNZ[/font][font=宋体]:当零标志未置[/font][font=Times New Roman]1[/font][font=宋体],则跳到指定地址。即:不等,则转移[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]int 20h ;[/font][font=宋体]从子程序退回主程序[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]binihex ends[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] end[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  利用循环左移指令[/font][font=Times New Roman]ROL[/font][font=宋体]循环寄存器[/font][font=Times New Roman]BX(BX[/font][font=宋体]内容将由第二个子程序提供[/font][font=Times New Roman])[/font][font=宋体]的内容,以便依序处理[/font][font=Times New Roman]4[/font][font=宋体]个十六进制数[/font][font=Times New Roman]:1. [/font][font=宋体]利用[/font][font=Times New Roman]CL[/font][font=宋体]当计数器,记录寄存器移位的次数。[/font][font=Times New Roman]2.[/font][font=宋体]将[/font][font=Times New Roman]BX[/font][font=宋体]的第一个十六进制值移到最右边。利用[/font][font=Times New Roman] AND [/font][font=宋体](逻辑“与”运算:对应位都为1时,其结果为1,其余情况为零)把不要的部份清零,得到结果:先将[/font][font=Times New Roman]BL[/font][font=宋体]值存入[/font][font=Times New Roman]AL[/font][font=宋体]中,再利用[/font][font=Times New Roman]AND[/font][font=宋体]以[/font][font=Times New Roman]0Fh[/font][font=宋体]([/font][font=Times New Roman]00001111[/font][font=宋体])将[/font][font=Times New Roman]AL[/font][font=宋体]的左边四位清零。由于0到9的[/font][font=Times New Roman]ASCII[/font][font=宋体]码为[/font][font=Times New Roman]30h[/font][font=宋体]到[/font][font=Times New Roman]39h[/font][font=宋体],而A到F之[/font][font=Times New Roman]ASCII[/font][font=宋体]码为[/font][font=Times New Roman]41h[/font][font=宋体]到[/font][font=Times New Roman]46h[/font][font=宋体],间断了[/font][font=Times New Roman]7h[/font][font=宋体],所以得到结果:若[/font][font=Times New Roman]AL[/font][font=宋体]之内容小于[/font][font=Times New Roman]3Ah[/font][font=宋体],则[/font][font=Times New Roman]AL[/font][font=宋体]值只加[/font][font=Times New Roman]30h[/font][font=宋体],否则[/font][font=Times New Roman]AL[/font][font=宋体]再加[/font][font=Times New Roman]7h[/font][font=宋体]。[/font][font=Times New Roman]ADD[/font][font=宋体]指令会将两个表达式相加,其结果存于左边表达式内。标志寄存器([/font][font=Times New Roman]Flag Register[/font][font=宋体])是一个单独的十六位寄存器,有[/font][font=Times New Roman]9[/font][font=宋体]个标志位,某些汇编指令(大部份是涉及比较、算术或逻辑运算的指令)执行时,会将相关标志位置[/font][font=Times New Roman]1[/font][font=宋体]或清[/font][font=Times New Roman]0[/font][font=宋体],[/font][font=Times New Roman] [/font][font=宋体]常碰到的标志位有零标志([/font][font=Times New Roman]ZF[/font][font=宋体])、符号标志([/font][font=Times New Roman]SF[/font][font=宋体])、溢出标志([/font][font=Times New Roman]OF[/font][font=宋体])和进位标志([/font][font=Times New Roman]CF[/font][font=宋体])。[/font][font=Times New Roman] [/font][font=宋体]标志位保存了某个指令执行后对它的影响,可用其他相关指令,查出标志的状态,根据状态产生动作。[/font][font=Times New Roman]CMP[/font][font=宋体]指令很像减法,是将两个表达式的值相减,但寄存器或内存的内容并未改变,只是相对的标志位发生改变而已:若[/font][font=Times New Roman] AL [/font][font=宋体]值小于[/font][font=Times New Roman] 3Ah[/font][font=宋体],则正负号标志位会置[/font][font=Times New Roman]0[/font][font=宋体],反之则置[/font][font=Times New Roman]1[/font][font=宋体]。[/font][font=Times New Roman] JL[/font][font=宋体]指令可解释为:小于就转移到指定位置,大于、等于则向下执行。[/font][font=Times New Roman]CMP[/font][font=宋体]和[/font][font=Times New Roman]JG [/font][font=宋体]、[/font][font=Times New Roman]JL[/font][font=宋体]等条件转移指令一起使用,可以形成程序的分支结构,是写汇编程序常用技巧。[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  第二个模块[/font][font=Times New Roman]DECIBIN [/font][font=宋体]用来接收键盘打入的十进制数,并将它转换成二进制数放于[/font][font=Times New Roman]BX [/font][font=宋体]寄存器中,供模块[/font][font=Times New Roman]1 BINIHEX[/font][font=宋体]使用。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]decibin segment[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]assume cs:decibin[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov bx,0 ;BX[/font][font=宋体]清零[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]newchar:mov ah,1 ;[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]int 21h ;[/font][font=宋体]读一个键盘输入符号入[/font][font=Times New Roman]al[/font][font=宋体],并显示[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]sub al,30h ;al[/font][font=宋体]减去[/font][font=Times New Roman]30H[/font][font=宋体],结果存于[/font][font=Times New Roman]al[/font][font=宋体]中,完成[/font][font=Times New Roman]ASCII[/font][font=宋体]码转二进制码[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]jl exit ;[/font][font=宋体]小于零则转移[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]cmp al,9d[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] jg exit ;[/font][font=宋体]左[/font][font=Times New Roman]>[/font][font=宋体]右则转移[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]cbw ;8[/font][font=宋体]位[/font][font=Times New Roman]al[/font][font=宋体]转换成[/font][font=Times New Roman]16[/font][font=宋体]位[/font][font=Times New Roman]ax[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]xchg ax,bx ;[/font][font=宋体]互换[/font][font=Times New Roman]ax[/font][font=宋体]和[/font][font=Times New Roman]bx[/font][font=宋体]内数据[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov cx,10d ;[/font][font=宋体]十进制数[/font][font=Times New Roman]10[/font][font=宋体]入[/font][font=Times New Roman]cx[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mul cx ;[/font][font=宋体]表达式的值与[/font][font=Times New Roman]ax[/font][font=宋体]内容相乘,并将结果存于[/font][font=Times New Roman]ax[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]xchg ax,bx[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] add bx,ax[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] jmp newchar ;[/font][font=宋体]无条件转移[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]exit: int 20 ;[/font][font=宋体]回主程序[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]decibin ends[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] end[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]CBW [/font][font=宋体]实际结果是[/font][font=Times New Roman]:[/font][font=宋体]若[/font][font=Times New Roman]AL[/font][font=宋体]中的值为正,则[/font][font=Times New Roman]AH[/font][font=宋体]填入[/font][font=Times New Roman]00h[/font][font=宋体];反之,则[/font][font=Times New Roman]AH[/font][font=宋体]填入[/font][font=Times New Roman]FFh[/font][font=宋体]。[/font][font=Times New Roman]XCHG[/font][font=宋体]常用于需要暂时保留某个寄存器中的内容时。[/font][/color]
[color=#000000][font=宋体]  当然,还得一个子程序([/font][font=Times New Roman]CRLF[/font][font=宋体])使后显示的十六进制数不会盖掉先输入的十进制数。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]crlf segment[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]assume cs:crlf[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov dl,0dh ;[/font][font=宋体]回车的[/font][font=Times New Roman]ASCII[/font][font=宋体]码[/font][font=Times New Roman]0DH[/font][font=宋体]入[/font][font=Times New Roman]DL[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov ah,2[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] int 21h[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] mov dl,0ah ;[/font][font=宋体]换行的[/font][font=Times New Roman]ASSII[/font][font=宋体]码[/font][font=Times New Roman]0AH[/font][font=宋体]入[/font][font=Times New Roman]AH[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov ah,2[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] int 21h[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] int 20 ;[/font][font=宋体]回主程序[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]crlf ends[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]end[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  现在我们就可以将[/font][font=Times New Roman]BINIHEX[/font][font=宋体]、[/font][font=Times New Roman]DECIBIN[/font][font=宋体]及[/font][font=Times New Roman]CRLF[/font][font=宋体]等模块合并成一个大程序了。首先,我们要将这三个模块子程序略加改动。然后,再写一段程序来调用每一个子程序。[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]crlf proc near[/font][font=宋体];[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov dl,0dh[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov ah,2[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]int 21h[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov dl,0ah[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov ah,2[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]int 21h[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]ret[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]crlf endp[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  类似[/font][font=Times New Roman]SEGMENT[/font][font=宋体]与[/font][font=Times New Roman]ENDS[/font][font=宋体]的伪指令,[/font][font=Times New Roman]PROC[/font][font=宋体]与[/font][font=Times New Roman]ENDP[/font][font=宋体]也是成对出现,用来识别并定义一个程序。其实,[/font][font=Times New Roman]PROC [/font][font=宋体]真正的作用只是告诉编译器:所调用的程序是属于近程([/font][font=Times New Roman]NEAR[/font][font=宋体])或远程([/font][font=Times New Roman]FAR[/font][font=宋体])。[/font][font=Times New Roman] [/font][font=宋体]一般的程序是由[/font][font=Times New Roman] DEBUG [/font][font=宋体]直接调用的,所以用[/font][font=Times New Roman] INT 20 [/font][font=宋体]返回,用[/font][font=Times New Roman] CALL [/font][font=宋体]指令所调用的程序则改用返回指令[/font][font=Times New Roman]RET,RET[/font][font=宋体]会把控制权转移到栈顶所指的地址,而该地址是由调用此程序的[/font][font=Times New Roman] CALL[/font][font=宋体]指令所放入的。[/font][/color]
[font=宋体][color=#000000]  各模块都搞定了,然后我们把子程序组合起来就大功告成[/color][/font]
[color=#000000][font=宋体]  [/font][font=Times New Roman]decihex segment ;[/font][font=宋体]主程序[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]assume cs:decihex[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]org 100h[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov cx,4 ;[/font][font=宋体]循环次数入[/font][font=Times New Roman]cx[/font][font=宋体];由于子程序要用到[/font][font=Times New Roman]cx[/font][font=宋体],故子程序要将[/font][font=Times New Roman]cx[/font][font=宋体]入栈[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]repeat: call decibin;[/font][font=宋体]调用十进制转二进制子程序[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]call crlf ;[/font][font=宋体]调用添加回、换行符子程序[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]call binihex ;[/font][font=宋体]调用二进制转十六进制并显示子程序[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]call crlf[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]loop repeat ;[/font][font=宋体]循环[/font][font=Times New Roman]4[/font][font=宋体]次,可连续运算[/font][font=Times New Roman]4[/font][font=宋体]次[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]mov ah,4ch ; [/font][font=宋体]调用[/font][font=Times New Roman]DOS21[/font][font=宋体]号中断[/font][font=Times New Roman]4c[/font][font=宋体]号功能,退出程序,作用跟[/font][font=Times New Roman]INT 20H[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]int 21H ; [/font][font=宋体]一样,但适用面更广,[/font][font=Times New Roman]INT20H[/font][font=宋体]退不出时,试一下它[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman]decibin proc near push cx ;[/font][font=宋体]将[/font][font=Times New Roman]cx[/font][font=宋体]压入堆栈,[/font][font=Times New Roman];[/font][/color]
[color=#000000][font=宋体]  ┇[/font][font=Times New Roman] exit: pop cx ;[/font][font=宋体]将[/font][font=Times New Roman]cx[/font][font=宋体]还原[/font][font=Times New Roman]; retdecibin endp binihex proc near push cx[/font][/color]
[color=#000000][font=宋体]  ┇[/font][font=Times New Roman] pop cx retbinihex endp crlf proc near[/font][/color]
[color=#000000][font=宋体]  [/font][font=Times New Roman] push cx[/font][/color]
[color=#000000][font=宋体]  ┇[/font][font=Times New Roman] pop cx retcrlf endpdecihex ends end[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[color=#000000][font=宋体]  [/font][font=Times New Roman]CALL[/font][font=宋体]指令用来调用子程序,并将控制权转移到子程序地址,同时将[/font][font=Times New Roman]CALL[/font][font=宋体]的下行一指令地址定为返回地址,并压入堆栈中。[/font][font=Times New Roman]CALL [/font][font=宋体]可分为近程([/font][font=Times New Roman]NEAR[/font][font=宋体])及远程([/font][font=Times New Roman]FAR[/font][font=宋体])两种:[/font][font=Times New Roman]1.NEAR[/font][font=宋体]:[/font][font=Times New Roman]IP[/font][font=宋体]的内容被压入堆栈中,用于程序与程序在同一段中。[/font][font=Times New Roman]2.FAR[/font][font=宋体]:[/font][font=Times New Roman]CS [/font][font=宋体]、[/font][font=Times New Roman]IP[/font][font=宋体]寄存器的内容依次压入堆栈中[/font][font=Times New Roman],[/font][font=宋体]用于程序与程序在不同段中。[/font][font=Times New Roman]PUSH[/font][font=宋体]、[/font][font=Times New Roman]POP[/font][font=宋体]又是一对指令用于将寄存器内容压入、弹出,用来保护寄存器数据,子程序调用中运用较多。堆栈指针有个“后进先出”原则,像[/font][font=Times New Roman]PUSH AX[/font][font=宋体],[/font][font=Times New Roman]PUSH BX[/font][font=宋体]…[/font][font=Times New Roman]POP BX[/font][font=宋体],[/font][font=Times New Roman]POP AX[/font][font=宋体]这样才能作到保护数据丝毫不差。[/font][/color]
[font=Times New Roman][color=#000000] [/color][/font]
[font=宋体][color=#000000]  汇编语言超浓缩教程到这要告一段落了,希望能奠定你独立设计的基础。而更多更好的技巧则全依赖你平时的积累了。祝你成功![/color][/font]

箫竹 发表于 2008-4-27 15:42

LZ太强了..支持下::04:: ::04:: ::04::

ydzj 发表于 2008-4-28 18:09

想学,但还没学,又看不懂,郁闷-ing……::07:: ::07:: ::07:: ::07:: ::07:: ::07::

 暗 发表于 2008-4-29 14:21

::03:: ::03:: ::03:: ::16:: ::16:: ::03::
我喜欢汇编!!
学习学习!!

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.