-
-
[分享]零基础16位汇编学习之主程序与子程序间的几种参数传递方法
-
发表于: 2022-2-10 12:51 5092
-
主程序在调用子程序时,一般要向子程序传递一些参数,然后,子程序运行后也要把结果参数传回给主程序,所以一般子程序需要入口参数和出口参数,这里学习三种参数传递方法。
一、寄存器传递参数
在需要调用子程序的时候利用寄存器存放参数作为入口和出口参数,这种方法简单方便,缺点是只能用于参数较少的时候。
例:把一个大写字母转为小写字母的子程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ;子程序名:pata;功能:把大写字母转换为小写字母;入口参数:al = 字符ascll码;出口参数:al = 字符ascll码;说明:如果字符是大写字母,则转换为小写字母,其他字符不变pata proc pushf ;保护寄存器里面的数据 cmp al,'A' ;字符串与大写A做比较 jb stp ;小于大写A则跳转 cmp al,'Z' ;字符串与大写Z作比较 ja stp ;大于大写Z则跳转 add al,20h ;是大写字母加20h就是ascll码串的小写字母stp:popf ret ;返回pata endp |
二、利用约定存储单元传递参数
第二种方法是利用约定的内存单元里的数据来传递参数,这种方法的优点是子程序要处理的数据和结果都有单独的内存单元,写程序不容易出错
例:实现32位数相加的子程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ;子程序名:pata1;功能:32位数相加;入口参数:date1和date2分别存放相加的32位数;出口参数:date3缓冲区存放;说明:1、32位数据存放依次为’高高低低‘的原则 2、可能产生的进位存放在date3开始的第5字节中pata1 proc pshu ax pshu cx pshu si ;保护寄存器里面的数据 mov cx,2 ;因为用16位寄存器计算所以循环加两次 xor si,si ;si寄存器置0pa1: mov ax,word ptr date1[si] ;提取date1段里面的16位数据到ax adc ax,word prr date2[si] ;ax和date2段里面的16数据进位相加 mov word ptr date3[si],ax ;把结果存入date3单元缓冲区 inc si inc si ;si指向另外16位数据 loop pa1 ;再循环相加一次 mov al,0 ;al置0,用于判断是否有进位 adc al,0 ;如果相加的数据有进位 mov byte ptr data3+4,al ;把进位数传递到date3的第5字节中 pop si pop cx pop ax ;寄存器恢复 ret ;返回pata1 endp |
例2:把ascll码表示的十进制数字转换为二进制数的子程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ;子程序名:pata2;功能:把ascll码表示的十进制数字转换为二进制数;入口函数:ds:bx缓冲区里面的数据;出口函数:ax,得到的二进制数存到ax寄存器里;说明:设表示的二进制数不大于65535pata2 proc push bx push cx push dx ;保护寄存器 xor ax,ax ;ax置0 mov cl,[bx] ;把ds:[bx]处的置赋予cl inc bx ;bx指向下一位数据 xor ch,ch ;ch清0 jcxz pta2 ;如果cx是0则跳转pta1: mov dx,10 ;dx = 10 mul dx ;dx×10 二进制表示1010 mov dl,[bx] ;取下一个数字符到10后面 inc bx ;bx指向下一位 and dl,0fh ;把dl转成bcd码 xor dh,dh ;dh(10)清0 add ax,dx ;把值和ax相加存到ax寄存器 loop pta1 pta2: pop dx pop cx pop bx ;恢复寄存器 retpata2 endp |
三、利用堆栈传递参数
如果使用堆栈传递入口参数,把需要传递的参数依次压入堆栈,子程序从堆栈中取入口参数,如果使用堆栈传递出口参数,把需要传递的参数依次压入堆栈,子程序从堆栈中取出口参数。
例1:写一个测量字符串长度的子程序,设字符串为0结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ;子程序名:pata3;功能:测量字符串长度;入口参数:字符串起始地址段值和偏移在堆栈中;出口参数:ax= 字符串长度pata3 proc push bp mov bp,sp ;把堆栈sp赋值给bp,为取参数做准备 push ds ;保护段寄存器 push si ;保护偏移地址 mov ds,[bp+6] ;取入口参数 mov si,[bp+4] mov al,0 ;al置0pat3: cmp al,[si] ;判断是不是结尾0 jz pat4 ;如果是0则跳转pat4 inc si ;不是0则si加1 jmp pat3 ;跳转到pat3继续计算pat4: mov ax,si ;si的值就是字符串的长度 sub ax,[bp+4] ;ax减去段寄存器地址的多余长度得到具体长度 pop si pop ds pop bp ;恢复寄存器数据 retpata3 endp |
赞赏
赞赏
雪币:
留言: