汇编-子程序参数传递的三种方式-寄存器法,堆栈法,参数赋值法【详述后两者】

汇编-子程序参数传递三种方式:
寄存器法,堆栈法,参数赋值法

子程序结构如下:

名称   PROC   FAR|NEAR

;DO SOMETHING

RET  [N];返回断点地址,N可忽略,加了必须对SP进行  平栈  操作

名称 ENDP

结合此结构,我们来看,

1.寄存器法

这个方法最简单易用,但是要注意对寄存器的选择,一般选ABCD[X]通用寄存器就可以了。
步骤如下:

1.通过MOV指令将参数存到寄存器

2.再在子程序中调用寄存器即可【注意保护寄存器】

样例就不给了。

2.堆栈法

过程是:

1.先将参数入栈
2.然后在子程序中使用SP,BP,SI这三个寄存器,对栈值(参数)进行取出利用

样例如下:

参数压栈:

 	MOV CX,01H
    ; 压入初始奇数1参数
    PUSH CX
    ; 压入结束参数50
    MOV CX,50
    PUSH CX

子程序参数利用:

 	; 利用栈指针SP取栈值
    MOV BP,SP
    ; 取结束参数50,字
    ; 栈底是高地址段
    MOV AX,[BP+2]
    ; 取初始参数1
    MOV BX,[BP+4]

注意:
在利用寄存器取值时要注意参数存储的物理结构,本例参数都是字变量,所以以2为单位进行取值
栈的地段的地址段会越来越高
既是:例如取栈顶时:
应当取SP+2,当然写成[SP+2]是错的,
需要:[BP+2]

如上例。

3.参数赋值法

这一个最是麻烦,但是用会了也就没什么了。

原理如下:
代码段CS定义变量进行参数存储,然后供各个程序模块【子程序,同一源文件】使用【特殊的存取】。
参数存放到CALL指令后的一串单元中,子程序通过返回地址【断点地址】存取参数并修改返回地址

步骤是:
CALL指令调用后,在CS定义自己的数据参数
然后利用SP,BP获取CALL指令执行后的断点地址
此时断点地址后就是对应的参数区
可通过SI取得对应参数

最后在RET前修改栈顶的值为参数区后的地址值【不强制规定,但一般都是】,
做PUSH(一定要先将原断点POP)
就能越过参数区做下一步操作

样例如下:

对参数的定义,

    ; call求和子程序
    CALL sumsub
    ; 参数定义
    NUM DW 50;结束参数
        DW 1;初始奇数
    ; 输出
    NEXT: CALL pf

子程序调用参数:

 ; 获取断点地址做SI
    MOV BP,SP

    MOV SI,[BP]

    ; 取代码段中变量
    ;结束50
    MOV AX,CS:[SI+0]
    ; 开始1
    MOV BX,CS:[SI+2]
    
    ;
    ;
    ;参数利用
    ;
    ;
	
	;修改当前断点【修改栈顶的地址断点】
	;清除默认断点地址
	
	POP CX

	;取自己要执行的断点位置地址
	MOV CX,OFFSET NEXT
    
    ;修改
    PUSH CX
RET

注意:
NEXT是程序返回后要执行的位置【在参数定义后】

CX不做固定,根据自己需要可以更换寄存器,只是不能使得入栈的变量是一个立即数罢了。

在子程序取得了当前执行断点后,开始取定义在CS中的参数,
需要修改默认段基址DS为CS

完。
可能写的不好,但还是求赞!
努力!

  • 16
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值