第6章 数据传送程序

102
第 6 第 第第 第第第 从从从从 从从从从 IBM-PC 从从从从从从从 从从从 从从从从从从 体、, 从从从从从从从从从从从从从从从从从 从从从从从从从从从从从从从从从从从从从从 从从 从从从从从从从从从从从从从从从 从从从从从从从从从从从从从从从从从从从 ,。 从从 从从从从从从从从从从从从从从从从从从从 从 ,。 从从从 从从从从从从从从从从从从从从从从从从从 从从从从从从从从从从 从从从从 从从从从从从 从从从从从从 从从从从从 从从从从从从从从从从从从从从 、; 从从从从从从从 从从从从从从从从从从 从从从从从从从从从从从从 从从从从从 从 ;;/。 IBM-PC 从从从从从从从 从从从 从从从 从从 从从从从从从 从从 从 :,, 从从从从 从从从从从 从

Upload: ursa-bright

Post on 15-Mar-2016

66 views

Category:

Documents


4 download

DESCRIPTION

第6章 数据传送程序. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第6章 数据传送程序

第 6 章 数据传送程序 从本章起,开始介绍 IBM-PC 机汇编指令的具体格式、功能和用法,以及各种寻址方式在程序设计中的应用。为使读者便于掌握宏汇编语言程序设计的基本方法,以后各章都配有大量的实例程序。并且为使读者能更灵活地进行汇编语言程序设计,程序实例中尽量选用不同的程序设计方法。 数据传送指令是汇编语言程序设计中最常用的指令。本章将详细介绍汇编语言数据传送指令的格式、功能及用法;结合数据传送程序设计的实例介绍各种寻址方式的使用方法;介绍堆栈的基本用法;并将介绍数据的基本输入/输出方法。 IBM-PC 机有四类数据传送指令:通用传送,累加器专用传送,地址目标传送和标志传送。

Page 2: 第6章 数据传送程序

通用传送指令:MOV 传送字节或字PUSH 字进栈POP 字退栈XCHG 字节或字交换

累加器专用指令:IN 输入字节或字OUT 输出字节或字XLAT 字节换码

地址目标传送指令:LEA 取有效地址LDS 取指示器到 DSLES 取指示器到 ES

标志传送指令:LAHF 取标志寄存器到 AHSAHF存 AH 到标志寄存器PUSHF 标志进栈POPF 标志退栈 下面分类讨论它们的格式、功能及使用方法。数据块传送程序

Page 3: 第6章 数据传送程序

6.1.1 数据传送指令 MOV 指令 ( 传送字节或字 )格式: MOV 目的操作数,源操作数其中,目的操作数和源操作数分别可以为: 目的操作数 源操作数 存储器 立即数 通用寄存器 存储器 段寄存器 ( 不能为 CS) 通用寄存器 段寄存器 ( 可以为 CS)以上目的操作数和源操作数除了不能从存储器到存储器以外,可以任意搭配。 功能:把一个字节或字从源操作数传送到目的操作数。

MOV 指令不影响状态标志。MOV 指令是一条功能很强的也是最常用的指令,它能实现:

Page 4: 第6章 数据传送程序

1.寄存器与寄存器之间的数据传送 ( 除了代码段基址寄存器 CS 和指令指针 IP 以外 ) 。 例如:

MOV AX, BX; (BX)->AXMOV DL, AH; (AH)->DLMOV DX, ES; (ES)->DXMOV DS, AX; (AX)->DS

Page 5: 第6章 数据传送程序

2.立即数传送到通用寄存器,即给AX、 BX、 CX、 DX、 BP、 SP、 SI、 DI 以及AH、 AL、 BH、 BL、 CH、 CL、 DH、 DL 寄存器赋初值。

例如:MOV AX, 100Q ; 100Q->AXMOV BX, 0FFFFH ; 0FFFFH->BXMOV AL, 4 ; 4->ALMOV CH, 100 ; 100->CHMOV SI, OFFSET TABLE; OFFSET TABLE->SI

Page 6: 第6章 数据传送程序

3.寄存器 (除了 CS和 IP以外的所有寄存器 )与存储器 ( 所有寻址方式 ) 之间的数据传送。例如:MOV AL, BUFFER ; (BUFFER)->ALMOV AX, [SI] ; ([SI])->AXMOV [DI], DX ; (DX)->[DI]MOV [BX+DI], DL ; DL->+([BX+DI])MOV SI, ES:[BP] ; (ES: [BP])->SIMOV AX, A[BX+ SI] ; (A[BX+ SI])->AX

Page 7: 第6章 数据传送程序

4.立即数传送到存储器 ( 所有寻址方式 ) ,其立即数的类型与存储器变量的类型一致。 例如:

MOV A, 3 ; 3同 A 的类型一致MOV BYTE PTR [SI], 3 ; 3 为 8 位数MOV WORD PTR [BX], 3 ; 3 为 16 位数MOV B1[BX+DI+ 1], 30H ; 30H同 B1 变量的类型 但是, MOV 指令不能实现存储单元之间的数据传送。若将存储单元 A(A 的类型为 1即 BYTE) 的内容传送到B 单元中,并且假设 A和 B 是在同一个数据段里定义的变量。用一条 MOV 指令不能直接完成这样的传送,可以用如下两条 MOV 指令实现其传送: MOV AL, A MOV B, AL

Page 8: 第6章 数据传送程序

假如需要这样传送的不是一个字节,而是一个数据块,例如 30 个字节,如果仍用上述直接寻址方式 ( 直接地址 )编程序,就需要写 60条MOV 指令。这些指令的操作符都一样,只是每条指令的地址 ( 位移量 ) 是变化的,而且地址的变化也是有规律的。为了简化程序的编制,学过一些高级语言的读者都会想到,这样的问题应该编制成循环程序。为了在每次循环执行时能够使源操作数和目的操作数修改地址,我们把地址 ( 位移量 ) 放在寄存器里,用寄存器间接寻址来寻找操作数。然后,每执行循环一次修改一次寄存器的内容使之指向下一个数据地址。用寄存器 CX 记循环次数,每循环一次减 1 ,一直到 CX 为零循环结束。

Page 9: 第6章 数据传送程序

用下列程序段实现之: MOV SI , OFFSET S1 ; S1 的位移量 ->SI MOV DI , OFFSET S2 ; S2 的位移量 ->DI MOV CX, 30 ; 30->CX NEXT:MOV AL,〔 SI 〕 ; (〔 SI〕 )-〉 AL MOV〔 DI〕, AL ; (AL)-〉〔 DI〕 INC SI ; (SI)+ 1->SI INC DI ; (DI)+ 1->DI DEC CX ; (CX)- 1->CX JNZ NEXT ;不等零时转 NEXT其中, INC 为增量 ( 这里为+ 1),DEC 为减量 ( 这里为- 1)操作符, JNZ 为不等于零时转移指令,这些指令在后面均有介绍。 IBM-PC 机还有专门的控制循环迭代的指令 (即 LOOP指令 ) 。上面程序段中的最后两条指令 DEC CX JNZ NEXT 可以用一条循环迭代指令: LOOP NEXT代替。

Page 10: 第6章 数据传送程序

6.1.2 数据块传送程序实例

以上的程序还仅仅是一个程序段,并不是一个完整的程序。为了使读者了解各种寻址方式的使用方法,下面用各种寻址方式和不同的数据定义来编制数据块传送的完整程序。 例 6 . 1 将以 S1 为起始地址的 30 个字符依次传送到同数据段的以 S2 为起始地址的一片字节存储单元里。方法一:数据块是用 DB 定义的一个字符串 S1 。用变址寄存器间接寻址方式访问 S1和 S2 ,即用〔 SI〕表示

S1 中各字节的位移量,用〔DI〕表示 S2 中各字节的位移量。

Page 11: 第6章 数据传送程序

方法一,完整程序如下:NAME EX6-1-1DATA SEGMENTS1 DB ‘ABCDEFGHIJKLMNOPQRSTUVW′ DB ‘XYZ0123′S2 DB 30 DUP (?)DATA ENDSCODE SEGMENT ASSUME DS:DATA,CS:CODE

START : MOV AX,DATA ;数据段寄存 MOV DS,AX ;器的装填 MOV SI,OFFSET S1 ;S1 的位移量 ->SI MOV DI,OFFSET S2 ;S2 的位移量 ->DI MOV CX,30 ;循环次数 30->CXNEXT : MOV AL,〔SI 〕 ; (〔SI〕 )->AL MOV 〔DI〕,AL ; (AL)->〔DI〕 INC SI ; (SI)+1->SI INC DI ; (DI)+1->DI LOOP NEXT ; (CX)-1->CX, (CX)=0 时转 MOV AH,4CH ;程序结束 INT 21H ;返回系统CODE ENDS END START

DEC CXJNZ NEXT

Page 12: 第6章 数据传送程序

方法二,完整程序如下:NAME EX6-1-1DATA SEGMENTS1 DB ‘ABCDEFGHIJKLMNOPQRSTUVW′ DB ‘XYZ0123′S2 DB 30 DUP (?)DATA ENDSCODE SEGMENT ASSUME DS:DATA,CS:CODE

START : MOV AX,DATA ;数据段寄存 MOV DS,AX ;器的装填 MOV BX,OFFSET S1 ;原 MOV SI,OFFSET S1 MOV SI,0 ;原 MOV DI,OFFSET S2 MOV CX,30 ;循环次数 30->CXNEXT : MOV AL, [BX+SI] ;原mov al,[si] MOV [BX+SI+30] ,AL ;原MOV [DI],AL INC SI ; (SI)+1->SI ;原 (DI)+1->DI LOOP NEXT ; (CX)-1->CX, (CX)=0 时转 MOV AH,4CH ;程序结束 INT 21H ;返回系统CODE ENDS END START

DEC CXJNZ NEXT

Page 13: 第6章 数据传送程序

方法三,完整程序如下:NAME EX6-1-2DATA SEGMENTS1 DB ‘ABCDEFGHIJKLMNOPQRSTUVW′ DB ‘XYZ0123′S2 DB 30 DUP (?)DATA ENDSCODE SEGMENT ASSUME DS:DATA,CS:CODE

START : MOV AX,DATA ;数据段寄存 MOV DS,AX ;器的装填 MOV SI, 0 ; mov si,offset s1 ;mov di,offset s2

MOV CX,30 ;循环次数 30->CXNEXT : MOV AL,S1[SI] ;mov al,[si] MOV S2[SI],AL ; mov [di],al INC SI ; (SI)+1->SI

LOOP NEXT ; (CX)-1->CX, (CX)=0 时转 MOV AH,4CH ;程序结束 INT 21H ;返回系统CODE ENDS END START

DEC CXJNZ NEXT

Page 14: 第6章 数据传送程序

6.2 字符的输入/输出 在上节,我们用各种数据表格及不同的寻址方式实现了 30 个字节的数据块传送。它是用数据定义伪指令给一个数据项分配存储单元,用一个符号名 ( 变量名 ) 与这个存储单元相联系,以便以后访问这个数据项。汇编程序在汇编时给每个数据项分配好存储单元,并把数据存放在这些存储单元里。这种提供已知数据的方法比较适用于有较多的 ( 一批 ) 已知数据的情况。

Page 15: 第6章 数据传送程序

6.2.1 字符的输入 如果程序要对任意数据进行处理,而且数据不是太多时,则可采用在程序运行时从键盘上键入已知数据的方法。在汇编语言中,键盘输入一个字符的方法是:发中断 21H 来请求 DOS 的功能调用,将 AH 中送上功能调用号,键盘输入一个字符的功能调用号是 1( 参见第 14 章 ) 。在程序中需要输入一个字符的地方写上指令: MOV AH, 01H

INT 21H当 CPU 执行到这两条指令时,就等待你键入一个字符,当你键入一个字符后,这个字符的 ASCII 码就存放在 AL 寄存器中。请注意,键入的数据都是一个字符的 ASCII 码 ( 因为多数外部设备都是以 ASCII 码的形式传送数据的 ) 。当你用以上两条指令接受一个字符时,假如你按数字键 4 ,则在 AL 里得到的不是数值 4 ,而是字符′ 4′的 ASCII 码34H。

Page 16: 第6章 数据传送程序

6.2.2 字符的输出 在微处理机上,要想知道程序运行的结果,常用的方法就是在屏幕上显示或在打印机上打印结果。在 IBM-PC 上的宏汇编语言里,要想输出一个字符需要请求 DOS 的功能调用,显示一个字符的功能调用号为02H ,将 02H 送入 AH ,发 21H 类中断,就会在屏幕上的当前位置显示寄存器 DL 中的一字符。因此,事先必须将要显示的字符的 ASCII 码送入 DL 。要想将 DL 中的字符在打印机上输出,就将功能调用号 05H送入 AH ,然后发中断 21H 。此时打印机必须已经准备好 ( 即打印机已加电,并已按 Ctrl+P 键连上了打印机 ) 。例如:要想显示输出 5 ,需要写指令: MOV DL ′, 5′

MOV AH, 02H INT 21H 要想打印输出字符 F ,需要写指令: MOV DL ′, F′ MOV AH, 05H INT 21H

Page 17: 第6章 数据传送程序

需要说明的是,用功能调用号 05H 打印一个字符时,若打印机已准备好,则在打印机上打印字符的同时,也在屏幕上显示这个字符。若打印机没有准备好,则 CPU 执行到 INT 21H 时就处于等待状态,使程序无法继续执行下去。当用功能调用号 02H显示一个字符时,若打印机已经准备好,则在显示字符的同时,在打印机上也打印这个字符,若在显示一个字符时,打印机没有准备好 ( 比如:打印机没有加电,或者没有按 Ctrl+ P 键连上打印机 ) ,则只显示而不打印,程序继续执行。因此,当你需要显示输出一个字符时,只需用功能调用号 02H 。当你需要显示并打印一个字符时,也不要将功能调用号 02H 和功能调用号05H 都写上,因为这样会显示两个同样的字符,二者只需写一个即可。一般亦只需用功能调用号 02H。

Page 18: 第6章 数据传送程序

6.2.3 字符输入/输出程序实例 例 6.2 从键盘上键入 20 个字符,然后以与键入字符的先后相同的顺序显示出来。 为了存放从键盘上键入的字符,我们分配一个 20 个字节的存储器缓冲区,假设这个缓冲区的起始地址名为 DATA 。我们将从键盘上接受来的字符依次存放在这片内存里,然后再从第一个字符开始,依次把它们显示出来。 其完整程序如下:

Page 19: 第6章 数据传送程序

NAME EX6-2DSEG SEGMENT DATA DB 20 DUP(?) ;分配 20 个字节的输入缓冲区DSEG ENDSCSEG SEGMENT ASSUME CS:CSEG,DS:DSEGGO:MOV AX,DSEG MOV DS,AX MOV CX, 20 ; 20->CX MOV SI,OFFSET DATA ;DATA 位移量 ->SIL01:MOV AH, 01H ;键入一个字符 ->AL INT 21H MOV [SI],AL ; (AL)->[SI] INC SI ; (SI)+1->SI LOOP L01 ;循环 20 次 MOV CX, 20 ; 20->CX MOV SI,OFFSET DATA ;DATA 位移量 ->SIL02:MOV DL,[SI ] ; ([SI] )->DL MOV AH, 02H ;显示 (DL) INT 21H INC SI ; (SI)+1->SI LOOP L02 ;循环 20 次 MOV AH, 4CH ;程序运行结束,返回 DOS INT 21HCSEG ENDS END GO

Page 20: 第6章 数据传送程序

6.3 堆栈操作程序

6.3.1 堆栈操作指令1. PUSH 指令 ( 把字推入堆栈 )格式: PUSH 源操作数 ( 字 )功能:首先将栈顶指针减 2 ,即 (SP)-2->SP; 然后将源操作数 ( 字 )->(SP)+1, (SP)。例如: PUSH AX ; (SP)-2->SP 且 (AX)->(SP)+1:(SP)PUSH BX ;将 (BX)推入堆栈PUSH SS ;将 (SS)推入堆栈PUSH CS ;将 (CS)推入堆栈 ( 这是合法的 )PUSH BETA ;将 BETA 存储字的内容推入堆栈PUSH BETA〔 BX〕 ;PUSH BETA〔 BX〕+〔 SI〕 ;

Page 21: 第6章 数据传送程序

2. POP 指令 ( 从堆栈顶弹出一个字 )格式: POP 目的操作数功能:首先把堆栈顶的字 ((SP)+ 1, (SP))-> 目的操作数; 然后将堆栈指针 SP 加 2 ,即 (SP)+ 2->SP。例如:恢复上面程序段保存的寄存器、存储器的内容的程序段为: POP BETA〔 BX〕+〔 SI〕POP BETA〔 BX〕POP BETAPOP A ;注意: POP CS 是非法的POP SSPOP BXPOP AX 堆栈操作指令 PUSH和 POP 的操作示意图如图 6-1 所示。

Page 22: 第6章 数据传送程序

3412

SS

SP

1234H

AX

压栈前 PUSH AX后

SS

SP1234H

AX

SP

1234H

BX

SS

POP BX后

3412

Page 23: 第6章 数据传送程序

需要注意的是: (1) 因为堆栈指针 SP总是指向已经存入数据的栈顶 ( 不是空单元 ) ,所以 PUSH 指令是先将 (SP)减 2 ,后将内容压栈 ( 即先修改 SP使之指向空单元,后压入数 ) ,而 POP 是先从栈顶弹出一个字,后将堆栈指针 SP 加 2 。 (2) PUSH CS 是合法的,但 POP CS 是不合法的。 (3) 因为 SP总是指向栈顶,而用 PUSH和 POP 指令存取数时都是在栈顶进行的,所以堆栈是“先进后出”或叫“后进先出”的。栈底在高地址,堆栈是从高地址向低地址延伸的,所以栈底就是最初的栈顶。 (4) 用 PUSH 指令和 POP 指令时只能按字访问堆栈,不能按字节访问堆栈。 (5) PUSH和 POP 指令都不影响标志。

Page 24: 第6章 数据传送程序

6.3.2 堆 栈 操 作 程 序 实 例

例 6.3 在键盘上输入 50 个字符,然后用与输入字符的先后相反的顺序在屏幕上显示出来。因为堆栈是“后进先出”的,因此,利用堆栈作为输入缓冲区极易实现按逆序输出。 其完整程序如下:NAME EX6-3

Page 25: 第6章 数据传送程序

STACK SEGMENT PARA STACK DW 50 DUP (?)STACKTOP LABEL WORDSTACK ENDSCODE SEGMENT ASSUME CS: CODE, SS: STACKSTART: MOV AX, STACK MOV SS, AX MOV SP,OFFSET STACKTOP MOV CX, 50 ;输入 50 个字符 堆栈 L1 : MOV AH, 01H INT 21H PUSH AX LOOP L1 MOV DL, 0AH ;显示“回车” MOV AH, 02H INT 21H MOV DL, 0DH ;显示“换行” INT 21H MOV CX, 50 ;从栈顶依次弹出 50 个字符输出L2 : POP DX MOV AH, 02H INT 21H LOOP L2 MOV AH, 4CH INT 21H CODE ENDS END START

Page 26: 第6章 数据传送程序

其中,最初的栈顶也可以不用指令送堆栈指针 SP ,即将上面程序中的 STACKTOP LABEL WORD 伪指令和 MOV SP,OFFSET STACKTOP 指令去掉,程序照样正确运行。因为只要在堆栈段的 SEGMENT伪指令中带有组合类型参数和组名参数:STACK ′STACK′ , 汇编程序会就自动把栈底 ( 也是最初的栈顶 ) 的位移量赋给堆栈指针 SP。 如果键入的字符为′ A′ ′, B′ … ′, , 8′ ′, 9′ 等 50 个字符,栈中的内容如图 6-2 所示 ( 见书 P121)。在图 6-2 中, SP0 指向的是栈底,也是最初的栈顶。 SPi 为第 i个字符键入后 PUSH 指令执行完后栈顶的位置 ( 即堆栈指针 SP 指向的位置 ) 。当执行 POP 指令时,是按 SP50, SP49,…, SP2, SP1 所指向的字顺序弹出的。

Page 27: 第6章 数据传送程序

6.4 数据交换程序 6.4.1 数据交换指令

XCHG 指令 ( 字节或字交换 )格式: XCHG 目的操作数,源操作数功能:将源操作数和目的操作数相互交换 ( 字节或字 ) 。此指令可以实现通用寄存器、累加器或存储器之间的相互交换。但是两个操作数中要求至少有一个通用寄存器。因此, XCHG 指令不能直接实现两个存储器单元的内容交换。XCHG 指令举例:

XCHG AX,BX ;AX与BX 寄存器内容交换XCHG SI,AX ;SI与AX内容交换XCHG AL,BL ;AL与BL内容交换

XCHG WORD-VAR,CX; 变量 WORD-VAR与CX 寄存器内容交换XCHG DH,BYTE-VAR ;DH 与变量 BYTE-VAR内容交换

Page 28: 第6章 数据传送程序

请注意:(1) XCHG 指令不影响状态标志。(2) 段寄存器不能作为 XCHG 指令的操作数。若要进行存储器 ( 字 ) 变量 A 和存储器 ( 字 ) 变量 B 的内容交换,可以用以下几条指令实现:MOV AX,BXCHG AX,AMOV B,AX 如果只用 MOV 指令则需要用四条指令占用两个通用寄存器才能实现:MOV AX,AMOV BX, BMOV A,BXMOV B,AX 另外利用堆栈交换存储器变量 A 和 B 的内容也是很方便的。利用下列四条指令即可实现 PUSH APUSH BPOP APOP B 以上四条指令之所以能实现 A 与 B 内容交换,是由于用 PUSH和POP 指令访问堆栈总是在栈顶进行的,也就是说,堆栈是“先进后出”的。

Page 29: 第6章 数据传送程序

6.4.2 数据交换程序实例 例 6.4 将 S1串与 S2串交换 ,其实现程序如下:

Page 30: 第6章 数据传送程序

DATA SEGMENT S1 DB ′ABCDEFG′ S2 DB ′0123456′ N DW $-OFFSET S2 ; N 为字符串长度DATA ENDSCODE SEGMENT ASSUME CS: CODE,DS:DATASTART:MOV AX,DATA ;DATA 段基址 DS MOV DS, AX MOV SI, 0 ; 0 SI MOV CX,N ;字符个数 CXL1 : MOV AL, S1〔 SI 〕 ; (S1〔 SI〕 ) 与 (S2〔 SI〕 ) 交换

XCHG AL, S2〔 SI〕MOV S1〔 SI〕, ALINC SI ; (SI)+ 1 SI LOOP L1 ;循环 N 次否 ?MOV CX,N ;显示 S1串MOV SI, 0MOV AH, 02H

L2 : MOV DL, S1〔 SI〕INT 21HINC SILOOP L2MOV DL ′ ′ , ;显示空格INT 21HMOV CX,N ;显示 S2串MOV SI, 0

L3 : MOV DL, S2〔 SI〕INT 21HINC SILOOP L3MOV AH, 4CHINT 21H

CODE ENDS END START

Page 31: 第6章 数据传送程序

6.5 端口输入/输出程序 6.5.1 端口输入/输出指令

IN/OUT 指令 ( 输入/输出指令 )8086 / 8088的输入/输出是一种专用的端口寻址的输入/输出方式 (非存储器对应方式 ) ,故有专门 I/O 指令。 8086 / 8088的 I/ O 指令有两种寻址方式:直接寻址方式和间接寻址方式。直接寻址的 I/ O 指令格式为:IN AL, nIN AX, nOUT n,ALOUT n,AX 其中, n 为 8位端口地址,故可寻址 256个 I/O 端口。间接寻址的 I/ O 指令格式为: IN AL,DXIN AX, DXOUT DX,ALOUT DX,AX

Page 32: 第6章 数据传送程序

这类 I/ O 指令的 I/ O 端口地址包含在 DX 中,即为 16 位地址。因此,可访问的 I/ O 端口地址空间最大可达 64K 个。IN 指令功能: 把一个字节或一个字由一个输入端口 ( 即指令中的 n 或DX) ,传送到AL或 AX。OUT 指令功能: 把在 AL 中的一个字节或在 AX 中的一个字传送至一个输出端口 ( 指令中的 n 或DX)。

例如: IN AL, 2FH ;从端口 2FH 输入一个字节, ALOUT 5, AL ;将 (AL) 输出到端口 5MOV DX, 3FCH ;将端口地址 3FCHDXIN AX,DX ;从端口 3FCH 输入一个字 AX

Page 33: 第6章 数据传送程序

6.5.2 端口输 入 / 输 出 程 序 实 例

由于端口输入/输出程序涉及很多硬件知识,因此这里只给出程序实例而不做解释。有关 I/ O 指令的应用,本书将在后面再详细介绍。

例 6.5 对 8235 定时器和 8255 可编程控制器接口芯片进行编程,让扬声器发出 600周的声音。其实现程序如下:

Page 34: 第6章 数据传送程序

· MODEL SMALL·DATA FRED DW 1988·CODE START: MOV AX,@DATAMOV DS,AXIN AL , 61HOR AL, 3HOUT 61H,ALMOV AL, 0B6HOUT 43H,ALMOV BX, FREDMOV AL,BLOUT 42H,ALMOV AL,BHOUT 42H,ALMOV AH, 0INT 16HIN AL, 61HAND AL, 0FCHOUT 61H,ALMOV AH, 4CHINT 21H END START

Page 35: 第6章 数据传送程序

6.5.3 对 I/O 接口芯片编程 见 p365 16.4 对 I/ O 接口芯片的编程 由第 15章大家知道,用户汇编程序截至目前为止,已有两种手段,或两个层次,或是两个界面来实现 I/ O 。其中一种是 DOS 功能调用 ,另一 种 是 BIOS 功 能调用 ,二者相比, DOS 功能调用处于外层,而 BIOS 功能调用处于内层。作为一般用户仅需 DOS 功能调用就可以了,进一步是 BIOS 功能调用。

Page 36: 第6章 数据传送程序

然而对于系统软件工作者则仅有这些还是不够的,因为他们要剖析 ROM—BIOS 的程序,要剖析 DOS系统程序,甚至进一步要改进 DOS 之结构,或是 BIOS 之功能,例如在 PC—DOS 上进行二次开发使其具有汉字功能,编制实时控制程序等等。要做到这一切就必须深入了解最内层的 I/ O控制或编程,但这要涉及到具体微机的硬件接口,因此我们不可能以一节的篇幅将其彻底阐述清楚。但是我们可以从一孔而观全局,对其全貌有一概括的了解,为以后深入学习打下一个基础,并在必要时能够知道从何处入手再行深造。

Page 37: 第6章 数据传送程序

16.4.1 与 8088配套的主要芯片简介 8088是 IBM PC 微机的心脏或大脑,然而仅有一个 8088 微处理器是不能构成硬件系统的,还必须有其它接口芯片的支持,这些芯片有些也是微处理器, 8088可以通过端口对其编程,以及通过端口读取必须的信息,实现对它们的控制和协调各部分的工作。在 DOS 下这些工作是由初始化程序或 DOS 内部程序,进而通过 BIOS 程序去进行的,用户是通过 DOS或BIOS 的功能调用间接进行干预的。这里则不然,我们将通过对主要配套的芯片的简介,通过使用 OUT和 IN 指令对典型芯片的编程来进一步了解最内层的 I/ O控制。

Page 38: 第6章 数据传送程序

1主机与外设交换信息的方式 (1) DMA 方式 ( 直接存储器访问 ) 系统板以 8237DMA 控制器芯片提供DMA 机构,其主要用于存储器刷新等。该片有四个 DMA 通道,可编程四个独立的 DMA 操作,由于其繁杂性,详细情况请查阅8237DMA之 Intel产品说明书。 在该方式下数据不必经累加器和端口与外设传递,而是通过快速直接传递的方式进行的。但是对其控制方式也是由端口对其编程实现的。

Page 39: 第6章 数据传送程序

(2) 其它方式 (查询和中断方式 ) 查询方式,接口电路中有 I/O 设备的工作状态′忙′,′闲′,及缓冲器的′满′、′空′状态, CPU 通过

AL(或 AX) ,进而通过端口对其不断地查询指挥其工作。 中断方式, CPU 不必定时查询 I/O 设备的状态 ,而是通过 AL(或 AX) 进而通过端口直接下达命令和工作方式 ( 编程 ) ,一旦 I/O 片接收了此信息,则由 I/O 接口芯片来控制相应 I/O 设备的 I/O ,只是在工作完成或是遇到紧急情况 (特殊条件产生 )才通过发中断信号的方式,请求 CPU干预。

综上所述, CPU 是通过端口与接口芯片通讯以达到下达任务、查询和传递信息的目的。

Page 40: 第6章 数据传送程序

存储器 微处理器 输入 /输出系统

总线

动态RAM(DRAM)静态RAM(SRAM)高速缓冲只读存储器闪速存储器

80868088802868038680486Pentium

打印机串行通信设备软盘驱动器硬盘驱动器鼠标CD-ROM驱动器绘图仪键盘视频监视器磁带机基于微处理器的个人计算机

Page 41: 第6章 数据传送程序

系统区384K 字节

TPA640K 字节

扩展存储区

8086~80486或 Pentium 中1M 字节存储器(可包括扩充存储器)

在 80286 或 80386SX 中为 15M 字节在 80386SL 中为 31M 字节在 80386DX、 80486、 Pentium中为 4096M 字节

个人计算机存储器映像

Page 42: 第6章 数据传送程序

08E3008E2F084900848F

025300252F

011600115F00700006FF00500004FF00400003FF

00000

COMMAND.COM

驱动程序(MOUSE.SYS) (ANSI.SYS)

MSDOS 程序

IO.SYS

DOS 通信区

BIOS 通信区

中断向量区

MSDOS 程序

空隙 TPA

9FFFF9FFF09FFEF

DOS TPA 的存储器映像,这个映像图根据DOS版本的不同而不同也随着驱动程序和配置情况的差异而改变

Page 43: 第6章 数据传送程序

硬盘

COM2

8255( PPI)

定时器

中断控制器

DMA控制器

03780377

0330032F

0320031F

030002FF

02F802F7

00640063

0060005F

00440043

0040003F

00240023

0020001F

0010000F

0000

050004FF

040003FF

03F803F7

03F003EF

03E003DF

03D003CF

0380037F

03780377

COM1

软盘

CGA 适配器

LPT1

I/O扩充区 FFFF

个人计算机的I/O

映像

Page 44: 第6章 数据传送程序
Page 45: 第6章 数据传送程序

2几种典型的接口芯片 (1) 8259中断控制器 它提供两个端口, 20H和 21H ,其中 20H对应中断命令寄存器,由其对8259编程。 21H对应中断屏蔽寄存器。 8259能接受8个独立的硬件中断信号,编号0~7,号数小的级别最高, DIOS 在系统初始化时已对其编程使其对应中断类型 08H~ 0FH ,其含义见第14章。用户通过端口21H可以设置对应编号的中断信号的屏蔽位。 (屏蔽寄存器 0~7位置时屏蔽相应编号的中断信号 ) 中断信号的发送关系如图 16-3 所示。例如当定时器发出中断信号时,如果 IMR 位的值为 0的话,而且是在开中断的情况下 (1F=1),CPU才接受中断信号,并转入中断处理。

Page 46: 第6章 数据传送程序

IRQ7 IRQ6 IRQ5 IRQ4 IRQ3 IRQ2 IRQ1 IRQ00FH类中断

0EH类中断0DH类中断

0CH类中断0BH类中断

0AH类中断09H类中断

08H类中断定时器中断

键盘中断彩色图像中断未用串行口中断

未用软盘中断

打印机中断

8259A 标准中断

口地址 20-23H 20H 命令口 21H 中断屏蔽寄存器

Page 47: 第6章 数据传送程序

开 /关中断信号

CPU

定时器76543210 屏蔽寄存器

0位7位

CPU 中断型号

Page 48: 第6章 数据传送程序

中断处理应遵循如下原则 ·保护现场 (关中断状态 ) ·屏蔽低级中断 (关中断状态 ) ·中断处理 ( 开中断状态 ) ·恢复现场 (关中断状态 ) ·向中断命令寄存器发中断结束命令。 例如发 EQI( 中断结束 )命令 … MOV AL, 20H OUT 20H, AL … 例如禁止除键盘外一切中断 … MOV AL, 0FDH OUT 21H, AL …

中断处理应遵循如下原则

Page 49: 第6章 数据传送程序

(2) 8255 可编程通用 I/O芯片 它用于系统板配置主持各种设备和信号,如键盘、扬声器、配置开关和若干其它信号。该片对应 4个 I/O口。其中 61H为输出端口 PB, 60H 和 62H是两个输入端口,分别称 PA和 PC口, 63H对应单字节的命令寄存器。其端口分配见图 16-4。 PC 加电后, BIOS发送 99H给 63H端口将该芯片初始化。可利用 PB口给定位置 1 的方法选择 PA和 PC 的交替输入。利用 PB口可读到曾写入 PB口的当前值。 当 PB口位 7=0 时,从 PA口输入的是键盘扫描码。当

PB口位 7=1 时,从 PA口输入的是由系统开关 1 , 2 反映的系统配置状态。其中位 7~ 6表示开关 1 的 8~ 7位,它指明了驱动器个数。其中位 6~5,表示开关 1的 6~5位,指明了显示器的类型。其中位 4~ 3对应开关 1 的 4~ 3 ,表示系统板上的 RAM 数。第2位未用。第 1 位对应开关 1 的位 1表示非磁盘系统。

Page 50: 第6章 数据传送程序

7 6 5 4 3 2 1 0 键盘扫描码输入口PA(60H)若 PB 位 7=0

输入口PA(60H)若 PB 位 7=1

7 6 5 4 3 2 1 0 配置开关 1SW1-1 非磁盘系统SW1-2 未用

SW1-3SW1-4 系统板上 RAM

SW1-6 SW1-5显示类型

SW1-8 SW1-7 驱动器数

8255 的端口分配 PA口( 60H)输入口

Page 51: 第6章 数据传送程序

输入口PA(60H)

输入口PB(61H)

7 6 5 4 3 2 1 0

定时器门 2扬声器数据

PC 位0-3 选源盒式机马达容许扩展 容许RAM

PA选源 1 键盘肯定0 禁止键盘

Page 52: 第6章 数据传送程序

输出口PB(61H)

输出口PC(62H)

7 6 5 4 3 2 1 0

SW2-1SW2-2

SW2-3SW2-4

盒式带数据输入

1=奇偶错定时器 2输出

1=扩展槽错

若 PB 位 2=1扩充槽上 RAM总数

Page 53: 第6章 数据传送程序

输出口 PB 的 0~2位为 1 分别表示定时器 2的门选通,扬声器数据选通, PC口位 0~ 3 的选源; PB口位 3~ 6置 0 分别表示开盒式磁带机马达,允许 RAM ,允许由扩展槽发错误信号,禁止键盘中断。而 PB口位 7则用以 PA口输入时选源。用来给键盘发肯定信号。注意当 PB口位 7为 0 ,且位 6 为 1 ,按或放开键的产生键盘中断。而一个键按下或放开由位 7为 1 或 0区分。 PC口 62H ,位 7~ 4置 1 分别表示奇偶错,扩充槽错,定时器 2的输出,盒式磁带机的输入。位 3~ 0视 PB口位 2为 1 或 0 而定,当 PB口位 2为 1 时, PC口位 0~ 3 分别表示系统板开关上的 1~4位,指出扩展槽上 RAM总数。当PB口位 2为 0 时, PC口位 0~ 3 分别对应系统板开关2的 5~ 8位,表示备用。

Page 54: 第6章 数据传送程序

例如读系统板配置开关 1 所给出的驱动器个数 … IN AL, 61H ;读 PB口当前值 OR AL, 080H; (AL)∧80H ,强迫位 7为 1 OUT 61H, AL; PB口位 7 置 1 ,使PA 为开关 1 开门 IN AL, 60H ;读 PA口,即得开关 1 状态 NOT AL ; AL 各位取反 MOV CL, 6 ;置移位置 SHR AL , CL ;右移 6 位前面补 0 ,(AL) 现为驱动器数 …

Page 55: 第6章 数据传送程序

(3) 8253 定时器 用以完成不同的定时 /计数功能。它有 3 个通道分别对应端口 40H, 41H, 42H。 每一通道均可通过 43H 端口编程,使其工作在 0~ 5六种方式之一。 0 # 通道用以产生定时器中断 1 # 用以发数据请求供 DMA 存储器刷新 2 # 到扬声器产生声音效果,由 8255PC口可取样。

Page 56: 第6章 数据传送程序

MSB LSB

MSB LSB输出2(OUT2)

时钟 2(CLOCK2)

8253 定时器2#通道端口 42H

锁存器

Page 57: 第6章 数据传送程序

每一通道包括一个 16 位计数器和一个 16 位锁定寄存器 (刷新前不变 ) 。 编程时将一计数值送给锁定寄存器,然后传给计数器,每输入一脉冲计数减 1 ,减到 0 时发一信号。 43H端口对应命令寄存器,其各位含义如下: 位 7 ~ 6 指出要编程的通道 00 , 01 , 10 分别对应 0 # , 1 # , 2 # 通道。 位 5 ~ 4表示读写方式, 00表示锁定当前计数器值, 0 表示只读 / 写 MSB , 10 表示只读 / 写

LSB , 11 表 示 先 读 / 写 LSB , 后MSB(LSB,MSB 各占8位 ) 。

位 3~ 1表示 6 种方式 位 0表示计数器计数方式,为 0 为二进制方式,为1为 BCD 码计数方式。

Page 58: 第6章 数据传送程序

MSB LSB

MSB LSB输出2(OUT2)

时钟 2(CLOCK2)

8253 定时器2#通道端口 42H

锁存器

Page 59: 第6章 数据传送程序

例如对 2 # 通道编程使其用方式 5 ,先 LSB后MSB, BCD 码计数 …

MOV AL, 0BBH ;选 2 号通道,方式 5, ;先 LSB后MSB, BCD 计数OUT 43H, ALMOV AL, 60H;OUT 42H, AL; 60H送 LSBMOV AL, 0H;OUT 42H, AL; 0H送MSB

Page 60: 第6章 数据传送程序

(4) 6845CRT 控制器 从本处开始将不再详细介绍该接口的细节,读者可参考 IBM PC 硬件手册。 6845CRT 控制器是一很复杂的芯片,加电后,由系统初始化,初始化后编程较容易。它对应两个端口, 3B4H口端口供选择 CRT芯片内部的寄存器,在访问 3B5H端口时,必须先通过

3B4H口选择内部 15个寄存器之一。 它支持 16KB 字符存储器,通过 0~ 15寄存器选址等功能。 (5) 彩色 /图形适配器 单色有 4KB 存储器,从 0B00H 开始,而彩色有 16KB 存储器从 0B800H 开始。对彩色显示6845之端口地址为 3D4H, 3D5H ,而增加

3D9H供选色用。

Page 61: 第6章 数据传送程序

(6) 打印机适配器单 色 显 示 器 打 印 机 适 配 器 , 端 口 3个, 3BCH 作为输出数据口, 3BEH 为控制口, 3BDH 为输入状态口。并行打印适配器 I/O口地址, 378H 输出数据, 37AH 输出控制, 379H输入状态。 (7) 异步通讯适配器 8250芯片端口地址 3F8H~ 3FEH。

Page 62: 第6章 数据传送程序

16.5 综合例 例 16.3 用 8255和 8258编程,使扬声器发出 600周的可听频率,击任一键停止。 这里应注意到:主钟 1.19318 兆赫,一个时钟周期约为 888.2299×10-9秒。 8253 定时器在方式 3 可产生方波, 600赫应为 1/600÷(888.2229×10-9)=1989。若定时器通道2有输出 ,可在 8255PB口 (6

1H)第 0 位第 1 位为 1 时向扬声器输出方波经扬声器后平滑,产生方波另有它法 (略 ) 。 源程序 ex16-3.asm

Page 63: 第6章 数据传送程序

STACK SEGMENT PARA STACK ′STACK′ DB 256 DUP (0)STACK ENDS

DATA SEGMENT PARA PUBLIC ′DATA′FREG DW 1989; 600周方波计数值DATA ENDS

CODE SEGMENT PARA PUBLIC′CODE′START PROC FAR

ASSUME CS:CODEPUSH DS

MOV AX, 0PUSH AX

MOV AX DATA

MOV DS, AX

ASSUME DS: DATA

Page 64: 第6章 数据传送程序

IN AL, 61H ;读 PB口现状OR AL, 3 ;为置 PB口 0 位 1 位为 1OUT 61H, AL ;开扬声器数据和定时器门迭通 2MOV AL, 0B6H ;先 LSB后MSB ,二进制计数方式OUT 43H, AL ;向8253 发命令MOV BX, FREG ;取计数值MOV AL, BL ;先发 LSBOUT 42H, AL ;给锁存器MOV AL, BH ;后发 MSBOUT 42H, AL ;给锁存器MOV AH, 0 ;读功能号INT 16H ; BIOS 键盘功能调用,等击键继续IN AL, 61H ;读 PB口当前值AND AL, 0FCH ;关扬声器数据和定时器门迭通 2信号OUT 61H, AL ;新写 PB口RET ;返回 DOS START ENDPCODE ENDS END START

Page 65: 第6章 数据传送程序

例 16.4 用汇编语言发声和唱歌 1 如何编写唱歌程序 用汇编语言编程 8253 定时器和 8255可编程程序控制器可以让扬声器发声,由于涉及到端口编程较为复杂,我们这里只介绍使用,而不涉及原理。 例 16.4 编程序让计算机演奏“亚洲雄风”这首歌曲。

Page 66: 第6章 数据传送程序

声音的生成(1) 发出指定频率的声音 声音的生成可以通过编程 8253 定时器和 8255可编程控制器实现。方法是首先编程 8253 定时器通道2让其按方式 3工作。即通过指令 MOV AL, 0B6H OUT 43H, AL 实现。接着应向 42H 口送入发出频率对应的计数值,即 MOV AL ,计数值低位 OUT 42H, AL MOV AL ,计数值高位 OUT 42H, AL

Page 67: 第6章 数据传送程序

然后通过 8255 打开扬声器的门即可发出该频率的声音。即 IN AL, 61H MOV AH, AL OR AL, 3 OUT 61H, AL 该频率的声音持续多长时间取决于开扬声器的 门 到关扬声器 门 间 的 时 间 。 详见过 程

SOUND。

Page 68: 第6章 数据传送程序

8253 定时器通道2频率与计数值间的对应关系。时钟频率÷发生频率 =送给 8253 定时器的计数值。当时钟频率为 1193180 时即 1234DCH 时,若给定声音频率存放在 DI 中,则该计数值应为: MOV DX, 12H MOV AX, 34DCH DIV DI这时计数值应在 AX 中,然后分别按低字节高字节送往 42H 口即可。

Page 69: 第6章 数据传送程序

(2) 延时

当时钟为 1193180周时,延时 10毫秒可由:

MOV CX, 2801 DL10ms:LOOP DL10ms实现,当时钟频率高时,用户可自行计算。

Page 70: 第6章 数据传送程序

(3) 音符与频率 音符与频率 音符与频率有如下对应关系: 音符 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 频率 131 147 165 175 196 220 247 262 294 330 349 392 440 496 523 节拍:一拍 250毫秒,半拍 125毫秒。以 10毫秒为单位则分别对应 25 和 12 。这样我们可将“亚洲雄风”的音符所对应的频率放在一张表 FREQ 中,将音符所对应的节拍放在另一张表 TIME 中,然后通过主程序逐一按音符频率和节拍值让扬声器发声,直到遇到音符对应频率计数值为 0 为止。

Page 71: 第6章 数据传送程序

2.演奏亚洲雄风实例 其中子程序 SOUND 为让扬声器发出由

DI 指定的频率, BX 指定的节拍的声音。SING 子程序为调用 SOUND 子程序发出的 SI 指向频率表, BP 指向节拍表对应的歌曲,其中频率表以 0 为结束符。主程序 STAT将 SI 指向频率表, BP 指向节拍表调用 SING子程序唱歌。

Page 72: 第6章 数据传送程序

STACK SEGMENT DW 100 DUP(?)STACK ENDSDATA SEGMENTBG DB 0AH,0DH ″, YA ZHOU XUN FEN:$″FREQ DW 263,196,263,294,330,263,263,392,262,330,294,262,294DW 263, 196, 263,294, 330,263, 263, 440,262, 330,294, 262, 294, 392DW 263, 196, 263,294, 330,263, 263, 392,262, 330,294, 262, 294DW 263, 196, 263,294, 330,263, 220, 262,440, 292,392, 392DW 392, 262, 392,392, 349,349, 330, 262,392, 262,294, 330DW 392, 523, 392,392, 440,440, 392, 349,330, 262,294, 294, 262DW 392, 392, 392,262, 440,392, ,392,349, 392,330, 262, 392,262, 294DW

392,392, 392, 262, 392, 440,440, 440, 392, 349, 330,262, 294, 294, 262

DW 0 TIME DW 50,25,25,18,7,50,25,25,25,25,18,7,100 DW 50, 25,25, 18, 7, 50,25, 25, 25,25,18, 7, 25,75 DW 50, 25, 25, 18, 7, 50,25,25,25,18,7,100 DW 50, 25 , 18, 7, 75, 25,25, 13, 25, 12,100 DW 50, 25, 25,13, 12, 75,25, 25, 25, 18,7, 100 DW 50, 25, 25,13, 12, 50,13, 12, 25, 25,25, 13, 112 DW 25, 25, 13,37, 13, 25,62, 25, 25, 25,25, 25, 13, 62 DW 25, 25, 13,37, 13, 25,12, 25, 13, 12,25, 25, 25, 13,112

DATA ENDS

Page 73: 第6章 数据传送程序

CODE SEGMENT ASSUME CS: CODE ,DS:DATASTAT PROC FARPUSH DSMOV AX, 0PUSH AXMOV AX,DATAMOV DS, AXMOV DX,OFFSET BGMOV AH, 09INT 21HMOV SI ,OFFSET FREQMOV BP ,OFFSET TIMECALL SINGRET STAT ENDP

Page 74: 第6章 数据传送程序

SING PROC NEARPUSH DIPUSH SIPUSH BPPUSH BX REPT1 : MOV DI,[ SI CMP DI, 0JE ENDSINGMOV BX,DS:[ BP]CALL SOUNDADD SI , 2ADD BP , 2JMP REPT1 ENDSING: POP BXPOP BPPOP SIPOP DIRET SING ENDP

Page 75: 第6章 数据传送程序

SOUND PROC NEARPUSH AXPUSH BXPUSH CXPUSH DXPUSH DIMOV AL,0B6HOUT 43H,ALMOV DX,12HMOV AX, 34DCHDIV DIOUT 42H,ALMOV AL,AHOUT 42H,ALIN AL, 61HMOV AH,ALOR AL, 3OUT 61H,AL DELAY : MOV CX,2801DL10: LOOP DL10DEC BXJNZ DELAY

Page 76: 第6章 数据传送程序

MOV AL, AH

OUT 61H, ALPOP DIPOP DX

POP CX

POP BX

POP AX

RET SOUND ENDP

CODE ENDS

END STAT

Page 77: 第6章 数据传送程序

发声另有他法 看一段程序

IN AL,61HAND AL,0FCH

L: XOR AL,2OUT 61H,ALMOV CX,140H

NEXT: LOOP NEXTJMP L

输入口PA(60H)

输入口PB(61H)

7 6 5 4 3 2 1 0

定时器门 2扬声器数据

PC 位0-3 选源盒式机马达容许扩展 容许RAM

PA选源

Page 78: 第6章 数据传送程序

6.6 换码程序 6.6.1 换码指令

XLAT 指令 (换码 )格式: XLAT换码表功能:用换码表中的一个字节 (称为换码字节 ) 来置换累加器 AL 中的内容。要求在此指令之前,寄存器 AL 的内容为要换码的字节在换码表中的下标 (距换码表的起始地址的位移量 ) ,换码表的起始地址在 BX 中。 XLAT 指令执行后,用以 BX 为基点、AL 为位移的表中的字节置换AL 中的内容。即: (〔BX〕+ (AL))->AL。要求换码表长度不得超过 256 个字节。此指令的操作如图 6-3 所示。

Page 79: 第6章 数据传送程序

问题:已知一个汉字的电报码由四位数字组成,现在已经知道有一种简单加密方法是利用如下对应关系进行加密。 原码 0 、 1 、 2、 3 、 4、 5、 6 、 7、 8、9分别对应密码 3 、 7、 4、 2、 1 、 0 、 5、9、 8、 6(当然也可以是其他一一对应关系)。现在编写一个程序从键盘读入 4位原码,然后输出其相应密码。例如输入 9357,输出应该为 6209。

Page 80: 第6章 数据传送程序

0 1 2 3 4 5 6 7 8 93 7 4 2 1 0 5 9 8 6

DS:BX指向

第一个原码 9送 AL

执行 XLAT 后第一个密码 6送 AL

Page 81: 第6章 数据传送程序

0 1 2 3 4 5 6 7 8 93 7 4 2 1 0 5 9 8 6

DS:BX指向

第二个原码 3送 AL

执行 XLAT 后第二个密码 2送 AL

Page 82: 第6章 数据传送程序

0 1 2 3 4 5 6 7 8 93 7 4 2 1 0 5 9 8 6

DS:BX指向

第三个原码 5送 AL

执行 XLAT 后第三个密码 0送 AL

Page 83: 第6章 数据传送程序

0 1 2 3 4 5 6 7 8 93 7 4 2 1 0 5 9 8 6

DS:BX指向

第四个原码 7送 AL

执行 XLAT 后第四个密码 9送 AL

Page 84: 第6章 数据传送程序

源程序.MODEL SMALL.DATA MIMAB DB ‘3742105986’ MIMA DB 4 DUP(?).CODE BEGIN: MOV AX,@DATA MOV DS,AX MOV CX,4 LEA BX,MIMAB LEA SI,MIMANEXT: MOV AH,1 INT 21H AND AL,0FH XLAT MIMAB MOV [SI],AL INC SI LOOP NEXT

Page 85: 第6章 数据传送程序

MOV CX,4 LEA SI,MIMA MOV AH,2 MOV DL,0DH INT 21H MOV DL,0AH INT 21HNEXT2: MOV AL,[SI] MOV DL,AL INT 21H LOOP NEXT2 MOV AH,4CH INT 21H END BEGIN

Page 86: 第6章 数据传送程序
Page 87: 第6章 数据传送程序

6.6.2 换码程序实例例 6.6 利用 XLAT 指令将二进制表示的十六进制数字转换成ASCII 码再显示出来。根据题意,需要在数据段中定义一个换码表,就是 0 , 1 ,…, 16所对应的 ASCII 码表:TABDA DB 30H, 31H, 32H, 33H, 34H, 35HDB 36H, 37H, 38H, 39H, 41H, 42H 或简写成: DB 43H, 44H, 45H, 46TABDA DB ‘0123456789ABCDEF’在代码段中,若想利用 XLAT 指令将 AL 中的十六进制数字 ( 比如AL=0CH) 转换成对应的 ASCII 码,需写如下指令:MOV BX,OFFSET TABDAMOV AL, 0CHXLAT TABDA 为了在 AL 中能得到 0 , 1 , 2 ,…, 9A …, , F 数字,亦需要在数据段中将它们依次存放在以 TABHEX 为起始地址的连续的一片内存中。为了清晰起见,每显示一个十六进制数码后显示一个空格。

Page 88: 第6章 数据传送程序

其完整程序如下:NAME EX6-6TABLE SEGMENTTABDA DB 30H,31H,32H,33H,34HDB 35H,36H,37H,38H,39HDB 41H,42H,43H,44H,45H,46HTABHEX DB 0,1,2,3,4,5,6,7,8,9DB 0AH,0BH,0CH,0DH,0EH,0FH TABLE ENDSCOSEG SEGMENT ASSUME CS:COSEG,DS: TABLESTART:MOV AX, TABLEMOV DS,AXMOV CX,10HMOV BX,OFFSET TABDAMOV SI,OFFSET TABHEX NEXT : MOV AL,〔SI XLAT TABDA ;换码: (〔BX〕+ (AL))AL MOV DL,AL MOV AH,02H INT 21H MOV DL,00H ;空白ASCII 码 DL MOV AH,02H INT 21H ;显示空白 INC SI LOOP NEXT MOV AH,4CH INT 21HCOSEG ENDS END START

Page 89: 第6章 数据传送程序
Page 90: 第6章 数据传送程序

需要注意的是:由于外设多数都是用 ASCII码传送的,因此,十六进制数字不能直接在屏幕上显示出来,必须将数字转换成其对应的ASCII 码才能正确地将数字显示出来。

Page 91: 第6章 数据传送程序

6.7 其它传送指令

6.7.1 地址目标传送指令1.LEA 指令 ( 有效地址 寄存器 )格式: LEA 目的操作数,源操作数其中,目的操作数为 16 位的通用寄存器 (即AX, BX, CX,DX, SP, BP, SI,DI 之一 ) ;源操作数是变量、标号或地址表达式。功能:把源操作数的有效地址传送至目的操作数寄存器。例如:LEA BX,VAR 1 ;变量 VAR 1 的位移量 BXLEA DX, BETA〔 BX〕〔 SI 〕 ;将数组元素的位移量 DXLEA AX,〔 BP〕〔DI 〕 ;将位移量 (BP)+ (DI) AX

Page 92: 第6章 数据传送程序

需要说明的是:(1) LEA 指令是处理变量的地址 ( 即变量的位移量 ) ,而不是变量的内容 ( 即变量的值 ) 。(2) LEA 指令和 MOV 指令的区别:MOV 指令传送有效地址 ( 位移量 ) 时,必须用 OFFSET 操作符作用于变量才行,否则,在 MOV 指令中用变量名作源操作数,就会传送变量的值。例如: MOV BX,OFFSET VARA ;将变量 VARA 的位移量 BXMOV BX, VARA ;将变量 VARA 的值 BX

Page 93: 第6章 数据传送程序

而用 LEA 指令传送有效地址时,不必用 OFFSET 操作符。上面的例: MOV BX,OFFSET VAR A等效于: LEA BX, VAR A另外, LEA 指令的源操作数可以带下标,即 LEA 指令可以传送任意数组元素的位移量。例如上面例子中的指令: LEA DX, BETA〔 BX〕〔 SI〕是将数组元素 BETA〔 BX〕〔 SI〕的位移量传送至DX 而MOV 指令用 OFFSET 操作符则不能直接取数组元素的位移量,只能取数组的第一个元素的位移量 ( 即数组的起始地址 ) 。(3) LEA 指令的源操作数必须是存储器操作数。(4) LEA 指令不影响状态标志。

Page 94: 第6章 数据传送程序

2LDS 指令 (双字指针 寄存器和 DS)格式: LDS 目的操作数,源操作数目的操作数为 16 位的通用寄存器之一,源操作数是双字长存储器指针。功能:将双字长源操作数的低地址中的字 ( 变量或标号在它所在段的位移量 ) 传送给目的寄存器;将双字长源操作数的高地址中的字 ( 变量或标号所在段的基址 ) 传送至DS 寄存器。例如:数据的定义为: B DB ′F′ A DD B其中, A 为双字指针变量,它的低位字中为 B 的位移量,高位字中为 B 变量所在段的基址。

Page 95: 第6章 数据传送程序

若写指令: LDS BX, A ;将 B 的位移量 ->BX,将 B 所在段基址 DS MOV AL,〔 BX 〕 ;将′ F′ 送至 AL这里指令 LDS BX, A 的操作图如图 6-4 所示。LDS 指令的源操作数也可带下标。例如: LDS BX, ADDR TABLE〔 SI〕LDS SI,NEWSEG〔 BX 〕 3.LES 指令 (双字指针 寄存器和 ES)除了把双字指针中的段基址传送至 ES 段寄存器,而不是传送至DS 外,其它与 LDS 指令完全相同。

Page 96: 第6章 数据传送程序

6.7.2 标示寄存器传送指令

1. LAHF 指令 ( 状态标志字节装入 AH)格式: LAHF( 无操作数 )功能:将标志寄存器的状态标志: SF, ZF,AF, PF, CF 位传送至AH 寄存器的对应位, AH 寄存器其余三位内容不变,其操作如图 6-5 所示。其中, AH 中带“ X” 的三位保持原内容不变。2. SAHF 指令 ( 将 (AH) 存入状态标志寄存器 )格式: SAHF( 无操作数 )功能: AH 的指定位 ( 与状态标志对应的位 ) 传送至标志寄存器 ( 即与LAHF 指令传送方向相反 ) 。其操作如图 6-6 所示。3. PUSHF 指令 ( 将标志寄存器推入堆栈 )格式: PUSHF( 无操作数 )功能:先将堆栈指针减 2( 即 (SP)-2 SP) ,然后将整个标志寄存器 (16位 )压入 (SP) 所指向的栈顶。

Page 97: 第6章 数据传送程序

4. POPF 指令 ( 标志退栈 )格式: POPF( 无操作数 )功能:先将堆栈顶的内容,即 ((SP)+ 1, (SP)) 传送至标志寄存器 (16 位 ) ,然后将堆栈指针 SP 加 2 ,即 (SP)+2 SP 。这几条指令的用途在于保存标志寄存器的内容,以及恢复标志寄存器的内容,或将标志寄存器的某一位或某几位置预定的值。关于它们的应用将会在第 7章的算术运算的例子中看到。

Page 98: 第6章 数据传送程序

习 题 6 1 将例 6 1 三种方法编写的程序加上输出结果的指令序列,即将 S1 中数据传送到 S2 后,再将 S2 中的字符显示输出。具体要求是:(1) 为程序 EX6-1-1 加上按正序将 S2 中的字符依次显示出来的指令序列。(2) 为程序 EX6-1-2 加上按逆序将 S2 中的字符依次显示出来的指令序列。(3) 为程序 EX6-1-3 加上按正序将 S2 中的字符依次显示出来的指令序列。提示:此题的困难在于 S2 是用 DW 伪指令定义的,而显示字符是一个字节一个字节的显示,解决此问题的方法有四个。

Page 99: 第6章 数据传送程序

i 按字节访问字变量,比如用 S2〔 SI〕地址表达式表示 S2 中的字节地址,在指令中用 PTR 操作符将字类型变量 S2 按字节访问。例如: MOV DL, BYTE PTR S2〔 SI〕ii 在数据段中定义 S2 的伪指令之前,用 LABEL或 EQU 伪指令为S2 所对应的同一物理位置,另外定义类型为 BYTE 的标号 ( 例如S3) 。当你希望按字节访问这片存储器时,就用 S3 这个名字 ( 比如:MOV DL, S3〔 SI〕 )。iii直接用 S2〔 SI〕访问,一次取一个字 ( 比如: MOV DX, S2〔 SI〕 ) ,然后先显示低位字节 (DL) ,再显示 (DH) 。即循环执行一次输出两个字符。iv 用变量名不出现在地址表达式里的间接访问。比如〔 SI〕、〔 BX〕、〔 BX〕〔 SI〕等地址表达式表示 S2 中的字节位移量 ( 例如: MOV DL,〔 SI〕 )。

Page 100: 第6章 数据传送程序

2 把例 6.1 的程序 EX6-1-1改为 S2 在辅助数据段, S1仍在数据段,将 S1 中的字符依次传送至 S2 后,按正序显示输出 S2中的字符。3 按例 6.1 的程序 EX6-1-3 的方法定义 S1 ,将 S1 按字依次推入堆栈,然后按 S1 中字符的反序从堆栈中弹出显示输出。提示:弹出字送入 DX ,首先显示 DL 的内容,然后再显示 DH的内容。4将 S1 字节变量中存放的 10 个字节,从中选出所有奇数位移量的 5 个字节,按相反顺序存入字节变量 S2。5 编写一个人机对话程序,要求屏幕显示提问:“what is your name?” 此时程序员键入: My name is……。

Page 101: 第6章 数据传送程序

6改写例 6.6 程序。(1) 将例 6.6改为不存储 0 , 1 , 2 ,…, 0FH ,而用指令计算出这些十六进制数字 ( 比如在 DH 里计算 ) ,然后将其转换成对应的 ASCII 码,并显示输出。(2) 将例 6.6改为不存储 0 , 1 , 2 ,…, 0FH ,而直接用 CX的值。提示: CX 的值依次为 16 , 15 ,…, 2 , 1 ,如果换码表定义为: TAB D DB ′FEDCBA9…21′ ,则 CX-1 即为′ 1′ ,′ 2′ ,…,′ E′ ′, F′在 TAB D 表中相对于表头的位移量。7交换 S1与 S2 变量中所存放的 5 个字。8设 S1 变量存放着 10 个字节,将位于 0 , 2 , 4 , 6 , 8位移量的字节与 1 , 3 , 5 , 7, 9位移量处的字节互相交换。

Page 102: 第6章 数据传送程序

9 编写一个加密与解密 0~9数字序列的程序,设 0 , 1 , 2 ,3 , 4 , 5 , 6 , 7, 8, 9对应的密码表为: 9, 0 , 8, 2 ,7, 4 , 6 , 3 , 1 , 5 ,键盘输入任意一个 4 位数要求程序能够马上输出这 4 位数对应的密码。例如,键盘输入 4935 ,显示输出7584 。10 编写与上述加密程序相应的解密程序。例如,输入 7584 ,输出 4935 。提示:首先写出解密表,如 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7, 8,9对应于 1 , 8, 3 , 7, 5 , 9, 6 , 4 , 2 , 0 。并注意,从键盘上输入 0~9数字时,在 AL 里得到的是 0~9数字的 ASCII码,因此,需要将它转换成二进制的数字值,而输出时又需将数字值转换成其对应的 ASCII 码。若用到逻辑指令则请参阅第 8章。