第六章子程序结构6.1 子程序的设计方法
过程(子程序)定义伪操作
procedure_name PROC NEAR ( FAR )
……
procedure_name ENDP
(1)NEAR属性:调用程序和子程序在同一代码段中
(段内调用)
(2)FAR属性:调用程序和子程序不在同一代码段中
(段间调用)
保存与恢复寄存器
subt proc far
push ax
push bx
push cx
push dx
......
pop dx
pop cx
pop bx
pop ax
ret
subt endp
子程序的调用和返回
子程序调用(中断调用):隐含使用堆栈保存返回地址call near ptr subp
(1) 保存返回地址
(2) 转子程序
(IP) ←subp的偏移地址
call far ptr subp
(1) 保存返回地址
(2) 转子程序
(CS) ←subp的段地址
(IP) ←subp的偏移地址
子程序的变量传送
(1)通过寄存器传送变量
(2)通过存储器传送变量
*子程序和调用程序在同一程序模块中,则子程序可
直接访问模块中的变量。
*子程序和调用程序不在同一程序模块中,则有两种
传送方式:建立公共数据区和使用外部符号。
(3)通过地址表传送变量地址
(4)通过堆栈传送变量或变量地址
例6.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
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
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
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
例6.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
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
如果数据段定义如下:
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
例6.4 累加数组中的元素(通过堆栈传送变量地址)
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
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
结构预置语句:把结构中各字段的数据存入存储器,
并可重新输入字符串和数值。
格式:变量名结构名< >
变量名结构名<预赋值说明>
例:S991000 STUDENT_DAT A < >
S991001 STUDENT_DAT A <, 1001, 22, >
STUDENT STUDENT_DATA 100 DUP (< >) 访问结构数据变量:
MOV AL, https://www.wendangku.net/doc/6b16336922.html,[SI]
MOV AL, [BX].NAME[SI]
MOV AL, STUDENT+4*https://www.wendangku.net/doc/6b16336922.html,[SI]
例6.4 累加数组中的元素(通过堆栈传送变量地址)
stack_strc struc
save_bp dw ?
save_cs_ip dw 2 dup (?)
par3_addr dw ?
par2_addr dw ?
par1_addr dw ? stack_strc ends
6.3 子程序举例
例6.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
hexibin proc near ; 16→2
mov bx, 0
newchar:
mov ah, 1
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
crlf proc near
mov dl, 0ah
mov ah, 2
int 21h
mov dl, 0dh
mov ah, 2
int 21h
ret
hexidec ends
end start
第六章作业
Page 177~182
6.4 6.5 6.9
6.13
期中作业:
(1) Hanoi塔的递归程序
(2) Fibonacci数的递归程序
(3) 字符串反序输出递归程序的改写(用STRUC伪操作)
(4) 十六进制转换成十进制程序的改写(‘a’~‘f’、‘A’~‘F’都接收)
(1)~(4)要求:* 源码
* 相应的输入/输出或Debug下的显示信息
(5) 在屏幕上显示20000以内的素数及其个数
要求:* 采用子程序结构
* 源码及相应注释
* 用BASIC和C完成相同的功能,比较它们的执行时间,
并对结果做适当分析
DOS功能调用INT 21H
用户在程序中调用DOS提供的一些子功能:
(1)一般设备的输入输出
(2)磁盘的输入输出及磁盘文件的管理
(3)其它
调用方法:
(1)设置调用参数
(2)MOV AH, 功能号
(3)INT 21H
(1)DOS键盘功能调用( AH=1,6,7,8,A,B,C )
例:单字符输入( AH=1 )
get-key: mov ah, 1
int 21h
cmp al, ‘Y’
je yes
cmp al, ‘N’
je no
jne get_key yes:
……
no:
……
(2)DOS显示功能调用( AH=2,6,9 )
例:显示单个字符( AH=2 )
mov ah, 2
mov dl, ‘A’
int 21h
例:显示字符串( AH=9 )
string db ‘HELLO’, 0dh, 0ah, ‘$’mov dx, offset string
mov ah, 9
int 21h
(3)DOS打印功能( AH=5 )