汇编语言:子程序演练

编制子程序,求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,然后查看内存空间便可以看到存入的数据
这里写图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值