1 / 71

第四章 汇编语言程序设计基础

……. 第四章 汇编语言程序设计基础. 基本程序结构: 顺序结构 循环结构 分支结构 子程序结构 复合结构:多种程序结构的组合. P116. 循环的初始状态. 初始化. 循 环 体. 循环的工作部分及修改部分. 修改部分. 计数控制 特征值控制 地址边界控制. Y. 循环控制 条件. N. 结. 束. 4.1 循环程序设计. P117. 1 2 3

Download Presentation

第四章 汇编语言程序设计基础

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. …… 第四章 汇编语言程序设计基础 基本程序结构: 顺序结构 循环结构 分支结构 子程序结构 复合结构:多种程序结构的组合 P116

  2. 循环的初始状态 初始化 循 环 体 循环的工作部分及修改部分 修改部分 计数控制 特征值控制 地址边界控制 Y 循环控制 条件 N 结 束 4.1 循环程序设计 P117

  3. 1 2 3 4 例1. 把BX中的二进制数以十六进制的形式显示在屏幕上。 BX

  4. 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

  5. 例2. 将正数n插入一个已整序的字数组的正确位置。 • 算法: 将数组中数逐个与N比较,Si为指针 • 若N<Ki,则Ki下移一个单元 • 若NKi,则插在Ki的下一个单元,并结束 • 临界条件: • 若NKn,则插入Kn的下一个单元 • 若N<K1,则K1~Kn后移一个单元, N插在第一个单元 • 循环控制: • 计数控制 元素个数=((字末地址-字首地址) / 2) +1 字数 = (字节末地址-字节首地址) +1 字节数 • 地址边界控制 结束地址为ARRAY_HEAD • 特征值控制: 表示结束条件的值

  6. x -1 3 5 49 15 52 23 37 105 99 78 65 32 n • 例2.将正数n插入一个已整序的字数组的正确位置。 • x dw ? • array_head dw 3,5,15,23,37,49,52,65,78,99 • array_end dw 105 • n dw 32 • 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

  7. 例3将首地址为A的字数组从小到大排序(气泡算法,多重循环)例3将首地址为A的字数组从小到大排序(气泡算法,多重循环) • A dw 32,85,16,15, 8 P119

  8. mov cx, 10 • dec cx • loop1: mov di, cx • mov bx, 0 • loop2: • mov ax, A[bx] • cmp ax, A[bx+2] • jle continue • xchg ax, A[bx+2] • mov A[bx], ax • continue: • add bx, 2 • loop loop2 • mov cx, di • loop loop1

  9. 判定条件 判定条件 4.2 分支程序设计 P121 A B A B … X (1)两路分支结构 (2)多路分支结构

  10. case 1 case 2 case n case 1 case 2 case 3 ? ? (1)逻辑尺控制 (2)条件控制 (3)地址跳跃表 TABLE DW ONE, TWO, THREE JMP TABLE[SI] … 1000 ONE: … 2000 TWO: … 3000 THREE: … 。。。。。。

  11. 例1.设有数组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 加法

  12. 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

  13. 例2.根据AL寄存器中哪一位为1(从低位到高位)把程序例2.根据AL寄存器中哪一位为1(从低位到高位)把程序 转移到8个不同的程序分支去 。(寄存器间接寻址) • cmp al, 0 • je continue • lea bx, branch_table • L: shr al, 1 ;逻辑右移 • jnc add1 • jmp word ptr [bx] • ;段内间接转移 • add1: • add bx, 2 • jmp L • continue: …… • routine1: …… • routine2: …… • …… branch_table dw routine1 dw routine2 dw routine3 dw routine4 dw routine5 dw routine6 dw routine7 dw routine8

  14. 4.3 子程序的设计方法 • 过程(子程序)定义伪操作 • procedure_name PROC NEAR ( FAR) • …… • procedure_name ENDP • (1)NEAR属性:调用程序和子程序在同一代码段中 • (段内调用) • (2)FAR属性:调用程序和子程序不在同一代码段中 • (段间调用) P123

  15. 保存与恢复寄存器 • subt proc far • push ax • push bx • push cx • push dx • ...... • pop dx • pop cx • pop bx • pop ax • ret • subt endp

  16. (SP)→ (IP) (SP)→ (IP) (CS) 子程序的调用和返回 • 子程序调用(中断调用):隐含使用堆栈保存返回地址 • call near ptr subp • (1) 保存返回地址 • (2) 转子程序 • (IP) ← subp的偏移地址 • call far ptr subp • (1) 保存返回地址 • (2) 转子程序 • (CS) ← subp的段地址 • (IP) ← subp的偏移地址

  17. (SP)→ (IP) (CS) (FLAGS) int 21H INT n(n : 中断类型号) (1) 保存现场和返回地址(FLAGS,CS,IP入栈) (2) 转中断处理程序 (IP) ← (n*4) (CS) ← (n*4+2) 子程序返回: (1)ret (返回地址出栈) (2)iret(IP,CS,FLAGS出栈)

  18. 子程序的参数传送 (1)通过寄存器传送参数 (2)通过存储区传送参数 *子程序和调用程序在同一程序模块中,则子程序可 直接访问模块中的变量。 *子程序和调用程序不在同一程序模块中,则有两种 传送方式:建立公共数据区和使用外部符号。 (3)通过地址表传送参数地址 (4)通过堆栈传送参数或参数地址 P124 P125 P127

  19. 例3. 十进制到十六进制的转换程序(通过寄存器传送变量) • Decihex segment ; 1016 • assume cs: decihex • main proc far • push ds • sub ax, ax • push ax • repeat: call decibin ; 102 • call crlf • call binihex ; 216 • call crlf • jmp repeat • ret • main endp

  20. Decibin proc near ; 102 • mov bx, 0 • newchar: mov ah, 1 • int 21h • sub al, 30h • jl exit ; <0退出 • cmp al, 9d • jg exit ; >9退出 • cbw • xchg ax, bx • mov cx, 10d • mul cx • xchg ax, bx • add bx, ax • jmp newchar • exit: ret • decibin endp

  21. binihex proc near ; 216 mov ch, 4 rotate: mov cl, 4 rol bx, cl mov al, bl and al, 0fh add al, 30h cmp al, 3ah jl printit add al, 7h ; ‘A’~’F’ printit: mov dl, al mov ah, 2 int 21h dec ch jnz rotate ret binihex endp

  22. crlf proc near mov dl, 0dh mov ah, 2 int 21h mov dl, 0ah mov ah, 2 int 21h ret crlf endp decihex ends end main

  23. 例4. 累加数组中的元素(直接访问变量) • data segment • ary dw 1,2,3,4,5,6,7,8,9,10 • count dw 10 • sum dw ? • data ends • code segment • main proc far • assume cs:code, ds:data • start: • push ds • sub ax, ax • push ax • mov ax, data • mov ds, ax • call near ptr proadd • ret • main endp

  24. proadd proc near • push ax • push cx • push si • lea si, ary • mov cx, count • xor ax, ax • next: add ax, [si] • add si, 2 • loop next • mov sum, ax • pop si • pop cx • pop ax • ret • proadd endp • code ends • end start

  25. 如果数据段定义如下: data segment ary dw 1,2,3,4,5,6,7,8,9,10 count dw 10 sum dw ? ary1 dw 10,20,30,40,50,60,70,80,90,100 count1 dw 10 sum1 dw ? data ends *如果直接访问内存变量,那么累加数组ary和数组ary1中的元素不能用同一个子程序proadd

  26. 例5 . 累加数组中的元素(通过地址表传送变量地址) • data segment • ary dw 10,20,30,40,50,60,70,80,90,100 • count dw 10 • sum dw ? • table dw 3 dup (?) ; 地址表 • data ends • code segment • main proc far • assume cs:code, ds:data • start: push ds • sub ax, ax • push ax • mov ax, data • mov ds, ax • mov table, offset ary • mov table+2, offset count • mov table+4, offset sum • mov bx, offset table • call proadd • ret • main endp

  27. proadd proc near • push ax • push cx • push si • push di • mov si, [bx] • mov di, [bx+2] • mov cx, [di] • mov di, [bx+4] • xor ax, ax • next: add ax, [si] • add si, 2 • loop next • mov [di], ax • pop di • pop si • pop cx • pop ax • ret • proadd endp • code ends • end start ary 10 0000 60 30 40 80 50 90 100 0014 0016 70 20 0002 count 10 0014 sum  ? 0016 table 0000 0018 (bx) (si) (di)

  28. 例6 . 累加数组中的元素(通过堆栈传送变量地址) • data segment • ary dw 10,20,30,40,50,60,70,80,90,100 • count dw 10 • sum dw ? • data ends • stack segment • dw 100 dup (?) • tos label word • stack ends

  29. code1 segment • main proc far • assume cs:code1, ds:data, ss:stack • start: • mov ax, stack • mov ss, ax • mov sp, offset tos • push ds • sub ax, ax • push ax • mov ax, data • mov ds, ax • mov bx, offset ary • push bx • mov bx, offset count • push bx • mov bx, offset sum • push bx • call far ptr proadd • ret • main endp • code1 ends

  30. (si) (cx) (ax) (ip) (cs) 0 (ds) (sp)  (di) (bp)  (bp) (bp)+6 0016 (bp)+8  0014 (bp)+0a  0000 • xor ax, ax • next: add ax, [si] • add si, 2 • loop next • mov [di], ax • pop di • pop si • pop cx • pop ax • pop bp • ret 6 • proadd endp • code2 ends • end start code2 segment assume cs: code2 proadd proc far push bp mov bp, sp push ax push cx push si push di mov si, [bp+0ah] mov di, [bp+8] mov cx, [di] mov di, [bp+6]

  31. 例8 十六进制到十进制的转换程序(通过寄存器传送变量) • hexidec segment; 1610 • main proc far • assume cs: hexidec • start: • push ds • sub ax, ax • push ax • repeat: • call hexibin ; 162 • call crlf • call binidec ; 210 • call crlf • jmp repeat • ret • main endp

  32. hexibin proc near ; 162 • mov bx, 0 • newchar: • mov ah, 1 • int 21h • sub al, 30h • jl exit • cmp al, 10d • jl add_to • sub al, 27h ; ‘ a ’ ~ ‘ f ’ • 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 newchar • exit: ret • hexibin endp

  33. binidec proc near ; 210 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 binidec endp 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

  34. crlf proc near mov dl, 0ah mov ah, 2 int 21h mov dl, 0dh mov ah, 2 int 21h ret crlf endp hexidec ends end start

  35. 4.4 I/O程序设计 P135 1. I/O设备的数据传送方式 程序控制方式(查询方式) CPU利用指令反复查询I/O的状态,直到I/O准备好,才进行输入/输出。此间CPU处于循环等待状态,未做有效的工作。 中断方式 CPU在执行程序的同时兼顾对I/O设备的控制或数据传送。当I/O设备准备好(空闲),由I/O通知CPU暂停正在运行的程序,转而处理I/O设备的请求,处理完即返回主程序继续执行。 DMA方式(直接存储器存取方式/成组传送方式) 主要适用于高速I/O设备(如磁盘),CPU向I/O接口提供控制信息(如数据块的首地址及字节数),I/O设备直接和存储器进行成批数据的快速传送。

  36. 2. 程序直接控制I/O方式 • I/O端口 • 外设接口由一组寄存器(数据寄存器/状态寄存器/命令寄存器)组成,每个寄存器有一个端口地址(端口号),IBM-PC机的I/O地址空间可达64K(0000~FFFFH)。 • I/O指令 • 主机与外设进行通信的最基本途径。DOS功能调用和BIOS例行程序中的输入/输出功能也是由IN和OUT指令完成的。 • 例:测试某状态寄存器(端口号27H)的第2位是否为1 • IN AL, 27H • TEST AL, 00000100B • JNZ ERROR P136

  37. 设备控制寄存器 1 0 端口61H 1 / 0 0 2号定时器门控 控制其它外部设备 与门 放大器 例1. Sound程序 mov dx, 6000 ;声音频率 in al, 61h and al, 11111100b trig: xor al, 00000010b out 61h, al mov cx, 1000 ;声音延迟 delay: loop delay dec dx jne trig P137

  38. 例2.CPU要从3个设备轮流输入数据,设备1,2,3的状态寄存器例2.CPU要从3个设备轮流输入数据,设备1,2,3的状态寄存器 • 端口号分别用STAT1,STAT2,STAT3表示,第5位是输入 • 准备位。 • INPUT: IN AL, STAT1 • TEST AL, 20H ;0010 0000b • JZ DEV2 • CALL FAR PTR PROC1 • DEV2: IN AL, STAT2 • TEST AL, 20H • JZ DEV3 • CALL FAR PTR PROC2 • DEV3: IN AL, STAT3 • TEST AL, 20H • JZ NO_INPUT • CALL FAR PTR PROC3 • NO_INPUT: • ……

  39. 非屏蔽中断请求 8259A 08 IR0 系统定时器 09 可编程中断控制器 IR1 键盘 2 NMI 0A IR2 彩色/图形接口 INTR 0B 中断逻辑 IR3 保留 CPU 0C IR4 串行通讯口 0D IR5 保留 n 4 0 1 0E IR6 软盘 INT n INTO 除法错 单步 0F IR7 打印机 (PIC) 3. 中断程序设计 中断源:引起中断的事件 外中断(硬中断):外设的I/O请求 —— 可屏蔽中断 电源掉电/奇偶错 —— 非屏蔽中断 内中断(软中断):INT指令/CPU错(除法错、溢出) P140

  40. 中断操作的5个步骤: (1) 取中断类型号 (2) 计算中断向量地址 (3) 取中断向量,偏移地址送IP,段地址送CS (4) 转入中断处理程序 (5) 中断返回到INT指令的下一条指令 • 例:BIOS中断 INT 4AH (P.136 图4.13) • 4AH4 = 128H • 4AH4+2 = 12AH • (128H)  IP • (12AH)  CS P143

  41. 类型0的(IP) 00000 类型0的(CS) 类型1的(IP) 00004 类型1的(CS) 类型N的(IP) 4*N 类型N的(CS) 类型255的(IP) 003FC 类型255的(CS) 中断向量表 IBM-PC中断系统能处理256种类型的中断,类型号为0~0FFH。中断向量表是各种中断处理程序的地址表。

  42. DOS功能调用(21H)存取中断向量 • 设置中断向量: • AH=25H • AL=中断类型号 • DS:DX=中断向量 • INT 21H • 取中断向量: • AH=35H • AL=中断类型号 • INT 21H • 返回时送ES:BX=中断向量

  43. 例1 用DOS功能调用存取中断向量 • MOV AL, N • MOV AH, 35H • INT 21H ; 取原中断向量 • PUSH ES • PUSH BX ; 保存原中断向量 • PUSH DS • MOV AX, SEG INTHAND • MOV DS, AX • MOV DX, OFFSET INTHAND • MOV AL, N • MOV AH, 25H • INT 21H ; 设置新的中断向量 • POP DS • …… • POP DX • POP DS • MOV AL, N • MOV AH, 25H • INT 21H ; 恢复原中断向量 • RET • ; • INTHAND: …… • IRET

  44. 7 6 5 4 3 2 1 0 中断屏蔽寄存器21H 打印机 键 盘 定时器 中断程序的编写步骤: 主程序:(1) 设置中断向量 ( DOS调用 AH=25H, AH=35H ) (2) 设置CPU中断允许位 FLAGS中的IF位=1允许中断 (STI 开中断) =0 禁止中断 (CLI 关中断) (3) 设置中断屏蔽位 I/O端口21H 中断屏蔽寄存器 中断屏蔽位=0 允许中断 =1 禁止中断

  45. 7 6 5 4 3 2 1 0 EOI 中断命令寄存器20H • 中断处理子程序: • 保存工作寄存器 (PUSH) • 开中断( STI ) • 中断处理功能 • 关中断( CLI ) • 送中断结束命令( EOI ,仅对硬中断) • 恢复工作寄存器( POP) • 中断返回( IRET ) MOV AL, 20H OUT 20H, AL

  46. 例2 .编写一个中断处理程序,要求在主程序运行期间,每隔 10秒响铃一次,同时显示‘The bell is ring!’ • dseg segment • count dw 1 • mess db 'The bell is ring!',0ah,0dh,'$' • dseg ends • cseg segment • main proc far • assume cs:cseg, ds:dseg, es:dseg • start: • push ds • mov ax, ax • push ax • mov ax, dseg • mov ds, ax P147

  47. mov al, 1ch mov ah, 35h int 21h; 取原中断向量 push es push bx ; 保存原中断向量 push ds mov dx, offset ring mov ax, seg ring mov ds, ax mov al, 1ch mov ah, 25h int 21h; 设置新的中断向量 pop ds in al, 21h and al, 11111110b out 21h, al; 设置中断屏蔽位,允许定时器中断 sti ; 开中断

  48. mov di, 2000 delay: mov si, 3000 delay1: dec si jnz delay1 dec di jnz delay; 主程序工作(期间每秒产生中断18.2次) pop dx pop ds mov al, 1ch mov ah, 25h int 21h; 恢复原中断向量 ret main endp P148

  49. ring proc far • push ds • push ax • push cx • push dx • mov ax, dseg • mov ds, ax • sti ; 开中断,允许更高级的中断 • dec count • jnz exit • mov dx, offset mess • mov ah, 09 • int 21h; 显示‘The bell is ring!’

  50. mov dx, 100 in al, 61h and al, 11111100b sound: xor al, 2 out 61h, al mov cx, 140h wait1: loop wait1 dec dx jne sound; 响铃 mov count, 182 exit: cli ; 关中断 pop dx pop cx pop ax pop ds iret ring endp cseg ends end start P149

More Related