240 likes | 566 Views
……. 第 5 章 循环与分支程序设计. 程序结构: 顺序结构 循环结构 分支结构 子程序结构 复合结构:多种程序结构的组合. 编制汇编语言程序的步骤: (1) 分析题意,确定算法 (2) 根据算法画出程序框图 (3) 根据框图编写程序 (4) 上机调试程序 三种模式: 1 ) DOS 操作系统下的实模式; 2 ) 80286 开始的保护模式;
E N D
…… 第5章 循环与分支程序设计 程序结构: 顺序结构 循环结构 分支结构 子程序结构 复合结构:多种程序结构的组合
编制汇编语言程序的步骤: (1) 分析题意,确定算法 (2) 根据算法画出程序框图 (3) 根据框图编写程序 (4) 上机调试程序 • 三种模式: 1)DOS操作系统下的实模式; 2)80286开始的保护模式; 3)从80386开始的虚86模式。
开 始 初 始 化 循环的初始状态 循 环 体 循环的工作部分及修改部分 控制条件计数控制 特征值控制 地址边界控制 结 束 5.1循环程序设计 (1)DO-UNTIL结构 N Y (1)DO-UNTIL结构
开 始 初 始 化 Y 控制条件 N 循环体 结 束 • DO_WHILE结构 (2) DO_WHILE结构 当循环次数有可能等于0的时候,应当用WHILE结构
BX 1 2 3 4 5.1.2循环程序设计方法 例5.1 把BX中的二进制数以十六进制的形式显示在屏幕上。 循环左移4位
开始 初始化循环次数 BX循环左移4位 最左边的4位转换为ASCII ASCII是A~F N Y 加 7 显示一个字符 循环次数=0 N Y 结束
Prognam segment Main proc far assume cs:prognam Start: push ds sub ax,ax push ax 指定返回地址 mov ch, 4 rotate: mov cl, 4 rol bx, cl mov al, bl and al, 0fh add al, 30h ;’0’-’9’ ASCII 30H-39H cmp al, 3ah jl printit add al, 7h ;’A’-’F’ ASCII 41H-46H printit: mov dl, al mov ah, 2 int 21h dec ch jnz rotate ret Main endp Prognam ends end
例5.4将正数n插入一个已整序的字数组的正确位置。例5.4将正数n插入一个已整序的字数组的正确位置。 Datarea segment x dw ? array_head dw 3,5,15,23,37,49,52,65,78,99 array_end dw 105 n dw 32 Datarea ends Prognam segment Main proc far Assume cs:prognam, ds:datarea Start: Push ds Sub ax,ax Push ax Mov ax,datarea Mov ds,ax 确定返回地址 不要这三句 话报的错 不要这两句 话报的错 段首地址
mov ax, n mov array_head-2, 0ffffh mov si, 0 compare: cmp array_end[si], ax jle insert mov bx, array_end[si] mov array_end[si+2], bx sub si, 2 jmp short compare insert: mov array_end[si+2], ax ret Main endp… 返回到DOS操作
例5.5设有数组x(x1, … , x10)和y(y1, … , y10),编程计算 z1=x1 + y1 z2=x2 + y2 z3=x3 - y3 z4=x4 - y4 z5=x5 - y5 z6=x6 + y6 z7=x7 - y7 z8=x8 - y8 z9=x9 + y9 z10=x10 + y10 逻辑尺:0 0 1 1 0 1 1 1 0 0 标志位为1: 减法 标志位为0: 加法
x dw x1,x2,x3,x4,x5,x6,x7,x8,x9,x10 y dw y1,y2,y3,y4,y5,y6,y7,y8,y9,y10 z dw z1,z2,z3,z4,z5,z6,z7,z8,z9,z10 logic_rule dw 00dch mov bx, 0 mov cx, 10 mov dx, logic_rule next: mov ax, x[bx] shr dx, 1 jc subtract add ax, y[bx] jmp short result ; 向前引用 subtract: sub ax, y[bx] result: mov z[bx], ax add bx, 2 loop next
例5.7将首地址为a的字数组从大到小排序(起泡算法,多重循环)例5.7将首地址为a的字数组从大到小排序(起泡算法,多重循环) a dw 100,30,78,99,15,-1,66,54,189,256 mov cx, 10 ;CX←数组元素个数 dec cx ;元素个数减1为外循环次数 loop1: mov di, cx ;di保留外循环次数 mov bx, 0 loop2: mov ax, a[bx] ;取前一个元素 cmp ax, a[bx+2] ;与后一个元素比较 jge continue ;前一个大于或等于后一个元素,则不进行交换 xchg ax, a[bx+2] ;否则,进行交换 mov a[bx], ax continue: add bx, 2 ;下一对元素 loop loop2 ;内循环尾 mov cx, di loop loop1 ;外循环尾
case 1 case 2 case n N Y ? 5.2分支程序设计 (1)CASE结构 (2)IF-THEN-ELSE结构 (3)地址跳跃表法 值与地址有对应关系的表
cmp al, 0 • je continue • Lea bx,branch_table • L: shr al, 1 ;逻辑右移 • jnb not_yet ;jnb=jnc • jmp word ptr [bx] • ;段内间接转移 • not_yet: • add bx, type branch_table • jmp L • continue: …… • routine1: …… • routine2: …… branch_table dw routine1 dw routine2 dw routine3 dw routine4 dw routine5 dw routine6 dw routine7 dw routine8 例5.10根据AL寄存器中哪一位为1(从低位到高位)把程序 转移到8个不同的程序分支去 。(寄存器间接寻址)
(寄存器相对寻址) cmp al, 0 je continue mov si, 0 L: shr al, 1 ;逻辑右移 jnb add1 ;jnb=jnc jmp branch_table[si];段内间接转移 add1: add si, type branch_table jmp L continue: …… routine1: …… routine2: …… ……
(基址变址寻址) cmp al, 0 je continue lea bx, branch_table mov si, 7* type branch_table mov cx, 8 L: shl al, 1 ;逻辑左移 jnb sub1 ;jnb=jnc jmp word ptr [bx][si];段内间接转移 sub1: sub si, type branch_table loop L continue: …… routine1: …… routine2: …… ……
§5.3 分支程序设计 一、转移指令: 转移指令分两种:无条件转移指令和条件转移指令。 1、无条件转移指令 格式: JMP 目标地址 功能:JMP指令是使程序无条件的转移到目标地址 指向的指令执行。 分类: 段内转移 段间转移
分支程序设计 三、分支程序设计 有两种结构形式:①比较/测试—分支结构; ②分支表(跳转表)结构。 1、用比较/测试分支结构(即用条件转移指令实现程序分支) 通常一条转移指令只能产生两个分支。
分支程序设计 例:数据块间的搬移程序 要求把内存中一数据块(源数据块)传送到另一存储区(目的数据块)。 … … … … 源块 源块 目的块 … 目的块 源块 目的块 … … … ①源块首址<目的块首址 ②源块首址>目的块首址 1.两个数据块分离 2.两个数据块部分重叠
数据块间的搬移程序 结论: 1、源数据块与目的数据块有分离:数据传送任意 2、源数据块与目的数据块部分重叠: ①源块首址<目的块首址 从数据块末地址开始传送数据。 ②源块首址>目的块首址 从数据块首地址开始传送数据
多路分支程序设计 多路分支采用条件转移指令实现存在的缺点: ①要用N条条件转移指令才能实现N+1路分支。 ②程序较长,且进入各路分支的时间不一致。
跳转表:多路分支程序设计 2. 跳转表 1)某程序需N 路分支,每路程序的入口地址分别为: SUB1、SUB2、…… SUBN,把这些转移的入口地址组成一个表,叫跳转表。 2)跳转表内由若干跳转指令组成。
数据段 表首址 分支1偏移量 分支2偏移量 … 分支N偏移量 跳转表1:用入口地址组成 跳转表1: 某程序需N路分支,每路程序的入口地址分别为SUB1、SUB2、……SUBN,把这些转移的入口地址组成一个表,表内每两个字节存放一个入口地址的偏移量。 查找第N个分支在的跳转表中的地址: (N-1)*2+表首址
代码段 表首址 JMP 分支1 JMP 分支2 JMP 分支N 跳转表2:由若干无条件转移指令组成 跳转表2 表内由若干无条件转移指令(JMP BRAN1、JMP BRAN2、...)组成,表存放在代码段中。 (假设:每条无条件转移指令都是3个字节长度) 查找第N个分支在的跳转表中的地址: (N-1)*3+表首址