子程序

结构流程图
main proc
子程序调用语句(EIP自动的由主程序指向子程序)→执行子程序段

子程序返回主程序return
流程图

调用与返回指令
1、段内调用与返回指令
段内直接调用
指令格式:CALL OPR;
OPR为子程序名;
执行操作:PUSH(EIP) (EIP)←(EIP)+D32
段内间接调用
指令格式:CALL WORD OPR;
OPR为寄存器或存储器地址;OPR可为除立即数意外的任何寻址方式;
执行操作:PUSH(EIP) (EIP)←(EA)
段内返回指令
指令格式:RET
执行操作:(EIP)←POP()
段内带立即数返回
指令格式:RET EXP;
执行操作:(ESP)←(ESP)+16位位移量
2、段间调用与返回指令
段间直接调用
指令格式:CALL FAR PTR OPR 或 CALL OPR
OPR为子程序名
执行操作:PUSH(CS),PUSH(EIP) 、(EIP) ← DST指定的偏移地址、(CS) ← DST指定的段地址
段间间接调用
指令格式:CALL DWORD OPR
EA由OPR的存储器寻址方式确定的有效地址
执行操作:PUSH(CS),PUSH(EIP) ,(EIP) ← (EA),(CS) ← (EA+4)
段间返回指令
指令格式:RET
执行操作:(EIP) ←POP( ),(CS) ←POP( )
段间带立即数返回
指令格式:RET EXP
执行操作:(EIP) ←POP( ),(CS) ←POP( ),(ESP) ←(ESP)+16位移量
子程序定义指令
格式:过程名 PROC [NEAR/FAR]
……
RET
……
过程名 ENDP
功能:子程序的定义
定义的过程必须在一个逻辑段内
类型属性隐含为NEAR,一个过程中至少有一个RET语句,可在任意位置,但是必须是最后一条执行

例 将字符串信息显示功能设计成子程序(16位指令)
Print_message  PROC
PUSH  AX
MOV  AH, 09H
INT 21H
POP  AX
RET
Print_message  ENDP
MAIN PROC
……
MOV  DX,OFFSET NUM
CALL   Print_message
……
MAIN ENDP

子程序的参数传递
参数传递的方式:
1、寄存器传递参数(参数多时不能使用)
2、变量传递(过程和调用程序在同一源文件)
3、通过地址表传递参数
4、通过堆栈传送参数或参数地址
5、通过外部模块调用传递参数

例 计算两个八位二进制数的和并保存、输出
addp:求两个八位二进制数的和;
writeint:输出和;
Include irvine32.inc
.Data 
dat  db 12h,0afh 
sum dw ?
.Code
Main proc far
xor   eax, eax
xor   ebx, ebx
mov  al, byte ptr dat
mov  bl, byte ptr dat+1
call   addp
mov  word ptr sum,ax
call   writeint
exit 
Main  endp
addp  proc   near 
add al, bl
adc ah,0
ret
addp  endp
End  main
例 求数组的累加和
include irvine32.inc  
.data
ary dw 10,20,30,40,50,60,70,80,90,100
count dw  10
sum dw  ?
.code
proadd proc near
push eax
push ecx
push esi
mov  ax,0
lea esi, ary
movzx ecx,word ptr count
Next: 
add ax,word ptr  [esi]
add esi,2
loop  next
mov  word ptr sum, ax
pop esi 
pop ecx
pop eax   
ret
proadd endp
main proc
call proadd
movzx eax,word ptr sum
call WriteHex
exit
main endp
end  main

用地址表传递参数
建立一个地址表,存放所有参数的地址,传递地址表的首地址给过程

例 累加数组中的元素(通过地址表传送参数地址)
include irvine32.inc  
.data
ary dw 10,20,30,40,50,60,70,80,90,100
count dw 10
sum dw ?
table dd 3 dup (?) ; 地址表
.code  
main proc far
mov table,offset ary
mov table+4,offset count
mov able+8, offset sum
mov ebx, offset table
call proadd
exit
main endp   
proadd proc near
push eax
push ecx
push esi
push edi
mov  esi,dword ptr [ebx]
mov  edi, dword ptr[ebx+4]
xor ecx,ecx
mov cx, word ptr [edi]
mov edi, dword ptr [ebx+8]
xor ax,ax
next:    
add   ax, word ptr [esi]
add esi, 2
loop next
mov word ptr [edi],ax
pop edi
pop esi
pop ecx
pop eax
ret
proadd endp
end main

用堆栈传递参数
调用者通过调整堆栈指针为返回参数预留空间,然后将过程所需的入口参数进栈
过程从堆栈得到入口参数,返回前将出口参数写入堆栈
调用者通过出栈得到返回参数
过程从堆栈存取参数时,通常使用EBP,因为其隐含的段地址在SS中
采用堆栈传递参数时,典型的过程结构如下:
StdProc proc near
push ebp
mov ebp, esp ; EBP指向当前栈顶,用于取入口参数
...
pop ebp
ret ParmSize;返回前从堆栈移出入口参数
StdProc endp
其中,ParmSize是过程被调用前进栈的入口参数的字节数

累加数组中的元素(通过堆栈传送参数地址)
.data
ary dw 10,20,30,40,50,60,70,80,90,100
count dw 10
sum dw ?
.Code
main proc far 
mov ebx,offset ary
push ebx
mov ebx,offset count
push ebx
mov ebx,offset sum
push ebx
call proadd
exit
main endp
proadd proc near
push ebp
mov ebp,esp
push eax
push ecx
push esi
push edi
mov esi,dword ptr [ebp+10h]
mov edi,dword ptr [ebp+0ch]
movzx ecx,word ptr [edi]
mov edi,dword ptr [ebp+8h]
xor ax,ax
next:
add ax,word ptr [esi]  
add esi,2
loop next
mov  word ptr  [edi],ax
pop edi
pop esi
pop ecx
pop eax
pop ebp
ret 12
proadd endp
end main

猜你喜欢

转载自blog.csdn.net/FZUMRWANG/article/details/79919119
今日推荐