在模块化编程的过程中,用子函数的方式是很常见的一种方式,汇编语言中必然会存在这样的方式
在模块化编程中必不可少的的当然是传入的参数和返回的参数
在这里先总结一下:
1、是单参数的传递和但参数的返回
这种传递方式的基本原则就是用寄存器来传递参数,基本格式:主函数将参数送入参数寄存器,子函数从参数寄存器中读取数据;子函数将得到的结果送入结果寄存器中,主函数将结果寄存器中的数据取出来使用
下面举个例子,计算2^3:
assume cs:code
code segment
start:mov si, 2 ;si作为参数寄存器
call math ;调用子函数math
mov ax, 4C00H
int 21H
math:mov ax, si
mov bx, si
mul bx
mul bx ;mul计算完之后,这里进行的是16位乘法,所以得到的结果高位存放在dx寄存器中,低位存放在ax中,所以这里的ax和dx都是结果寄存器
ret ;回到主函数中去
code ends
end start
这里的si就是参数寄存器,dx和ax都是结果寄存器
2、多参数的传递
用寄存器的方法传递数据肯定是不靠谱的,毕竟寄存器的数量很少,所以在多参数的传递时,要用别的办法去代替
原则:先在内存中开辟两个空间,一个用来存放需要传递的参数,另一个用来存放子函数计算得到的结果
下面举一个例子,例子的内容是:用子函数计算2和3的平方,然后在主函数中可以调用计算结果放入ax和dx中,要求ax得到的是2^2=4,dx得到的是3^2=9
assume cs:code, ds:data_in, es:data_out
data_in segment ;作为输入参数开辟的空间
db 2, 3
data_in ends
data_out segment ;作为输出结果开辟的空间
dw 8 dup(0)
data_out ends
code segment
start:mov ax, data_in
mov ds, ax
mov ax, data_out
mov es, ax
mov cx, 2
mov si, 0
mov di, 0
call math ;调用子函数
mov ax, es:[0] ;将子函数得到的结果按照要求放在寄存器ax和dx中
mov dx, es:[2]
mov ax, 4C00H
int 21H
math:mov al, ds:[si]
mov bl, ds:[si]
mul bl ;做8位的乘法运算
mov es:[di], ax ;将结果放在输出结果的内存空间中
inc si
add di, 2
loop math ;因为有两个参数做一个循环
ret ;返回到主函数中去
code ends
end start
3、用栈的方式传递数据
基本原理:主函数将需要传递给子函数的参数压入栈中,子函数从栈中取得参数
下面用一个例子说明,例子要求用子程序的栈参数调用的方法计算2^3
assume cs:code
code segment
start:mov ax, 2
push ax ;先将2入栈
call math ;调用子函数
mov ax, 4C00H
int 21H
math:push bp ;将子函数用到的寄存器入栈
mov bp, sp ;在没有指明段名时,bp默认在ss段,操作的是栈
mov ax, [bp + 4] ;将栈指针指向存放2的地方
mov bp, ax ;将2给bp(给bp是因为在子程序的开始将bp入栈了,避免与主函数的寄存器冲突),为了做3次运算准备
mul bp
mul bp ;进行3次运算
pop bp ;在子函数结束前,将放入栈中的寄存器释放出来
ret 4 ;回到主函数,这里的4是指将sp+4,就是将栈指针指向初始位置,因为1和3占用了4个字节的栈空间
code ends
end start
因为进行的16位乘法运算,所以结果的低位在ax中,高位放在dx中