第3章80x86汇编语言程序设计下.ppt
1,第3章 80 x86汇编语言程序设计(下),2,3.3 汇编语言格式,汇编语言源程序结构汇编语言上机过程汇编语言语句格式伪操作(伪指令),3,数据段 说明:堆栈段 1、各段顺序无关 2、除代码段外,可缺省 3、可有若干个数据段,若干代码段 代码段 END 标号,附加段,3.3.1 源程序结构概览,4,汇编语言程序例,DATA SEGMENT BUF1 DB 34H BUF2 DB 2AH SUM DB?DATA ENDS,CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV AL,BUF1 ADD AL,BUF2 MOV SUM,AL MOV AH,4CH INT 21HCODE ENDS END START,5,3.3.2 汇编语言源程序上机过程,源程序.asm,目标程序.obj,结果debugDOS下执行,执行,可执行程序.exe,6,有三类语句:指令语句完成操作功能,能翻译成机器代码伪指令语句为汇编程序在翻译源程序时提供 有关信息 宏指令语句由若干条指令语句组成的语句,通用语句格式:名字 操作项 操作数;注释,3.3.3 汇编语言语句格式,7,指令语句格式 标号:指令助记符目的操作数,源操作数;注释 其中,表示可选项;,1、标号 标号是后续指令的符号名称,可用符号是:字母:A-Z,a-z 数字符:0-9 专用字符:?,_,$标号长度不超过31个字符,2、指令助记符 指令助记符是汇编指令的符号代码,不可缺省。汇编源程序时,系统使用内部对照表将每条指令的助记符译成相应的机器码。,8,3、目的操作数 1)参与指令操作 2)暂存操作结果 除立即寻址方式外,其他寻址方式均适用于目的操作数.,4、源操作数 提供原始数据或操作对象,面向所有寻址方式,5、注释 注释在系统汇编时并不产生机器码 注释可以放在指令语句尾,也可单独使用 注释前面的“;”不可缺少,9,常量常量有两种:1、数值常量 二进制数 以B结尾,如01011101B 八进制数 以Q结尾,如235Q 十进制数 以D结尾或没有结尾字母,如98D或98 十六进制数 以H结尾,如5BH2、字符串常量 用单引号括起来的一个或多个字符,如A、AB 字符用ASCII码形式存储,常量的应用:(1)在指令语句中作立即数 MOV CX,100(2)在指令语句中作位移量 MOV AX,34SI(3)在数据定义语句中作初值 X DB 12H,34H,10,变量和标号变量有三种属性:1、段属性变量所在段的起始地址2、偏移属性从段起始地址到定义变量的位置之间的字节数3、类型属性该变量所保留的字节数 DB 1个字节 DW 2 个字节 DD 4个字节 DQ 8个字节 DT 10个字节,11,标号也有三种属性:1、段属性定义标号所在段的起始地址2、偏移属性从段起始地址到定义标号的位置之间的字节数3、类型属性表示它的转移特性 NEAR(近)段内转移 FAR(远)段间转移,12,处理器选择伪指令 数据定义和存储器分配伪指令 段定义伪指令 程序开始和结束伪指令 表达式赋值伪指令 地址计数器与对准伪指令 基数控制伪指令,3.3.4 伪指令,13,(一)处理器选择伪指令.8086 可使用8086指令(一般不用写).286 可使用80286指令.286P 可使用保护方式下的80286指令.386 可使用80386指令.386P 可使用保护方式下的80386指令.486 可使用80486指令.486P 可使用保护方式下的80486指令.586 可使用Pentium指令.586P 可使用保护方式下Pentium的指令.686 可使用Pentium Pro指令.686P 可使用保护方式下Pentium Pro的指令.MMX 可使用MMX指令.XMM 可使用SSE指令,当源程序使用了286及以上的机型新增加的指令时,应该在程序开始使用相应的处理器选择伪指令。,14,(二)数据定义伪指令格式:变量名 定义符 操作数项表操作:为变量分配存储单元并将初值置入相应单元中,操作数项可为:1、常数或表达式 2、字符串 3、?表达式 4、带DUP 的表达式,定义符可为:DB 定义字节 DW 定义字(2个字节)DD定义双字(4个字节)DF定义六字节 DQ定义八字节 DT定义十字节,操作数项表:操作数项,操作数项,操作数项,15,操作数是常数或表达式 X1 DB 40H;为X1分配1个字节,初值40H X2 DW 250*250;为X2分配2个字节,初值62500 X3 DD 10203040H;为X3分配4个字节,初值为10203040H X4 DQ(120+50)/10;为X4分配8个字节,初值17 X5 DB 10,20,30;多项定义,X5被分配3个字节,初值分别为10,20,30,地址从低到高,各个值间用逗号分开,16,操作数为字符串 STRING1 DB HELLO STRING2 DB H,E,L,L,O 字符串用DB定义,被定义串以单引号括起来 串中可包含数字符、大小写英文字母、回车符、换行符、空格、?、$、下划线_等 字符串以ASCII码形式存储在存储单元中。,STRING1 H+1 E+2 L+3 L+4 O,17,区分 S1 DB AB 与 S2 DW AB 它们的存储情况为:S1 S2 A B B A,操作数项为?用于预留空间,不置初值 Y1 DB 20H,?;定义2个字节,其中预留1个字节 Y2 DW?,?;预留2个字 Y3 DD?;预留4个字节 Y4 DQ?;预留8个字节 Y5 DT?;预留10个字节,18,操作数项带重复定义符DUP 格式:N DUP(操作数项表)操作:以N所示次数定义操作数项表内容 VAR1 DW 2 DUP(2,4),1476H VAR2 DB 2 DUP(?,2 DUP(A,B)存储情况为:VAR1 02H VAR2?00H A 04H B 00H A 02H B 00H?04H A 00H B 76H A 14H B,19,操作数运算符,算术运算符逻辑运算符关系运算符数值回送运算符属性运算符运算符优先级,20,算术运算符(单目+,单目-,+,-,*,/,MOD)运算符 格 式 运 算+表达式 取表达式正值-表达式 取表达式负值+表达式1+表达式2 求表达式1、表达式2之和-表达式1-表达式2 求表达式1、表达式2之差*表达式1*表达式2 表达式1、表达式2之积/表达式1/表达式2 表达式1、表达式2之商 MOD 表达式1 MOD 表达式2 取余数,说明:1、算术运算符可用于数值表达式或地址表达式2、用于地址表达式时,只有其结果有物理意义时才有效 常用的是:地址+数字常量 地址-数字常量,21,算术运算符示例(1)MOV AL,20+30;50-AL MOV BH,100-2;98-BH MOV CX,50/2;25-CX MOV AL,80 MOD 15;5-AL,(3)设数据定义如下:ARRAYA DW 1,2,3,4,5,6,7 WENDA DW?将数组长度(字数)存入CX:MOV CX,(WENDA-ARRAYA)/2;地址-地址,结果为一常量,(2)将首地址为BLOCK的字数组的第6个字传送到DX:MOV DX,BLOCK+(6-1)*2;地址+常量,结果仍为一地址值,22,逻辑运算符(NOT,AND,OR,XOR)运算符 格 式 运 算 NOT NOT 表达式 按位取反 AND 表达式1 AND 表达式2 按位“与”运算 OR 表达式1 OR 表达式2 按位“或”运算 XOR 表达式1 XOR 表达式2 按位“异或”运算 逻辑运算符和逻辑运算指令的区别:逻辑运算指令 逻辑运算符出现在语句的位置 指令助记符 操作数字段操作对象 可以是寄存器或 只能是整型常数 存储器操作数何时计算 程序运行时 源程序汇编时,23,关系运算符(EQ,NE,LT,LE,GT,GE)运算符 格 式 运 算 EQ 表达式1 EQ 表达式2 表达式1=表达式2为真 NE 表达式1 NE 表达式2 表达式1表达式2为真 LT 表达式1 LT 表达式2 表达式1表达式2为真 GE 表达式1 GE 表达式2 表达式1=表达式2为真,关系运算符的两个操作数必须都是常量或同一段内的符号地址,比较结果为逻辑值:如果关系成立,则返回0FFFFH(真);否则,返回0(假)。,24,逻辑运算符示例 MOV AH,NOT 0F0H;0FH-AH MOV BL,40H OR 0B4H;0F4H-BL XOR BL,55H XOR 48H;XOR BL,1DH AND CH,50H AND 30H;AND CH,10H,关系运算符示例 N1 EQU 10 N2 EQU 20.MOV BX,N1 EQ N2;0-BX MOV CX,N1 NE N2;0FFFFH-CX MOV AX,N1 LT N2;0FFFFH-AX MOV DI,N1 GE N2;0-DI,25,数值回送运算符(SEG,OFFSET,TYPE,LENGTH,SIZE)数值回送运算符对变量或标号进行分析,回送其地址属性值或变量特征值。(1)地址回送运算符 符号 作用对象 操 作 SEG 变量或标号 返回其所在段的段基址值OFFSET 变量或标号 返回其在段内的偏移量,26,(2)符号特征回送运算符 符号 作用对象 操 作 TYPE 变量或标号 用数字表示其类型属性 LENGTH 变量 用DUP重复定义符定义的变量,返回分配的元素个数;其他 形式,则返回1 SIZE 变量 回送LENGTH*TYPE之积,27,TYPE 运算符 类型属性 运算结果变量 DB 1 DW 2 DD 4 DQ 8 DT 10标号 NEAR-1 FAR-2,28,数值回送运算符示例 D_SEG SEGMENT NUM1 DB 10 DUP(10);数据定义 NUM2 DB 10H,20H,50H NUM3 DW 20 DUP(0,4 DUP(2)NUM4 DB STRING D_SEG ENDS,MOV CL,SIZE NUM4;1*1-CL MOV CH,SIZE NUM3;20*2-CH,MOV AH,TYPE NUM3;2-AHMOV BH,LENGTH NUM3;20-BH(最外层),MOV SI,OFFSET NUM1;NUM1的偏移量-SIMOV DI,OFFSET NUM2;NUM2的偏移量-DI,MOV AX,SEG NUM1MOV BX,SEG NUM2;NUM2与NUM1段基址值相同,注意OFFSET与LEA的区别,29,属性运算符(PTR,SHORT),SHORT格式:JMP SHORT 标号 操作:转移的距离属性为短,即转移范围为-128+127字节,PTR格式:类型 PTR 表达式 操作:对存储器寻址的表达式,类型可为BYTE,WORD,DWORD,QWORD和TBYTE;表达式为标号时,类型可为NEAR或FAR。该运算符显式指定表达式的类型,30,PTR 运算符示例(1)DATA1DB 10H,20H,30H DATA2DW 4023H,1A00H;数据定义.MOV AX,WORD PTR DATA1;(AX)-2010H MOV BL,BYTE PTR DATA2;(BL)-23H PTR运算符指明DATA1由原来的字节变量临时改变为字变量,而字变量DATA2则临时变为字节变量,所谓临时是指在当前指令语句中有效,而存储分配情况并不改变。,(2)MOV BYTE PTRSI,60H;字节传送 SUB WORD PTRBX,36H;字数据减 JMP FAR PTR S1;段间转移,31,本课件涉及到的运算符优先级优先级 运算符 类 别 1 LENGTH,SIZE 数值回送运算符 2 PTR,OFFSET,SEG,TYPE,属性与数值回送运算符 3+,-符号运算符 4*,/,MOD 算术运算,移位运算符 5+,-算术运算符 6 EQ,NE,LT,LE,GT,GE 关系运算符 7 NOT 逻辑运算符 8 AND 逻辑运算符 9 OR,XOR 逻辑运算符 说明:优先级1最高,而优先级9最低 圆括号()可改变执行顺序,32,(三)段定义伪指令1)完整的段定义伪指令 格式:段名 SEGMENT 定位类型组合类型使用类型类别名.段名 ENDS 操作:定义逻辑段,(1)定位类型 指定当前段的起始地址的性质1、PARA 段起始地址的低4位为0H,即16的倍数。2、PAGE 段起始地址的低8位为00H,即256的倍数 3、BYTE 段可从任意地址开始 4、WORD 当前段的起始地址为偶地址 5、DWORD 段的起始地址为4的倍数 默认项是PARA,33,(2)组合类型 说明程序连接时的段合并方法1、PRIVATE 为私有段,连接时不与其他模块中的同名段合并2、PUBLIC 不同模块的同名段连接在一起,形成参与邻接模块所公用的物理段 3、COMMON 产生一个覆盖段。与其它具有该类型的同名段拥有同一起始地址,共享相同的存储区。共享存储区的长度由同名段中最大的段确定4、STACK 功能同PUBLIC,但新形成的段为堆栈段 默认项是PRIVATE,34,(3)使用类型 说明使用16位还是32位寻址方式 USE16 使用16位寻址方式 USE32 使用32位寻址方式 386以下处理器默认项是USE16,386及以上处理器默认项是USE32,(4)类别名 LINK 程序将类别名相同的段依次序连续存放在 内存中。如果这些段未选择PUBLIC、COMMON组合 类型,则这些段将各自独立 缺省类别名,作空处理。,35,段定义伪指令示例 D_SEG SEGMENT PARA DATA NUM1 DB 10 DUP(?)D_SEG ENDS S_SEG SEGMENT PARA STACK DW 100 DUP(?)S_SEG ENDS E_SEG SEGMENT DATA STRING DB HELLO E_SEG ENDS.,36,2)指定段寄存器伪指令 格式:ASSUME 段寄存器:段名,段寄存器:段名.操作:明确段与段寄存器的关系。,说明:1、代码段中必须至少有一个ASSUME语句 2、ASSUME可以出现在源程序中的任意地方 3、仅说明段与段寄存器的对应关系,除了在程序装入时将代码段和堆栈段的段基址赋值给CS和SS外,并没有把数据段和附加段的段基址值送入DS、ES、GS和FS寄存器中,需要在程序中显式赋值。,37,ASSUME语句示例 D_SEG SEGMENT PARA DATA NUM1 DB 10 DUP(?)D_SEG ENDS S_SEG SEGMENT PARA STACK DW 100 DUP(?)S_SEG ENDS E_SEG SEGMENT DATA STRING DB HELLO E_SEG ENDS C_SEG SEGMENT PARA CODE ASSUME CS:C_SEG,DS:D_SEG,ES:E_SEG;SS:S_SEG START:.C_SEG ENDS END START 这里明确D_SEG段为数据段,S_SEG段为堆栈段,E_SEG段为附加段,C_SEG为代码段。,38,段寄存器的赋值(1)代码段寄存器CS(及IP)的赋值 当连接程序扫描到程序结束伪指令END符号地址时,系统自动将当前代码段基址赋值给CS,同时把END后的符号地址送入IP,系统自动填入SS示例 S_SEG SEGMENT PARA STACK STACK DW 200 DUP(?)S_SEG ENDS,1、系统自动填入 被定义为堆栈的段选择STACK组合类型,当含有该段的目标程序被装入存储器时,系统自动取该段基址送SS,取段长度送SP,(2)堆栈寄存器SS(及SP)的填入有以下两种方法:,39,2、用指令填入 被定义为堆栈的段在组合类型位置上缺省,在代码段中用3条MOV指令完成这个功能.,用指令填入SS示例 S_SEG SEGMENT PARA STACK DW 200 DUP(?)TOP LABLE WORD S_SEG ENDS C_SEG SEGMENT PARA CODE ASSUME CS:C_SEG,SS:S_SEG,DS:NOTHING,ES:NOTHING START:MOV AX,S_SEG;填入段基址 MOV SS,AX LEA SP,TOP;填入栈指针 C_SEG ENDS END START,40,(3)数据段寄存器DS及附加段寄存器的填入 用MOV传送指令填入,填入DS、ES示例 D_SEG SEGMENT PARA DATA;数据段 X DW?,4000H,100 DUP(?)D_SEG ENDS E_SEG SEGMENT PARA DATA;附加段 STRING DB EXAMPLE E_SEG ENDSC_SEG SEGMENT PARA CODE ASSUME CS:C_SEG,DS:D_SEG,ES:E_SEG,SS:S_SEG START:MOV AX,D_SEG MOV DS,AX;数据段基址-DS MOV AX,E_SEG MOV ES,AX;附加段基址-ES,41,3)存储模型与简化段定义伪指令1、模式选择伪指令MODEL格式:.MODEL 模式选择符功能:指明简化段所用内存模式,Tiny模式(微模式):所有数据和代码放入同一物理段内,可写成.COM文件形式 Small模式(小模式):所有数据放在一个64KB的段,所有代码放在一个64KB的段 Medium模式(中模式):所有数据放在一个64KB的段,代码可放在多个段 Compact模式(压缩模式):所有代码放在一个64KB的段,数据可放在多个段 Large模式(大模式):代码和数据都可用多个段 Huge:与Large相同,但数据段大小可超过64KB Flat:允许用户用32位偏移量,42,2、简化的段定义伪指令,数据段定义伪指令格式:.DATA 名字功能:定义数据段,若有多个数据段,用名字区别。只有一个数据段时,段名为DATA,栈段定义伪指令格式:.STACK 名字功能:定义一个栈段,并形成SS及SP的初值,SP的默认值为1024,隐含段名为STACK,代码段定义伪指令格式:.CODE 名字功能:定义代码段,若有多个代码段,用名字区别。只有一个代码段时,段名为CODE,43,简化段定义示例.MODEL SMALL.STACK 100H.DATA.CODESTART:MOV AX,DATA MOV DS,AX MOV AX,4C00H INT 21HEND START,44,(四)程序开始和结束伪指令 1)程序开始伪指令 格式1:NAME 模块名 操作1:用此名作为模块名 如缺省则以模块的源程序文件名为模块名,模块命名伪指令示例 NAME MODE1 NAME MODE2 TITLE EXAM,格式2:TITLE 文本操作2:没有NAME时,用其前6个字符作为模块名 可在列表文件中打印标题,45,2)源程序结束控制伪指令 格式1:END 格式2:END 符号地址 功能:告诉汇编程序,源程序到此结束,并将符号地址 所示单元的段基址和偏移量自动装入CS和IP中,源程序结束控制伪指令示例 C_SEG SEGMENT PARA CODE ASSUME CS:C_SEG,.START:.C_SEG ENDS END START 说明:源程序从标号START处开始执行,46,(五)表达式赋值伪指令(EQU,=)格式:名字 EQU 表达式 名字=表达式 操作:为表达式取一个名字,供以后引用 说明:1、表达式可为常数、变量、标号、指令助记符、字符串 2、在一个源程序中,被EQU伪指令赋值的符号不能 再次赋值,而用=定义的符号名可重复定义.3、赋值语句仅在汇编源程序时,作为替代符号用,不产生目标代码,也不占有存储单元,47,赋值伪指令示例 CONST EQU 100*2;定义符号常数 ADDRS EQU BX+10;为地址表达式定义名字 CHAR EQU COMPUTER;为字符串定义名字 COUNT=AX;给寄存器定义名字.MOV BX,CONST;引用 ADD BX,COUNT SUB ADDRS,20.等同于 MOV BX,100*2 ADD BX,AX SUB BX+10,20,48,(六)地址计数器与对准伪指令1)地址计数器$,示例1 ARRAY DW 1,2,$+4,3,4,$+3,ARRAY 01h 0074H 00 02h 0076H 00 7Ch 0078H 00 03h 007AH 00 04h 007CH 00 81h 007EH 00,示例2 BUFFER DB 1,2,3,4,5 COUNT EQU$-BUFFER 数据定义的结果:COUNT的值即为BUFFER的长度,示例3 OUT 21H,AL JMP$+2;跳转到下一句 MOV AX,0,49,2)定位伪指令 格式1:ORG 表达式 格式2:ORG$+表达式 功能:将表达式的值送入程序计数器$表示程序计数器的当前值 定位伪指令示例 10H 20H D_SEG SEGMENT PARA DATA 11H 30H ORG 10H X DB 20H,30H ORG$+5 17H 40H Y DB 40H,50H 18H 50H D_SEG ENDS,50,完整段定义结构 简化段定义结构 程序段前缀结构,3.3.5汇编语言源程序结构,51,完整段定义结构,DATA SEGMENT DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATASTART:MOV AX,DATA MOV DS,AX MOV AH,4CH INT 21HCODE ENDS END START,什么作用?,52,简化段定义结构,.MODEL SMALL.DATA.CODE MOV AX,DATA MOV DS,AX MOV AH,4CH INT 21H END,53,利用程序段前缀的结构,DATA SEGMENT DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATAMAIN PROC FAR PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX RETMAIN ENDPCODE ENDS END MAIN,54,常用的返回DOS的方法,使用DOS功能调用的4CH功能:MOV AH,4CHINT 21H使用INT 20H指令将主程序设计成一个属性为FAR的过程,由DOS调用该过程执行,由RET指令返回DOS(原理和使用方法见后),55,统计一个字节数据块中负元素的个数,存入变量CNT D_SEG SEGMENT ARRAY DB-1,10,11,-7,-9,4,8 LEN EQU$-ARRAY CNT DB?D_SEG ENDS.LEA SI,ARRAY JSU:INC SI MOV CX,LEN LOOP LP MOV DX,0 MOV CNT,DLLP:MOV AL,SI MOV AH,4CH CMP AL,0 INT 21H JGE JSU INC DL,56,INT 20H DS 程序段前缀区 程序区,程序加载结构,操作系统加载EXE程序时自动在前面加上256字节的程序段前缀,PUSH DS MOV AX,0 PUSH AX 把程序段前缀区第一个字节单元的地址和偏移量压栈保存,这个单元是指令INT 20H,这几句一定要放在主程序开始的位置RET 指令把程序段前缀区第一个字节单元的地址和偏移量弹出分别送IP和CS,转去执行INT 20H,从而实现返回DOS,57,存储单元NUM中为一个16位的二进数,统计其中值为1 的位的个数存入RESULT C_SEG SEGMENT.MAIN PROC FAR JZ DONE PUSH DS SAL AX,1 MOV AX,0 JNC NEXT PUSH AX INC CL MOV AX,D_SEG NEXT:JMP LOOP1 MOV DS,AX DONE:MOV RESULT,CL MOV CX,0 RET MOV AX,NUM MAIN ENDPLOOP1:AND AX,AX C_SEG ENDS END MAIN本程序采用的是用RET返回DOS的方法 循环结束条件是什么?采用这样的条件有什么好处?,58,程序的基本结构有三种:顺序结构、分支结构和循环结构。1)顺序结构 顺序结构是最简单也是最基本的程序结构。程序按顺序执行,不发生任何转移。,语句1,语句n,语句2,.,3.4 程序的基本结构,59,2)分支结构 分支结构是指计算机根据实际情况或条件,作出判断和选择,转而执行不同的程序段的一种程序结构。,条件,程序段,条件,程序段A,程序段B,Y,N,Y,N,60,多路分支结构 根据某个控制字的各“位”状态实行多路转移,多路条件测试,程序段1,程序段2,程序段n,61,3)循环结构 任务需要重复执行某一程序段,这种情况采用循环结构来实现。,初始化,循环体,修改部分,控制部分,初始化,控制部分,循环体,修改部分,N,Y,Y,N,62,两个32位无符号数乘法程序,NUM1 DD 12345678HNUM2 DD 5A4BEF06HRESU DD 2 DUP(?)MOV EAX,NUM1MUL NUM2MOV RESU,EAXMOV RESU+4,EDX,3.4.1 顺序结构程序设计,教材上的例子请看P98中的例3.17,上机调试该程序(注意给X,Y,Z赋初值)。,63,压缩的BCD码转化成ASCII码 BCD_BUF DB 96H ASC_BUF DB 2 DUP(?)BCD_BUF 96,MOV AL,BCD_BUF MOV CL,4 MOV BL,AL SHR AL,CL;右移4位,将高4位填0ADD AL,30HMOV ASC_BUF,ALAND BL,0FHADD BL,30HMOV ASC_BUF+1,BL.,ASC_BUF 9,6,64,用直接查表法完成将键盘输入的一位10进制数(09)转换成对应的平方值并存放在SQRBUF单元中,SQUTAB DB 0,1,4,9,16,25,36,49,64,81SQRBUF DB?MOV BX,OFFSET SQUTABMOV AH,1INT 21H;DOS功能调用的1号子功能是键盘输入SUB AL,30HXLATMOV SQRBUF,AL,65,把存储单元A和B中的两个单字节压缩BCD码相加,结果存到C单元中,进位存放到C+1中。,A DB 32HB DB 15HC DB 2 DUP(?)MOV AL,A;取被加数ADD AL,B;二进制加法DAA;调整为十进制结果MOV C,AL;存回C单元LAHF;取标志位AND AH,01;取CF位MOV C+1,AH;存进位到C+1单元,要求不用分支结构,该怎么做?,如果用分支结构该怎么做?,66,1、比较/转移 利用比较和条件转移指令实现两路分支。比较结果记录在某些标志位中,条件转移指令根据约定的条件进行对照,满足条件时转移,不满足条件时不转移。,2、跳转表转移 利用跳转表实现多路分支。比较/转移指令可嵌套,但程序结构复杂,跳转表可使程序结构清晰。,3.4.2 分支结构程序设计,教材上的例子请看P99中的例3.18和例3.19,上机实现例3.18程序。,67,利用比较和条件转移指令实现程序分支变量X为一任意有符号字节数,若X为负数,则将其取补码;否则,和Y相加,其和存入AX中.MOV AL,X CMP AL,0 JGE ADDT NEG AL;X求补 MOV X,AL JMP EXITADDT:ADD AL,Y;X+Y ADC AH,0EXIT:,X=0,X-X取补,AX-X+Y,Y,N,68,设字节单元N1、N2中存放无符号数(1)若两个均是偶数,则分别加1后送D1、D2中(2)若两个均是奇数,则直接送D1、D2中(3)若一个是奇数,一个是偶数,则把奇数送D1,偶数送D2中,AL-(N1),AH-(N2),(AL)0=0,(AH)0=0,AL-(AL)+1AH-(AH)+1,(AL)(AH),D1-(AL),D2-(AH),奇,偶,偶,奇,注意:根据条件,当N1是奇数时,无论N2是奇数还是偶数,都只需直接送D1、D2,69,程序如下:MOV AL,N1 MOV AH,N2 TEST AL,01H;测试 N1的奇偶 JNE ENDO;N1为奇数 TEST AH,01H;测试 N2的奇偶 JNE L1;N2是奇数,转移 INC AL;两个均是偶数 INC AH JMP ENDOL1:XCHG AL,AH;N1是偶数,N2是奇数ENDO:MOV D1,AL;存放结果 MOV D2,AH,转上页,70,利用跳转表实现多路分支跳转表是在某一内存区域顺序排列的一组有规律的入口地址。如是段内分支,每个地址占两个单元(IP的值)如是段间分支,每个地址占4个单元(CS:IP的值)TABLE SUB1 TABLE SUB1 SUB2 SUB3 SUB2,IP,IP,IP,IP,CS,IP,CS,段内转移 段间转移,71,根据AL中哪一位为1(从低位到高位)把程序转移到8个不同的程序分支去,TABLE DW ROUTINE_1 DW ROUTINE_2 DW ROUTINE_3 DW ROUTINE_4 DW ROUTINE_5 DW ROUTINE_6 DW ROUTINE_7 DW ROUTINE_8,72,方法1 用变址寻址方式,CMP AL,0 JE DONE MOV SI,0L:SHR AL,1 JNB NOT_YET;CF=0或ZF=1跳转 JMP TABLESINOT_YET:JZ DONEADD SI,TYPE TABLE;Type Table=2 JMP LDONE:,73,方法2 用寄存器间接寻址方式,CMP AL,0 JE DONE LEA BX,TABLEL:SHR AL,1 JNB NOT_YET JMP WORD PTRBXNOT_YET:JZ DONE ADD BX,TYPE TABLE JMP LDONE:,74,方法3 用基址变址寻址方式,CMP AL,0 JE DONE LEA BX,TABLE MOV SI,7*TYPE TABLE MOV CX,8L:SHL AL,1 JNB NOT_YET JMP WORD PTRBXSINOT_YET:JZ DONE SUB SI,TYPE TABLE JMP LDONE:,75,在附加段中有一个从小到大排序的无符号数字数组,其首地址在DI中,数组的第一个单元存放数组长度。要求在数组中查找(AX),如找到,CF=0,并在SI中给出该元素在数组中的偏移地址;如未找到,CF=1。,算法:在R数组中查找K,采用折半查找法LOW1,HIGHN;若LOWHIGH,则查找失败,置CF=1,退出程序。否则,计算中点:MID(LOW+HIGH)/2;(3)K与RMID比较。若=RMID,则查找成功,程序结束;若KRMID,则转(5);(4)HIGHMID-1,转(2);(5)LOWMID+1,转(2)。,76,CMP AX,ES:DI+2;与第一个数比较 JA CHK_LAST;(AX)(ES:DI+2)转 LEA SI,ES:DI+2 JE EXIT;相等,找到,就是第一个数 STC;小于第一个数,失败 JMP EXITCHK_LAST:MOV SI,ES:DI;取数组长度 SHL SI,1;长度*2(DW型)ADD SI,DI CMP AX,ES:SI;与最后的数比较 JB SEARCH;小于则转 JE EXIT;相等则结束 STC;大于最后一个,失败 JMP EXIT,77,SEARCH:MOV LOW_IDX,1;给LOW赋初值 MOV BX,ES:DI MOV HIGH_IDX,BX;给HIGH赋初值 MOV BX,DI;BX中放首地址MID:MOV CX,LOW_IDX MOV DX,HIGH_IDX CMP CX,DX JA NO_MATCH;LOWHIGH,失败 ADD CX,DX SHR CX,1;折半 MOV SI,CX SHL SI,1;*2(DW型)COMPARE:CMP AX,ES:BX+SI;与中间数比较 JE EXIT;相等,找到,78,JA HIGHER;大于中间数,转 DEC CX MOV HIGH_IDX,CX;调整查找区间到前半部分 JMP MIDHIGHER:INC CX MOV LOW_IDX,CX;调整查找区间到后半部分 JMP MIDNO_MATCH:STCEXIT:,79,循环程序的组成:1、初始化部分 设置初始值2、循环工作部分 具体的操作和运算3、循环修改部分 为执行下一循环而修改某些参数4、循环控制部分 判断循环继续还是结束,循环控制方法有:(1)计数控制法 增数法 减数法(2)条件控制法,3.4.3 循环结构程序设计,80,单重循环程序设计将以s1为起始地址的26个字母依次传送到以s2为起始地址的连续单元中。数据定义如下:DATA SEGMENT S1 DB ABCDXYZDATA ENDSESTRA SEGMENT S2 DB 26 DUP(?)ESTRA ENDS,81,方法1 采用寄存器间接寻址方式 MOV AX,SEG S1;初始化 MOV DS,AX MOV AX,SEG S2 MOV ES,AX MOV SI,OFFSET S1 MOV DI,OFFSET S2 MOV CX,26 LOP1:MOV AL,SI;工作部分 MOV ES:DI,AL INC SI;修改部分 INC DI LOOP LOP1;控制部分,82,方法2 采用变址寻址方式 MOV AX,SEG S1;初始化 MOV DS,AX MOV AX,SEG S2 MOV ES,AX MOV SI,0 MOV DI,0 MOV CX,26 LOP1:MOV AL,S1SI;工作部分 MOV ES:S2DI,AL INC SI;修改部分 INC DI LOOP LOP1;控制部分,83,方法3 采用基址变址寻址方式 MOV AX,SEG S1;初始化 MOV DS,AX MOV AX,SEG S2 MOV ES,AX MOV BX,OFFSET S1 MOV BP,OFFSET S2 MOV SI,0 MOV DI,0 MOV CX,26 LOP1:MOV AL,BX+SI;工作部分 MOV ES:BP+DI,AL INC SI;修改部分 INC DI LOOP LOP1;控制部分,84,方法4 采用串处理指令 MOV AX,SEG S1;初始化 MOV DS,AX MOV AX,SEG S2 MOV ES,AX LEA SI,S1 LEA DI,S2 MOV CX,26 CLD REP MOVSB,85,计数控制法计数控制法适用于循环次数已知的场合,2、减数法 初始化时循环计数器置为循环次数,每执行一次循环体后计数器减1,并测试循环计数器是否为0,如为0则终止循环。减数法一般用循环指令形成循环回路。,1、增数法 初始化时循环计数器置0,每执行一次循环体后计数器加1,并与已知的循环次数比较,如相等则退出循环。增数法一般用比较指令和条件转移指令实现循环转移。,86,NUM DW 1;.MOV CX,0;初始化 MOV AX,0 ROTATE:ADD AX,NUM;累加 INC WORD PTRNUM INC CX;计数器加1 CMP CX,50;与已知的循环次数比较 JNZ ROTATE MOV S,AX.,增数法计算S=1+2+3+50,结果存入AX中,如何做N的阶乘N!,87,减数法将内存中6个十进制数的ASCII码转换为非压缩BCD码,并存放在后继相应单元中,如错,存放0FFH。,ASCBUF DB 35H,38H,30H,4DH,39H,32H DB 6 DUP(?).MOV DI OFFSET ASCBUF MOV CX,6 LAB_1:MOV BL,0FF