博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
汇编——子程序调用参数传递的三种方式(示例程序:三个数累加求和)
阅读量:4181 次
发布时间:2019-05-26

本文共 2740 字,大约阅读时间需要 9 分钟。

一、子程序定义

子程序名      PROC     NEAR|FAR

                     .

                     .

                     RET

子程序名       ENDP

子程序名相当于标号,表示本过程的符号地址。过程有NEAR和FAR两种类型,FAR型的过程可供段间调用,NEAR型过程仅供段内调用。

在一个过程中,至少要有一条返回指令RET,它可以书写在过程中的任何位置,但是过程执行的的最后一条指令一定是RET。

二、子程序调用指令

格式:CALL   [NEAR PTR]    子程序名

CALL指令的两个作用,1.将断点地址(CALL指令的下一条指令地址)压栈保存,2.转去子程序执行。

[NEAR PTR]可以省略。

三、返回指令

格式:RET     [N]

指令作用:实现子程序执行完后返回主程序的指令。从堆栈栈顶弹出一个字数据(段内调用)送入IP作为返回地址。N是立即数,执行完RET之后,再将SP增加N,也叫“平栈”。

四、子程序参数传递的三种方式:

程序示例:假设:N1=1234H,N2=2345H,N3=3456H,计算并显示这3个数的累加和,并用二进制形式显示结果

1.通过寄存器传递参数:调用子程序前,调用程序把入口参数放在约定的寄存器中,子程序执行时,通过约定的寄存器取得入口参数;返回时,子程序把出口参数存放在约定的寄存器中,调用程序通过约定的寄存器中取得出口参数。

DATA	SEGMENT NUM  	DW  1234H     	DW  2345H     	DW  3456HDATA 	ENDSSTACKS 	SEGMENT STACK          DB  100 DUP(?)STACKS  ENDSCODE 	SEGMENT 	ASSUME  CS:CODE,DS:DATA,SS:STACKSBEG:	MOV  AX,DATA    	MOV DS,AX    	MOV SI,OFFSET NUM    	CALL COMPUTEXYZ:	CALL DISP    	MOV  AH,4CH    	INT 21HCOMPUTE PROC  	MOV BX,0  	ADD BX,[SI+0]  	ADD BX,[SI+2]  	ADD BX,[SI+4]  	RETCOMPUTE ENDPDISP PROC  	MOV CX,16LAST:	MOV DL,'0'  	RCL BX,1 	JNC NEXT        MOV DL,'1'NEXT:	MOV AH,2  	INT 21H  	LOOP LAST  	RETDISP ENDPCODE ENDSEND BEG

本例程序中调用程序把2号功能入口参数放在DL寄存器中,显示子程序在执行时从DL中取得参数。 

2.通过堆栈传递参数:子程序调用前,调用程序把参数依次压入堆栈,构成一个堆栈参数表,当子程序调用时,子程序从堆栈中取出各参数。子程序返回时,要使用 RET n 指令调整SP指针,其中n是堆栈参数表的大小,即使用完堆栈之后删除堆栈参数表,使堆栈恢复到原始状态,也就是文章开始提到的“平栈”。

DATA 	SEGMENT NUM  	DW  1234H     	DW  2345H     	DW  3456HDATA 	ENDSSTACKS 	SEGMENT STACK 'STACK'        DB  100 DUP(?)STACKS  ENDSCODE 	SEGMENT 	ASSUME  CS:CODE,DS:DATA,SS:STACKSBEG:	MOV  AX,DATA        MOV  DS,AX        MOV  SI,OFFSET NUM        PUSH WORD PTR [SI+0]        PUSH WORD PTR [SI+2]        PUSH WORD PTR [SI+4]        CALL COMPUTE	;注意CALL指令隐含的堆栈操作XYZ:	CALL DISP        MOV  AH,4CH        INT  21HCOMPUTE PROC        MOV BP,SP        MOV BX,0        ADD BX,[BP+2] 		;栈底处在高地址段        ADD BX,[BP+4]        ADD BX,[BP+6]        RET  6COMPUTE ENDPDISP PROC	MOV CX,16LAST:   MOV DL,'0' 	RCL BX,1 	ADC DL,0NEXT:   MOV AH,2  	INT 21H  	LOOP LAST  	RETDISP ENDPCODE ENDSEND BEG

3.通过变量传递参数:如果子程序和调用程序都在同一个源文件中,则双方可以直接访问模块中的变量,从而实现参数传递。

STACKS 	SEGMENT STACK 'STACK’   	DB 100 DUP(?)STACKS 	ENDSCODE 	SEGMENT   	ASSUME CS:CODE,SS:STACKSBEG:	CALL COMPUTENUM   	DW  1234H     	DW  2345H     	DW  3456HXYZ:	CALL DISPEXIT:  	MOV AH,4CH       	INT 21HCOMPUTE PROC      	MOV BP,SP      	MOV SI,[BP+0]			; [BP+0]为断点地址      	MOV BX,0      	ADD BX,CS:[SI+0]      	ADD BX,CS:[SI+2]      	ADD BX,CS:[SI+4]      	POP AX				;弹出原来的断点地址      	MOV AX,OFFSET XYZ	;改变栈顶内容,从而使返回地址改变      	PUSH AX      	RET 				;返回断点XYZCOMPUTE ENDPDISP 	PROC      	MOV CX,16LAST: 	MOV AL,'0'      	RCL BX,1 	ADC AL,0		NEXT:	MOV AH,0EH	;BIOS功能调用显示一个字符  	INT 10H      	LOOP LAST  	RETDISP ENDPCODE ENDSEND BEG

这个例子没有我们常见的数据段,二是把数据定义在了代码段,子程序在执行时,需要用数据时,访问存放数据的内存单元,并且在子程序执行要结束时,改变原来的断点地址,跳过代码段中的数据存储区,到下一片段的执行代码区。

转载地址:http://wwhai.baihongyu.com/

你可能感兴趣的文章
ubuntu中使用mysql实现opensips用户认证
查看>>
ubuntu14.04 安装freeswich问题记录
查看>>
编译webrtc audio_device提示的‘typeof’问题
查看>>
音视频文件码率与大小计算
查看>>
语音质量评价
查看>>
Android NDK开发Crash错误定位
查看>>
timer_create定时器使用
查看>>
webrtc agc
查看>>
Android 版本AGC调节
查看>>
音频PCM数据存储方式
查看>>
WebRtc 的VAD算法解析
查看>>
音频界的瑞士军刀 --- SoX - Sound eXchange 国外开源音频处理软件介绍(一)
查看>>
WebRTC音频处理流程概述
查看>>
android 编译faad2
查看>>
AAC ADTS格式分析
查看>>
MAC下zsh配置
查看>>
bash 轉移 zsh (oh-my-zsh) 設定心得
查看>>
ndk 静态库使用集锦
查看>>
ios 使用exosip库连接问题
查看>>
Xcode环境下osip,eXosip, openssl的静态库编译方法(编译出来给IOS使用)
查看>>