编制子程序,求y=x^4,自变量x为字节,应变量y可以在一个字内存放(x的值不会造成y溢出)
(1)版本1(用寄存器传递参数和结果):子程序的参数由寄存器bl提供,返回结果在ax中;
(2)版本2(用寄存器传递参数和结果,轻灵的子程序,笨重的主程序):子程序不变,主程序中提供如下数据区,在主程序中,循环调用子程序,完成y=x^4的求解,并将结果存入在相应的数据区:
data segment
x db 1,2,3,4,5,6,7,8
y dw 0,0,0,0,0,0,0,0
data ends
(3)版本3(用内存单元传递参数和结果,轻灵的主程序,功能相对强大的子程序):数据区不变,子程序完成全部8个数据的求解任务,主程序只调用一次子程序即可。数据x的起始偏移地址由si提供,存放结果的y的偏移地址,由di提供,在调用前,由主程序为子程序提供si、di值。
(4)版本4:将上面的程序按多文件的方式存放。
1.版本一源码:
assume cs:code ,ss:stack
stack segment
db 16 dup(0)
stack ends
code segment
main proc ;主程序
start:
mov ax,stack
mov ss,ax
mov sp,16 ;分配好栈
mov bl,4 ;bl提供参数4
call zi ;调用子程序zi
mov ax,4c00h
int 21h
main endp ;主程序结束
zi proc ;子程序
push cx ;cx入栈
push dx ;最后结果不会超过一个字,但运算中很可能超过一个字节,要用16位乘法,所以用到dx
push bx ;用16位乘法所以用ax,与之对应用bx,为了不影响bx在主程序中的使用将bx入栈
mov bh,0;用bx但要保证bx与bl值相同,所以设置高位为0
mov ax,1
mov cx,4;设置循环次数
s: mul bx ;乘法循环
loop s
pop dx
pop cx
pop bx ;依次出栈
ret ;返回主程序
zi endp
code ends
end start
运行结果:
2.版本二源码:
assume cs :code ,ds:data,ss:stack
data segment
x db 1,2,3,4,5,6,7,8
y dw 0,0,0,0,0,0,0,0
data ends
stack segment
db 16 dup(0)
stack ends
code segment
main proc ;主程序
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ax,data
mov ds,ax
mov si,offset x;取X符号的偏移地址赋给si
mov di,offset y;取Y符号的偏移地址赋给di
mov cx,8
c: mov bl,[si] ;将si处的内容送入bl
call zi
mov [di],ax ;将得到的最终结果放入Y符号的对应位置
inc si
add di,2 ;因为Y处对应的是字型数据,所以di要加2
loop c
mov ax,4c00h
int 21h
main endp
zi proc ;子程序
push cx ;cx入栈
push dx ;最后结果不会超过一个字,但运算中很可能超过一个字节,要用16位乘法,所以用到dx
push bx ;用16位乘法所以用ax,与之对应用bx,为了不影响bx在主程序中的使用将bx入栈
mov bh,0;用bx但要保证bx与bl值相同,所以设置高位为0
mov ax,1
mov cx,4;设置循环次数
s: mul bx ;乘法循环
loop s
pop bx
pop dx
pop cx ;依次出栈
ret ;返回主程序
zi endp
code ends
end start
运行结果:
3.版本三源码:
assume cs:code ,ds:data,ss:stack
data segment
x db 1,2,3,4,5,6,7,8
y dw 0,0,0,0,0,0,0,0
data ends
stack segment
db 16 dup(0)
stack ends
code segment
main proc
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ax,data
mov ds,ax
mov si,offset x ;取X符号的偏移地址赋给si
mov di,offset y ;取Y符号的偏移地址赋给di
call zi
mov ax,4c00h
int 21h
main endp
zi proc
push cx
push dx ;最后结果不会超过一个字,但运算中很可能超过一个字节,要用16位乘法,所以用到dx
push bx ;用16位乘法所以用ax,与之对应用bx,为了不影响bx在主程序中的使用将bx入栈
mov cx,8 ;设置外层循环次数
c: push cx
mov bl,[si];将si处的内容送入bl
mov bh,0 ;用bx但要保证bx与bl值相同,所以设置高位为0
mov ax,1
mov cx,4 ;设置内层循环次数
s:mul bx ;乘法循环
loop s
mov [di],ax;将得到的最终结果放入Y符号的对应位置
inc si
add di,2 ;因为Y处对应的是字型数据,所以di要加2
pop cx ;恢复外层循环次数
loop c
pop bx
pop dx
pop cx ;依次出栈
ret
zi endp
code ends
end start
4.版本四源码:
第一部分:
主程序(将版本3进行拆分)
extrn zi:far
assume cs:code,ds:data, ss:stack
data segment
x db 1,2,3,4,5,6,7,8
y dw 0,0,0,0,0,0,0,0
data ends
stack segment
db 16 dup (0)
stack ends
code segment
main proc
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ax,data
mov ds,ax
mov si,offset x ;取X符号的偏移地址赋给si
mov di,offset y ;取Y符号的偏移地址赋给di
call zi
mov ax,4c00h
int 21h
main endp
code ends
end start
第二部分:
子程序
public zi
assume cs:code
code segment
zi proc far
push cx
push dx ;最后结果不会超过一个字,但运算中很可能超过一个字节,要用16位乘法,所以用到dx
push bx ;用16位乘法所以用ax,与之对应用bx,为了不影响bx在主程序中的使用将bx入栈
mov cx,8 ;设置外层循环次数
c: push cx
mov bl,[si] ;将si处的内容送入bl
mov bh,0 ;用bx但要保证bx与bl值相同,所以设置高位为0
mov ax,1
mov cx,4 ;设置内层循环次数
s:mul bx ;乘法循环
loop s
mov [di],ax;将得到的最终结果放入Y符号的对应位置
inc si
add di,2 ;因为Y处对应的是字型数据,所以di要加2
pop cx ;恢复外层循环次数
loop c
pop bx
pop dx
pop cx ;依次出栈
ret
zi endp
code ends
end
先编译两个文件(4.txt和5.txt,当时写的时候暂时存在了4.txt和5.txt两个文本文件里头)
masm 4.txt;
masm 5.txt
编译通过以后,连接两个文件:
link 4.obj+5.obj
运行的时候运行主文件的exe程序即可:
4.exe,然后查看内存空间便可以看到存入的数据