汇编语言第6章 子程序设计
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
寄存器传递参数: AX
要求从键盘输入一个0~65535之间的十进制数,然后把该 数以十六进制的形式在屏幕上显示出来。
decihex segment assume cs:decihex repeat: call decibin call crlf call binihex call crlf jmp repeat mov ah,4ch int 21h
显示字节ARRAY中的值 ... mov bx,offset array mov cx,count displp:mov al,[bx] call aldisp mov dl,2CH ;显示一个逗号,分隔数据 mov ah,2 int 21h inc bx loop displp .exit 0
aldisp proc push ax push cx push dx push ax mov dl,al mov cl,4 shr dl,cl or dl,30h cmp dl,39h jbe aldisp1 add dl,7 aldisp1:mov ah,2 int 21h
;对cry数组的计算
寄存器传递参数:AX,BX,CX
子程序名:proadd ;功能:数组求和子程序 ;入口参数:BX带数组的首地址,CX带数组长度 ;出口参数:AX存数组的累加和
proadd proc mov ax, 0 next: add ax, [bx] inc bx inc bx loop next ret proadd endp code ends end start
; 键盘输入十进制数, 转二进制
;回车换行
;二进制转十六进制, 输出 ;回车换行
;无限循环CTRL-C中断执行
寄存器传递参数: BX
;十进制转换为二进制 decibin proc near mov bx, 0 newchar:mov ah, 1 int 21h sub al, 30h jl exit cmp al, 9d jg exit cbw xchg ax, bx mov cx, 10d mul cx xchg ax, bx add bx, ax jmp newchar exit: ret decibin endp
mov bx, offset bry mov cx, count2 call proadd mov sum2, ax
mov bx, offset cry mov cx, count3 call proadd mov sum3, ax mov ah, 4ch int 21h main endp
;对bry数组的运算
子程序的编程原则
按功能进行模块分解
主子程序分别画流程图
写子程序说明
子程序名 百度文库能 入口/出口参数等
显示回车换行子程序
DISPODOA PROC PUSH AX PUSH DX MOV AH,2 MOV DL,0DH INT 21H MOV AH,2 MOV DL,0AH INT 21H POP DX POP AX RET DISPODOA ENDP
段内返回 段间返回 段内或段间带参 数返回
MAIN
2000:2500
CALL FAR ptr PA
PA
0500:1000
RET
SP
00 10
CS = 2000 IP = 2500
00 05
子程序的调用指令
格式: CALL 过程名
过程名就是子程序入口地址,即子程序第一条指令的首字 节地址
CALL指令寻址方式 段内直接寻址 段内间接寻址 段间直接寻址 段间间接寻址
寻址方式
段内直接调用
CALL FAR PTR DST CALL DST 如: CALL BX
SP=SP-2;[SP]=返回地址的段地址 SP=SP-2;[SP]=返回地址的偏移值 IP=DST的偏移地址,CS=DST的段地址
SP=SP-2;[SP]=CALL指令的下一条指 令的IP值 IP=DST中的有效地址EA(IP=BX)
段间直接调用
段内间接调用
SP=SP-2;[SP]=返回地址的段地址 CALL DST SP=SP-2;[SP]=返回地址的偏移值 如: CALL DWORD PTR[BX] IP=EA的低16位,CS=EA的高16位
段间间接调用
RET RETF RET n
IP=[SP],SP=SP+2 IP=[SP], SP=SP+2 CS=[SP],SP=SP+2 IP=[SP], SP=SP+2(段内) CS=[SP],SP=SP+2(段间) SP=SP+n
寄存器传递 存储器传递 地址表传递
参数较少
堆栈传递
参数较多
求带符号的字数组的最大值
. model small .data count dw 5 array dw 8,-1,56,0,100 max dw ? .code .startup lea si,array mov cx,count dec cx call findmax mov max,ax mov ah,4ch int 21h findmax proc mov ax, [si] next: cmp ax, [si+2] jge skip mov ax, [si+2] skip: add si, 2 loop next ret findmax endp code ends end
寄存器传递参数AX,BX,CX
从键盘上输入一个字符串,存入INPUT中,要求 以回车作为输入的结束,字符结尾部分添加0
CALL DST CALL BX CALL FAR PTR DST CALL DWORD PTR[BX]
返回指令
格式: RET/ RETF/ RET n 寻址方式:
段内返回 段间返回
说明:
CALL和RET指令的属性
过程是有类型的,缺省情况下是NEAR类型 CALL和RET 指令的操作也是有类型的
;具有缺省属性near的subname过程 ;保护寄存器:顺序压入堆栈
;ax/ bx/ cx仅是示例
;过程体 子程序中使用了AX, BX,CX
;恢复寄存器:逆序弹出堆栈
;过程返回 ;过程结束
子程序的调用与返回指令
指令格式
CALL DST
① 断点入栈 ② 转子程序
指令功能
SP=SP-2;[SP]=CALL指令的下一条指 令的IP值; IP=IP+D16
;实现al内容的显示
;转换al的高4位
;al高4位变成3
;是0Ah~0Fh,还要加上7 ;显示
pop dx ;恢复原ax值到dx and dl,0fh ;转换al的低4位 or dl,30h cmp dl,39h jbe aldisp2 add dl,7 aldisp2:mov ah,2 ;显示 int 21h pop dx pop cx pop ax ret aldisp endp
调用程序和子程序不在同一个代码段
CODE1 SEGMENT … SUBR1 PROC FAR … RET SUBR1 ENDP … CALL SUBR1 … CODE1 ENDS CODE2 SEGMENT … CALL FAR PTR SUBR1 … CODE2 ENDS
子程序调用方式举例
DATA SEGMENT NPROC DW NEARP FPROC DD FARP DATA ENDS CODE1 SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX CALL NEARP ;段内直接 LEA AX,NEARP CALL AX ;段内间接 LEA BX,NPROC CALL WORD PTR[BX] ;段内间接
CALL FAR PTR FARP LEA BX,FPROC CALL DWORD PTR[BX] MOV AH,4CH INT 21H NEARP PROC NEAR …… RET NEARP ENDP CODE1 ENDS END START
;段间直接
;段间间接
CODE2 SEGMENT ASSUME CS:CODE2 FARP PROC FAR …… RET FARP ENDP CODE2 ENDS ……
如果定义的过程是FAR属性的,那么对它的调用和 返回一定都是FAR属性的。(断点的保存和弹出都 是32位的)。 如果定义的过程是NEAR属性的,那么对它的调用 和返回一定都是NEAR属性的。(断点的保存和弹出 都是16位的)。
子程序和调用程序之间的调用形式
1、调用程序和子程序在同一个代码段 CODE SEGMENT ASSUME CS:CODE …… CALL SUBR1 …… SUBR1 PROC …… RET SUBR1 ENDP CODE ENDS
NEAR属性(段内近调用)的过程只能被相 同代码段的其他程序调用 FAR属性(段间远调用)的过程可以被相同 或不同代码段的程序调用
子程序的常见格式
subname proc push ax push bx push cx … pop cx pop bx pop ax ret subname endp
stack_seg segment para 'stack' dw 100 dup(?) tos label word ;label是定义变量类型的伪指令 stack_seg ends
寄存器传递参数
code main
segment proc far assume cs:code;ds:parm_seg;ss:stack_seg start: mov ax, stack_seg mov ss, ax mov sp, offset tos ;定义堆栈指针 mov ax, parm_seg mov ds, ax mov bx, offset ary ;对ary数组的运算 mov cx, count1 call proadd mov sum1, ax 寄存器传递参数:AX,BX,CX
;二进制转换为十六进制 binihex proc near mov ch, 4 rotate: mov cl, 4 rol bx, cl ;小循环左移4位 mov al, bl and al, 0fh add al, 30h cmp al, 3ah jl printit add al, 07h printit : mov dl, al mov ah, 2 int 21h dec ch jnz rotate ret binihex endp 寄存器传递参数BX
子程序设计中的现场保护和恢复
保护现场和恢复现场是指保护和恢复CPU 内部的通用寄存器。
哪些必须保护? 哪些不必保护? 哪些不应该保护?
子程序的参数传递
入口参数(输入参数)
主程序提供给子程序
出口参数(输出参数)
子程序返回给主程序
参数的形式:
① 数据本身 (传值) ② 数据的地址(传址)
参数的传递
第六章
子程序设计
子程序的定义
子程序
把功能相对独立的程序段单独编写和 调试,作为一个相对独立的模块供程 序使用,就形成子程序
特点
实现源程序的模块化 简化源程序结构 提高编程效率
主要内容
过程定义伪指令
参数传递是子程序设计的重点和难点
子程序可以嵌套
子程序的定义
过程定义伪操作 过程名 PROC [NEAR]|FAR ... RET 不能缺少! 过程名 ENDP
proc near ;回车换行子程序 mov dl, 0dh mov ah, 2 int 21h mov dl, 0ah mov ah, 2 int 21h ret crlf endp decihex ends end crlf 寄存器传递参数
有Ary、bry、cry三个字数组,长度任意。分别求各数组 中所有元素之和,送sum1、sum2、sum3单元中,求数 组累加和用proadd过程实现。 parm_seg segment ary dw 7,8,9,11,100 count1 equ ($-ary)/2 sum1 dw ? bry dw 101,11,25,46,77,9,3,121,18 count2 equ ($-bry)/2 sum2 dw ? cry dw 5,3,9,15,99,1,2,4,7,10 count3 equ ($-cry)/2 sum3 dw ? parm_seg ends 寄存器传递参数:BX,CX,AX