清华大学冯博琴微机原理第4章汇编语言程序设计.ppt_第1页
清华大学冯博琴微机原理第4章汇编语言程序设计.ppt_第2页
清华大学冯博琴微机原理第4章汇编语言程序设计.ppt_第3页
清华大学冯博琴微机原理第4章汇编语言程序设计.ppt_第4页
清华大学冯博琴微机原理第4章汇编语言程序设计.ppt_第5页
已阅读5页,还剩120页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第4章 汇编语言程序设计,.ASM,.OBJ,.EXE,编译,连接,编译程序: MASM.EXE,连接程序: LINK.EXE,用户编写程序,程序在计算机中运行,计算机的控制由操作系统交给用户程序,运行用户程序,当用户程序运行结束后,应再将控制权交回操作系统,所以,在程序中应该有返回DOS的指令。在计算机中,返回DOS的指令是操作系统中的一个子程序,用户使用时应调用这个子程序。,每当一个用户的可执行文件.EXE装入内存后,存储器的分配情况如图:,00000H,100个字节,SS,用户程序空间,FFFFFH,CS,DS,ES,无论用户程序有几段,也无论这些段的排列顺序如何,用户程序的代码前一定有100个字节的程序段前缀(Program Segment Prefix, 简称PSP),PSP给出了用户的可执行文件(.EXE)的若干控制信息。其中PSP的开始处(第1,2字节)有一条中断指令INT 20H的代码,这条指令的功能是结束用户程序,返回操作系统。在用户程序执行完以后,通过执行该条指令就可以返回DOS。,如何使用户程序执行完后返回来执行这条指令?,DS,ES,SS,CS,首先将用户程序定义为一个远过程,当可执行文件装入内存后,DS,ES两个段寄存器被CPU自动设置为指向PSP的首址,所以一般程序的开始指令为: PUSH DS XOR AX, AX PUSH AX 即将DS的内容和0000H压入堆栈,程序结束时的最后一条语句为RET,就把压入堆栈的PSP段的段基址和偏移量0000H弹出并送入CS和IP,转而执行返回DOS的指令INT 20H。,堆栈情况,返回操作系统的另一个办法是用系统调用中断指令: INT 21H, 在用户程序结束时,用下面两条指令: MOV AH, 4CH INT 21H 这两条指令经常用在短的程序段中,即用户程序并不是一个完整的汇编程序,而只是由一些指令组成的、没有堆栈区或数据区的程序段。,第一节 伪指令,伪指令:伪指令不是处理器运行的指令,而是程序员给汇编程序下达的命令。是在编译源程序期间由汇编程序执行的命令。,因为程序要分段放在内存内,编译程序必须要知道每段的起始位置,为CPU的段寄存器分配地址;如果程序中有变量,还要定义变量空间,存放数据、结果;知道源程序的开始、结束标志,伪指令语句:在汇编时不产生二进制代码,仅为编译程序提供汇编时所需要的信息的语句。,一、段定义,一般的源程序分为4个段:代码段Code、数据段Data、堆栈段Stack、附加段Extra。 各个段从段定义语句开始,到段结束语句ENDS结束。,段名 SEGMENT 定位类型 组合类型 类别, 段体 ,段名 ENDS,用户指定,可任选定义,段名必须是合法是标识符。,定位类型:,内存可以看成是一本书,将其分成页,段,字,和字节 每256个地址为一页(PAGE),每页的起始地址为二进制: * * * 0000 0000 16进制:*00H,第一页 (256个地址),第二页 (256个地址),00000H,000FFH,00100H,00200H,001FFH,每16个地址为一段(PARA),每段的起始地址为二进制: * * * * 0000 16进制:*0H,第一段 (16个地址),第二段 (16个地址),*00H,*0FH,*10H,*1FH,*20H,段(节)是默认的定位类型,每2个地址为一个字(WORD),每个字的起始地址为偶数; 最基本的类型是字节(BYTE),字节只包含一个地址,可以是内存的任何空间。,定位类型表示所定义的段存放在内存空间时,段首地址对内存空间的要求,即段起始点是放在一页的起点上(PAGE)还是一段的起点上(PARA)等,如果不定义定位类型,编译程序将默认其为段类型,即将段首地址放在从*0H开始的内存空间,BYTE: 表示本段起始单元可以从任一地址开始; WORD: 表示本段起始单元从一个偶地址开始; PARA: 表示本段起始单元从一个段的边界开始(默认); PAGE: 表示本段起始单元从一个页的边界开始。,组合类型,组合类型是告诉编译程序,所定义的段与其他段的关系,即将该段存放内存时,是否将该段与其他段在物理上或逻辑上放在一起。 常常一个汇编程序可以有很多代码段、数据段或堆栈段,这时,就要综合考虑各段的组合类型。,NONE: 表示本段与其他段不发生任何关系,该段有自己的基地址,是默认的组合关系。,PUBLIC:在满足定位类型的前提下与其他模块的同名段连接在一起,形成一个新的逻辑段,共用一个段基址。,COMMON: 表示产生一个覆盖段。连接时,把本段与其他也用COMMON说明的同名段置成相同的起始地址,重叠在一起,共享相同的存储区,其段长度由最长的段确定。,STACK: 在每个汇编程序中,只能必须有一个堆栈段,连接时,将本段与其他也用STACK说明的同名段连接成一个连续的大的STACK段,编译程序自动初始化SS和SP寄存器,使SS的内容为该连续段的首址,SP指向堆栈底部加1的存储单元。,MEMORY: 表示本段在存储器中应定位在所有其他段的最高地址。,AT: 表示本段从表达式指定的地址处开始装入,这样,在程序中用户就可以直接定义段地址,这种方式不适用于代码段。,类别:是用单引号括起来的字符串,连接时,LINK程序把类别相同的段放在连续的存储区中(可以不同名)。类别名可以任意,但一般为CODE , STACK, DATA等,表明该段的类型,例如:定义堆栈段如下: ST SEGMENT PARA STACK STACK DB 100 DUP(?) ST ENDS,段名,组合类型,类别,定位类型,堆栈长度,段结束,通过定义,自动初始化了SS和SP。,SS:0000H,SS:0063H,SS:0064H,100字节,SP,连接两个汇编语言目标程序时,它们的数据段同名,组合类型为PUBLIC,定位类型为PARA。连接后第一个目标程序的数据段的起始物理地址是01010H,长度为17AH,则第二个目标程序数据段的起始物理地址为多少?,01010H + 17AH= 0118AH,因为第二个数据段的定位类型为PARA,故应从节(段)的边界开始,01190H,因为组合类型为PUBLIC,所以共用一个段基址,在内存中顺序存放。,现有汇编目标程序A和B,它们的数据段类别名相同,组合类型皆为COMMON,若A程序数据段中有字符串ABC,B程序数据段中有字符DEF,则执行连接操作 LINK A+B 后,产生目标程序的数据段中偏移地址为0000H单元的内容是什么?,因为COMMON类型为覆盖,所以组合后B覆盖A,44H,二、过程定义,过程的含义和子程序是一样的,一个码段中可以包含一个或多个过程。,码段名 SEGMENT 过程名1 PROC FAR RET 过程名1 ENDP 过程名2 PROC NEAR RET 过程名2 ENDP 码段名 ENDS,FAR: 该过程为远过程,调用该过程时为段间调用,即CS和IP均要重新赋值; NEAR: 该过程为近过程,调用该过程时为段内调用,只赋值IP。(默认),过程名1 PROC FAR RET 过程名1 ENDP,过程名是合法的标识符; 一个程序的主过程(起始指令所在的过程)应是FAR过程,因为该过程是DOS调用的。过程中应有RET指令,以便返回到调用处。过程可以嵌套调用,但不可以嵌套定义。,过程开始,过程结束,例:延时100ms的子程序,编程如下:,DELAY PROC MOV BL, 10 AGAIN: MOV CX, 2801H WAIT: LOOP WAIT DEC BL JNZ AGAIN RET DELAY ENDP,三、段寻址,虽然定义了段,但由于段名是任意的,编译程序仍然不知道哪个段是码段,哪个段是数据段等,所以在码段中要用ASSUME伪指令进行说明,告诉编译器不同的段寄存器分别对应哪个段地址。,ASSUME 段寄存器: 段名,段寄存器: 段名,,当汇编程序遇到一个段名时,就自动地引用给出的段寄存器对段名加以汇编。,但汇编程序将DS和ES的值赋为PSP首址的值,在程序中还要由MOV指令重新对DS赋值。,正确的DS地址,MOV AX, 数据段名 MOV DS, AX,四、结束语句 END,ENDS : 段结束 ENDP:过程结束 END: 整个汇编源程序结束(不配对使用) 汇编程序在编译时遇到END,便得知源程序已经结束。,END 表达式,表达式为可执行程序运行的起始位置,一般为主过程名。,五、ORG,ORG 表达式,指定了在其后的指令或数据存放的偏移地址。,ORG 0100H MOV AX, 0,表明该指令放在码段,其偏移地址为0100H。码段的首地址从CS:0000H处开始。,六、完整结构,DATA SEGMENT X DB 3 Y DB 5 DATA ENDS STACK SEGMENT STACK STACK DB 100 DUP(?) STACK ENDS CODE SEGMENT ASSUME CS:CODE, DS: DATA, SS:STACK BEGIN PROC FAR PUSH DS XOR AX, AX PUSH AX MOV AX, DATA MOV DS, AX RET BEGIN ENDP CODE ENDS END BEGIN,将PSP首址压栈,以便返回DOS,设置DS段寄存器内容,源程序结束,第一条指令的地址,分配段寄存器,主过程名,数据段,堆栈段,返回DOS,PUSH DS XOR AX, AX PUSH AX MOV AX, DATA MOV DS, AX,标准程序前奏,一般写在代码段开始,第二节 数据定义,一、常量、变量及标识符,常量:二进制(B),八进制(Q),十六进制(H), 十进制(D)(默认),100 01100100B 244Q 64H AB,变量:代表存放在某些存储单元的数据,这些数据在程序的运行期间随时可以修改。 在程序中以变量名的形式出现。,定义变量:给变量分配存储单元, 为这个单元起名字(变量名), 可以同时将这些存储单元预置初值。,每个变量都有三个属性,段属性(SEG) 变量所在的存储单元的段基址 偏移量属性(OFFSET) 变量所在的存储单元距段起点的字节数 类型属性(TYPE) 一个单位变量占用存储单元的字节数,分为: DB(1个字节) DW(2个字节) DD(4个字节) DQ(8个字节) DT(10个字节),DATA SETMENT X DB 5, 4 Y DW 40H Z DD 2030H DATA ENDS,DS:0000H,X,Y,Z,X,Y,Z分别都有三个属性: 段基址,偏移量,类型值 这三个属性都有固定的值。,标识符:给指令或某一存储单元地址所起的名字 标识符由下列字符组成: 字母: AZ, az; 数字: 09; 特殊字符: ? . _ $,数字不能作标识符的第一个字符,标识符最长为31个字符。,标识符后面跟冒号时,表示标号,代表该行指令的起始地址, 标号可以被转移、调用指令直接引用 标识符后面不带冒号时,表示变量。,标号:代码段中某一条指令的地址。,标号有3个属性: 段属性(SEG) 该条指令所在段的段基址 偏移量属性(OFFSET) 该指令的偏移地址(距段起点的字节数) 距离属性 表示该标号是作为段内还是段间被调用或转移的,该属性有两个值: NEAR(FFFFH, -1): 本标号只能被标号所在段的转移或调用指令所访问(段内转移),标号后有冒号; FAR (FFFEH, -2): 本标号可被其他段(不是标号所在段)的转移或调用指令访问(段间转移)。,标号名 LABEL FAR,二、数据定义伪操作,DB:定义字节,其后的每个操作数占有一个字节单元,连续存放;,BUFFER DB 2, 3, 5,DW:定义字,其后的每个操作数占有两个字节;,BUF DW 2, 3, 5,DD: 定义双字,其后每个操作数占4个字节;,若仅保留单元,不初始化,用?代替初值; 若数据重复,用 n DUP( )代替,n为重复次数。,STRING DB HELLO!,ARRAY DB 100 DUP(?),6个字节的存储单元,内为各字符对应的ASCII码, 字符串用单引号标识,保留100个字节,首地址为ARRAY,不初始化,即100个字节内均为随机值,DATA1 DB 100 DUP(AB),初始化200个字节,内有100个41H, 42H,使用汇编语言定义的伪操作命令是: VAL DB 93 DUP (5, 2 DUP(1, 2 DUP(3), 4) 则在VAL存储区前10个字节单元的数据是:,5,1,3,3,4,1,3,3,4,5,若定义 DB 1, 2, 5 DUP(0, 1, 2 DUP(3), 则在存储区前7个单元的数据是:,1,2,0,1,3,3,0,三、等值伪操作,名字 EQU 表达式,名字 = 表达式,给名字定义一个值或其他符号名或一条可执行语句,在汇编时,凡是出现该名字的地方就用定义的数据替代。,用EQU赋值的名字不能重新赋值,但可用PURGE释放后重新定义。,TIMES EQU 50 BUF DB TIMES DUP(?),等效于:,BUF DB 50 DUP(?),ALPHA EQU 256 BETA = ALPHA-2,DATA SEGMENT A DW 3 B DW 4 L EQU B-A DATA ENDS,DS:0000H,数据段,L为常量,不占空间,值为2,变量在数据段出现,一般为偏移量,在程序段出现,为存储空间的内容。,MOV AX, A MOV BX, B ADD AX, BX,; AX: 3,; BX: 4,; AX: 7,DATA SEGMENT A DW 3, 7 B DW 14 L EQU B X DW B Y EQU B-A DATA ENDS,DS:0000H,数据段,; L: B,; Y: 0004H,MOV AX, L MOV AX, X MOV AX, A MOV AX, A+2 MOV BX , Y,; AX: 000EH,; AX: 0004H,; AX: 0003H,; AX: 0007H,MOV AX, B,; X:0004H,; BX: 0004H,第三节 汇编语言运算符,汇编语言运算符:是编译程序在编译时计算的,与运算指令不同,指令是在程序运行时计算的。 一、算术运算符 ,*, / , MOD , SHL , SHR MOV AX, A+B 二、逻辑运算符 AND, OR, XOR, NOT C EQU B-A AND AX, C AND OFH,三、关系运算符 EQ, NE, LT, GT, LE, GE less than , great than 结果产生一个逻辑值,真为0FFFFH, 假为0000H,MOV AX, (choice LT 20) AND 5) OR (choice GE 20) AND 6 ),注意: 算术运算符总可以用于数字操作,其结果也是数字的。当应用于存储器操作数时,只有+, -运算符有意义; 逻辑运算符的操作数也必须是数字,存储器操作数不能进行逻辑运算; 关系运算符连接的两个操作数,必须都是数字的或是在同一段内的存储器地址。,四、值返回符 1) $运算符 $:当前地址偏移量的值,BLOCK DB HELLO! NUM EQU $-BLOCK,;NUM为 6,STR1 DW AB STR2 DB 16 DUP(?) CNT EQU $-STR1 MOV CX, CNT MOV AX, STR1 HLT,; CX为 18,; AX为4142H,STR1 DW 4142H,STR1 DB 41H, 42H,DATA SEGMENT NA EQU 15 NB EQU 10 NC DB 2 DUP(4, 2 DUP(5, 2) CNT DB $-NC CWT DW $-CNT ND DW NC DATA ENDS,设数据段定义如下:,从DS:0000H开始至CNT单元之前存放的数据依次为:_;ND单元中的值为_;CWT单元中的值为_; CNT单元中的值为_。,4,5,2,5,2,4,5,2,5,2,0000H,1,0AH,SEG 和OFFSET SEG: 求标号或变量的段基址 OFFSET: 求标号或变量的距段首址的偏移量,DATA SEGMENT A DB 12 B DW 23, 25 DATA ENDS MOV BX, OFFSET B MOV AX, SEG B LEA BX, B,; BX: 0001H,; AX: DS值,; BX: 0001H 与 MOV BX, OFFSET B,DATA SEGMENT TABLE DW 10, 20, 30, 40, 50 ENTRY DW 3 DATA ENDS MOV BX, OFFSET TABLE ADD BX, ENTRY MOV AX, BX,;0000H,;BX: 3,;AX: 1E00H,3) TYPE 标号或符号的类型值 对变量 :表示变量的字节数 DB 1, DW 2, DD 4 对标号:表示过程或指令地址的调用类型 (NEAR) -1 或 (FAR) -2,DATA SEGMENT A DB 12 B DW 23, 25 DATA ENDS MOV AX, TYPE A MOV BX, TYPE B,;AX: 0001H,;BX: 0002H,4) LENGTH 和 SIZE,LENGTH: 对DUP情况下, 变量的项数或元素个数, 在其他情况下该项属性为1; SIZE:对操作数分配的字节数。 SIZE=LENGTH TYPE,A DB 1234 B DW 5 DUP(2, 3 DUP(0) C DW AB, C, D L1: MOV AL, TYPE B MOV BL, LENGTH B MOV AH, SIZE A MOV BH, SIZE C MOV CL, TYPE L1 MOV CH, SIZE B,; AL: 2,; BL: 5,; AH: 1,; BH: 2,; CL: 0FFH,; CH: 0AH,C DW ABE, C, D 正确与否?,对于下面的数据定义,各条MOV指令单独执行后,请填充有关寄存器的内容:,TABLE1 DB ? TABLE2 DW 20 DUP(?) TABLE3 DB ABCD MOV AX, TYPE TABLE1 MOV BX, TYPE TABLE2 MOV CX, LENGTH TABLE2 MOV DX, SIZE TABLE2 MOV SI, LENGTH TABLE3,; AX: 1,; BX: 2,; CX: 20,; DX: 40,; SI: 1,5) HIGH 和LOW,HIGH: 对操作数取高字节; LOW: 对操作数取低字节。,NUM EQU 0CDEFH MOV AH, HIGH NUM MOV AL, LOW NUM,; AH: 0CDH,; AL: 0EFH,五、属性运算符,用来给指令中的操作数指定一个临时的属性,而暂时忽略操作数定义时的属性。,1) PTR 定义操作数为新的类型,新类型 PTR 操作数,操作数可以是存储器的地址或标号名,F1 DW 1234H F2 DB 23H, 56H, 18H MOV AL, BYTE PTR F1 MOV AX, WORD PTR F2,; AL: 34H,; AX: 5623H,DAT1 DB 12H, 34H DAT2 DB 56H, 78H MOV AX, WORD PTR DAT1 CMP AX, WORD PTR DAT2 JA L1 MOV BX, WORD PTR DAT2 MOV WORD PTR DAT2, AX MOV WORD PTR DAT1, BX L1: HLT,DAT1单元的值是:_,; AX: 3412H,; 7856H,56H,2) THIS 指定新类型,像PTR一样可用来建立一个特殊类型的存储器地址操作数,而没有为它分配存储器。新的存储器操作数的段和偏移量部分就是下一个能分配的存储单元的段和偏移量。,F1 EQU THIS BYTE F2 DW 4321H, 2255H MOV AL, F1 MOV AX, F2,THIS 类型名,F1,; AL: 21H,; AX: 4321H,F1和F2具有相同的段基地址和偏移地址,但类型不同。,3) 段超越,强迫当前指令的操作数按指定的段基地址寻址。,MOV AX, ES:BX,4) SHORT,用于无条件转移指令JMP,通知编译器,转移的目标地址在-128 +127之间。 JMP 标号 ;是三字节指令 JMP SHORT 标号; 是两字节指令,第四节 汇编语言程序,汇编语言编写的程序也跟高级语言类似,程序结构分三种:顺序、分支、循环;较复杂的程序也应该是由众多子程序组成的,每个子程序是一个过程,在程序中被显式地调用。变量等数据部分被定义在数据段,所有程序都要显式地定义堆栈段。汇编程序的每一条指令都与机器语言一一对应,因此,汇编生成的可执行文件代码少,适合于实时控制,但由于语法成分很少,不适合于复杂的算法、运算。汇编程序主要的调试环境是DOS系统下的DEBUG程序。,程序设计步骤,1.分析问题 2.建立数学模型 3.确定算法 4.绘制程序流程图 5.内存分配(指令或伪指令) 6.编制程序 7.程序调试,顺序结构程序,例:自然数09的平方表,存在内存TABLE开始的连续10个单元中,现XAD单元存有任意一自然数(0X10),查表求X的平方,存入YAD单元中。 解:X2 的值的地址: TABLE表的首地址 + X,DATA SEGMENT 数据段内容 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START PROC FAR PUSH DS ;将DS入栈 MOV AX,0000H ;AX置零 PUSH AX ;将0入栈 主程序 RET START ENDP CODE ENDS END,DATA SEGMENT TABLE DB 0,1,4,9,16,25,36,49,64,81 XAD DB 8 YAD DB ? DATA ENDS,MOV AX ,DATA MOV DS ,AX ;初始化DS LEA BX ,TABLE ;表的首址送BX MOV AH ,0 ;AH送0 MOV AL ,XAD ;将X送AL ADD BX , AX ;求X平方值的地址 MOV AL , BX ;X平方值送AL MOV YAD , AL,BX,BX=BX+AX,64,如何用查表指令(XLAT)完成?,例:编程求函数y=(a+b)*c-d)/e,其中a、b、c、d、e依次存放在VARA、VARB、VARC、VARD、VARE单元,结果存放在VARY单元。 解:首先定义存储单元,然后在主程序中依次实现,DATA SEGMENT VARA DB 6 VARB DB 7 VARC DB 8 VARD DB 9 VARE DB 10 VARY DB ? DATA ENDS,MOV AL , VARA ADD AL , VARB ;a+b-AL IMUL VARC ;(a+b)*c-AX MOV BH , 0 MOV BL , VARD ; d-BX SUB AX, BX ;(a+b)*c-d-AX IDIV VARE MOV VARY , AX,; AX: 09H,DX:05H,分支结构程序设计,可以有两种形式,如图所示,它们分别相当于高级语言程序中的IF-THEN-ELSE语句和CASE语句,它们适用于要根据不同条件做不同处理的情况。,实现方法:在产生分支之前,通常用比较、测试的办法在标志寄存器中设置相应的标志位,然后再选用适当的条件转移指令,以实现不同情况的分支转移。,例:符号函数: (128X+127) 设任意给定的X存放在XX单元,计算出函数Y值要求存放在YY单元。,例:符号函数:,DATA SEGMENT XX DB 0F0H YY DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START PROC FAR PUSH DS SUB AX,AX PUSH AX MOV AX,DATA MOV DS,AX,MOV AL,XX CMP AL,0 JGE BIGR MOV AL,0FFH MOV YY,AL ;AL = -1 RET BIGR: JE EQUL MOV AL,1 ;AL =1 EQUL: MOV YY,AL RET START ENDP CODE ENDS END START,实现方法:用地址表法。思路:将各分支程序的入口地址依次罗列形成一个地址表,让BX指向地址表的首地址,从键盘接收或其他方式获取要转到的分支号,再让BX与分支号进行运算,使BX指向对应分支入口地址,最后即可使用JMP WORD PTR BX 或JMP DWORD PTR BX 指令实现所要转到的分支,例:根据AL(18)中的值,转移到不同分支(R1R8)。,解:1、建立分支地址表,DATA SEGMENT BRTAB DW R11,R12 DW R21,R22 DW R31,R32 DW R81,R82 DATA ENDS,解:2、实现分支转移,方法1: LEA BX, BRTAB GTB: RCR AL , 1 JC GETAD ADD BX , 4 JMP GTB GETAD: JMP DWORD PTR BX,例:根据AL(07)中的值,转移到不同分支(R1R8)。,方法2: LEA BX, BRTAB MOV AH , 0 MUL 04H ADD BX, AX JMP DWORD PTR BX,BX,例:根据AL(07)中的值,转移到不同分支(R1R8)。,解:2、实现分支转移,循环结构程序设计,1.设置循环的初始状态 设置循环次数的计数值,以及循环体正常工作的初始状态等 2.循环体 由循环的工作部分及修改部分组成。 3.循环控制部分 循环程序设计的关键,每一个循环程序必须选择一个循环控制条件来控制循环的运行和结束,通常有两种方法控制循环:用计数控制循环,用条件控制循环,LOOP L1 = DEC CX JNZ L1,先判断条件,然后执行循环体。 DO-WHILE结构 先执行循环体,然后判断条件。 DO-UNTIL结构 特点:至少执行一次循环体。,例:显示以0结尾的字符串。 STR DB Let us have a try !,0 MOV BX,OFFSET STR AGAIN: MOV DL,BX CMP DL,0 JZ DONE ;为0结束 MOV AH,2 ;调用DOS功能的2号功能 INT 21H ;不为0,显示 INC BX ;指向下一个字符 JMP AGAIN DONE: ,例:求S=1+2+3+4+100,解1: MOV CX,100 MOV AX , 0 MOV BX,1 AG: ADD AX, BX INC BX LOOP AG MOV SUM, AX,解2: MOV CX,99 MOV AX , 1 MOV BX,2 AG: ADD AX, BX INC BX LOOP AG MOV SUM, AX,例:从给定串中寻找最大的值,并放到MAX单元.元素放在BUFFER开始的单元中。 解:分析: CX:循环比较次数, 循环次数数据个数1 BX:数据指针 LOOP:循环控制,参考程序: BUFFER DB 21,33,45,67,98,10, COUNT EQU $-BUFFER MAX DB ? MOV CX, COUNT-1 MOV BX, OFFSET BUFFER MOV AL, BX DON: INC BX ;指向下一个数 CMP AL, BX ;AL- BX JA P1 ;大于转 MOV AL, BX ;交换 P1 : LOOP DON MOV MAX,AL,例:求N! 分析: N等于0: N!=1 N不等于0: N!=N*(N-1)*(N-2) *3*2*1,程序段: MOV AX, N CMP AX, 1 JA NOZ MOV AX, 1 JMP OK NOZ: MOV BX,N-1 LP1: MUL BX DEC BX JNZ LP1 OK: MOV YY,AX,例:试编制程序把BX寄存器内的二进制数以十六进制形式在屏幕上显示出来。 分析: 1、二进制到十六进制显示必须转换成ASCII码,即0-9、41H-46H(AF) 2、BX寄存器为16位,共有4组4位二进制位,可用一个循环次数为4的循环逐一显示。 3、取出四位二进制位可以用循环左移指令,再将高四位与0FH相与。,MOV CH,4 LOOP1: MOV CL,4 ROL BX,CL;BX循环左移四位 MOV AL,BL AND AL,0FH;取其低四位 ADD AL,30H;转换为ASCII码 CMP AL,3AH JL DISP ;小于10,转换完毕 ADD AL,7;大于等于10,换到AF DISP: MOV DL,AL MOV AH,2 INT 21H ;显示 DEC CH ;循环次数减一 JNZ LOOP1 ;循环完成否继续循环,例:设计一个100ms的软件延时程序。采用多重循环程序,内循环完成10ms的延时,外层循环10次即可。,CODE SENGMET ASSUME CS:CODE START: MOV DL,10 DELAY1: MOV CX,2800H DELAY2: LOOP DELAY2 DEC DL JNZ DELAY1 MOV AH,4CH INT 21H CODE ENDS END START,以5MHz主频为例,LOOP指令执行需18个时钟周期。 10 000 *5 /18=2800,子程序设计,子程序:相对主程序而言,是被主程序调用的程序.把功能相对独立的程序段单独编写和调试,作为一个相对独立的模块供程序使用,就形成子程序 子程序调用示意图:,主,子,子,子1,子2,主,主,主,汇编语言中,子程序要用一对过程伪指令PROC和 ENDP声明,格式如下: 过程名 PROC NEAR/FAR ;过程体 过程名 ENDP 可选的参数指定过程的调用属性。没有指定过程属 性,则采用默认属性 NEAR属性(段内近调用)的过程只能被相同代码段的其他程序调用 FAR属性(段间远调用)的过程可以被相同或不同代码段的程序调用,子程序设计,利用寄存器传递参数 主程序将参数保存到寄存器中,子程序通过访问寄存器来取得变量。 子程序将参数保存到寄存器中,主程序通过访问寄存器来取得变量。,例:从键盘接收一个十进制数,将其以十六进制的形式显示出来。 分析: 1)从键盘接收十进制数,键盘输入的是ASCII码,要先转换成十六进制30H-39H,如果输入的不是数字,还要加以判断。若输入的是多位数,也要加以判断,并累加计算。 2)输入后在下一行显示十六进制数,应当有回车换行 3)将十进制数转换成十六进制数后,再逐一转换成ASCII码显示,CODE SEGMENT ASSUME CD:CODE,DS:DATA MAIN PROC FAR START: PUSH DS MOV AX,0 PUSH AX CALL DECIN CALL CRLF CALL BINTODEC RET MAIN ENDP,DECIN PROC NEAR MOV BX,0 NEWCHAR: MOV AH, 1;有回显键盘输入 INT 21H ;AL=键输入ASCII码 SUB AL, 30H JL EXIT CMP AL, 9 JG EXIT CBW,XCHG AX,BX MOV CX,10 MUL CX XCHG AX,BX ADD BX,AX JMP NEWCHAR EXIT:RET DECIN ENDP,CRLF PROC NEAR MOV DL,0DH ;回车ASCII码 MOV AH,2 INT 21H ;显示回车 MOV DL,0AH ;换行ASCII码 MOV AH,2 INT 21H ;显示换行 RET CRLF ENDP,BINTODEC PROC NRAR MOV CH,4 NEXT2: MOV CL,4 ROL BX,CL MOV AL,BL AND AL,0FH ADD AL,30 CMP AL,3AH JL PRINT ADD AL,7,PRINT: MOV DL,AL MOV AH,2 INT 21H DEC CH JNZ NEXT2 RET BINTODEC ENDP,例:从键盘接受一个十六进制数(00FFFFH,正数),转换为十进制数并在屏幕上显示出来 分析: 1)从键盘接受十六进制数,用DOS的1号功能调用逐一接收,每接收完一个再接收下一个时应将先前的左移四位。 2)接收完毕后最大为65536,显示时可以将此数除以10000,1000,100,10,1将商逐一显示即可。,CODE SEGMENT ASSUME CD:CODE,DS:DATA MAIN PROC FAR START: PUSH DS MOV AX,0 PUSH AX CALL HEXIBIN CALL CRLF CALL BINIDEC RET MAIN ENDP,HEXIBIN PROC NEAR MOV BX,0 NEW: MOV AH,1 INT 21H SUB AL,30H JL EXIT ; CMP AL,10D JL ADD_TO SUB AL,07H CMP AL,0AH JL EXIT,CMP AL,10H JGE EXIT ADD_TO: MOV CL,4 SHL BX,CL MOV AH,0 ADD BX,AX JMP NEW EXIT: RET HEXIBIN ENDP,CRLF PROC NEAR MOV DL,0DH ;回车ASCII码 MOV AH,2 INT 21H ;显示回车 MOV DL,0AH ;换行ASCII码 MOV AH,2 INT 21H ;显示换行 RET CRLF ENDP,BINIDEC PROC NEAR MOV CX,10000D CALL DEC_DIV MOV CX,1000D CALL DEC_DIV MOV CX,100D CALL DEC_DIV MOV CX,10D CALL DEC_DIV MOV CX,1D CALL DEC_DIV RET,DEC_DIV PROC NEAR MOV AX,BX MOV DX,0 DIV CX MOV BX,DX MOV DL,AL ADD DL,30H MOV AH,2 INT 21H RET DEC_DIV ENDP BINIDEC ENDP,利用共享变量(全局变量)进行参数传递 例:子程序设计:冒泡排序 规则:表中相邻两元素一一比较,并把大值元素向下交换,直至表尾(大值元素下沉),此时,称为一次冒泡(程序中一次大循环)。以后重复冒泡排序,直至最小元素冒到表顶为止。 分析:假设有N个元素,则需要N-1次冒泡,每次冒泡需要的比较次数N-1-J, J为完成的冒泡次数. 子程序名:ARRAY 子程序功能:冒泡排序 入口:TAB=数据首址,N=数据项数 出口=显示排好序的字符,子程序设计,DATA SEGMENT TAB DB 10,23,5,16,9 ;定义字符串 N = $-TAB ;N在此等于5 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA STAR: MOV AX,DATA MOV DS,AX ;初始化数据段 CALL ARRAY ;调用子程序 RET 在此定义子程序 CODE ENDS END,ARRAY PROC NEAR MOV DL,N-1 ;外循环次数 MOV BX, 0 UPPER: MOV CX,N-1 SUB CX,BX ;内循环次数 MOV SI,0,INNER: MOV AL,TABSI INC SI CMP AL,TABSI JBE DON XCHG AL,TABSI MOV TABSI-1,AL DON: LOOP INNER INC BX DEC DL CMP DL,0 JNZ UPPER OK:RET ARRAY ENDP,第五节 DOS功能调用,操作系统管理计算机,为用户提供与CPU对话的接口,也就是提供使用键盘和显示器的通道。操作系统同时管理设备、文件,这样,用户不需要具体掌握这些接口的地址,输入输出数据的格式,直接执行操作系统提供的命令就可以了。比如DOS命令:DIR, TYPE COPY等。这是用户在操作系统层面上的调用。 在运行用户程序时,DOS将操作权交给了用户程序,用户就无法再去执行DOS的操作命令了,这时,用户程序需要与键盘、显示器等系统资源打交道该怎么办?,在高级语言中,在这种情况下都是调用编译系统提供的库函数,也即编译系统已把输入输出等操作功能做成函数的形式,用户只要依据函数的格式进行调用即可。 在汇编程序中,如果用户程序要与输入输出设备打交道,就要调用现成的程序,这些程序是DOS系统的一部分,随DOS系统驻留内存,用户需要按照这些程序要求的接口格式调用。,这些完成不同功能的子程序是以中断服务程序的方式提供的。 这些功能按不同的类别分成许多组,分别有不同的中断入口,在汇编程序中最常用的是INT 21H中断入口,也称为DOS系统功能调用。这个中断入口中有90多个小程序,每个小程序都被编上号,固定完成某一种功能,调用时有一定的格式,因为对某一个小程序而言,输入条件(入口参数)和输出结果(出口参数)的格式都是固定的。用户在使用时,既要给出小程序的编号(AH),又要按照其提供的格式进行调用,才能正确完成操作。,系统功能调用的小程序有90多个,在这里只介绍与输入输出有关的一部分。,1) 在显示器上显示单个字符(2号功能),功能:在屏幕的光标处显示单个字符 入口参数: 要显示字符的ASCII码放在DL中 出口参数: 无,MOV DL, A MOV AH, 2 INT 21H,; 提供调用功能号,; 系统功能调用,; 在屏幕光标处显示字符A,运行至此,屏幕上当前光标处显示字符A,2) 在屏幕上显示字符串(9号功能),功能:在屏幕上当前光标处输出存储在内存数据段的一串字符串,该字符串以$结束。 入口参数: DS:DX指向欲显示字符串的首址 出口参数:无,DATA SEGMENT STRING DB I am a student.$ DATA ENDS MOV DX, OFFSET STRING MOV AH, 9 INT 21H,; 指向字符串首址,; 提供调用功能号,; 系统功能调用,3) 带显示的键盘输入(1号功能),功能:等待键盘输入,直到按下一个键。 入口参数: 无 出口参数: 键入键的ASCII码放在AL中,并在屏幕上显示该键。,MOV AH, 1 INT 21H MOV 2000H, AL ,; 提供调用功能号,; 系统功能调用,程序运行到此停下,等待用户键盘输入,用户从键盘键入的键的ASCII码进入AL中,4) 不带显示的键盘输入(7号功能),功能:等待键盘输入,直到按下一个键。 入口参数: 无 出口参数: 键入键的ASCII码放在AL中,但在屏幕上没有显示,常用于输入密码。,MOV AH, 7 INT 21H MOV 2000H, AL ,; 提供调用功能号,; 系统功能调用,程序运行到此停下,等待用户键盘输入,用户从键盘键入的键的ASCII码进入AL中,该功能与1号功能类似,只是输入的字符不在屏幕上显示,5) 字符串输入(10号功能),功能:等待从键盘输入一串字符到存储区的数据段,直到按下回车结束输入。 入口参数:DS:DX指向接收字符串的内存地址的首址,该地址的第一个字节是由用户设置的可输入字符串的最大字符数(含回车) 出口参数:存放输入字符串,存储区的第二个字节是实际输入的字符数(不含回车),实际输入的字符串从该存储区的第三个字节处开始存放。,DATA SEGMENT BUF DB 20, 20 DUP(?) DATA ENDS LEA DX, BUF MOV AH, 0AH INT 21H,程序运行到此停下,等待用户键盘输入,若输入ABCD后,BUF,DX,实际字符个数,开始存放,6) 程序结束,返回DOS( 4C号功能 ),功能:将控制权移交DOS。 入口参数:无 出口参数:无,MOV AH, 4CH INT 21H,在屏幕上显示Whats your name?,用户输入自己的名字#后显示:Welcome #。,DATA SEGMENT MEG DB Whats your name ?, 10,13,$ MEG1 DB Welcome $ BUF DB 30, ? ,30 DUP(0) DATA ENDS CODE SEG

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论