汇编语言-子程序调用
来源:互联网 发布:js 判断ie9以下版本 编辑:程序博客网 时间:2024/06/06 12:37
汇编语言-子程序调用
ret与ref指令
ret
ret == pop IP
ret指令用栈中的数据,修改IP的内容,从而实现近转移;
功能介绍
retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移
CPU执行ret指令时,进行下面两步操作:
(1)(IP) = ((ss) * 16 + (sp))(2)(sp) = (sp) + 2
相当于进行:
pop IP
retf
retf == pop IP + POP CS
功能介绍
CPU执行retf指令时,进行下面两步操作:
(1)(IP) = ((ss) * 16 + (sp))(2)(sp) = (sp) + 2(3)(CS) = ((ss) * 16 + (sp))(4)(sp) = (sp) + 2
相当于进行:
pop IPpop CS
call指令
call 标号
功能介绍
(把当前IP压栈后, 转到标号处执行指令)
a. (SP) = (SP) - 2 ((SS) * 16 + SP) = (IP)b. (IP) = (IP) + 16位位移
相当于:
push IPjmp near ptr 标号
- 16位位移 = “标号”处的地址 - call指令后的第一个字节的地址;
- 16位位移的范围 -32768—-32767, 用补码表示;
- 16位位移由编译程序在编译时算出;
call far ptr 标号
功能介绍
(把当前CS,IP压栈后, 转到标号处执行指令)
a. (SP) = (SP) - 2 ((SS) * 16 + SP) = (CS)b. (SP) = (SP) - 2 ((SS) * 16 + SP) = (IP)c. (CS) = 标号所在段的段地址 (IP) = 标号在段中的偏移地址
相当于:
push CSpush IPjmp par ptr 标号
call 16位寄存器
功能介绍
(sp) = (sp) – 2((ss) * 16 + (sp)) = (IP)(IP) = (16位寄存器)
相当于:
push IP jmp 16位寄存器
call word ptr 内存单元地址
功能介绍
push IPjmp word ptr 内存单元地址
实例展示
mov sp, 10hmov ax, 0123hmov ds:[0], axcall word ptr ds:[0]执行后,(IP)=0123H,(sp)=0EH
call dword ptr 内存单元地址
功能介绍
push CSpush IPjmp dword ptr 内存单元地址
实例展示
mov sp, 10hmov ax, 0123hmov ds:[0], axmov word ptr ds:[2], 0call dword ptr ds:[0]执行后,(CS)=0,(IP)=0123H,(sp)=0CH((IP)= ds:[0], (CS) = ds:[2])
子程序调用
通过上面介绍的两个指令,我们可以完成子程序的调用。简单调用程序如下:
assume cs:codecode segmentstart: mov ax,1 mov cx,3 call s mov bx, ax mov ax,4c00H int 21H s: add ax,ax loop s retcode endsend start
子程序调用-传递参数问题
我们在写c语言或者其他高级语言的时候,要经常用到函数之间的参数传递这一个概念。那么在汇编语言中,我们怎么做到总程序和子程序之间的参数传递呢?
寄存器存放法
首先可以考虑在寄存器中,存放数据,比如a存放在ax中,b存放在bx中。
mov ax,amov bx,b
这种方式可以在参数比较少的时候使用,但是参数多了呢?那么那么多的寄存器给你存放。因此这种方式不是长久之计。
内存存放法
我们想到了一个比较好的思路,就是将参数保存到内存中,然后在寄存器中存放这些参数的首地址,通过首地址访问一系列的参数。这种方式,显然可以存放更多的数据,并且没有数量上的限制。
;参数存放段data segment db 'aaaaa',0 db 'aaaaa',0 db 'aaaaa',0data endscode segment ... ... mov ax,data mov es,ax mov si,0 call sub1 ... ... sub1: mov ax,es[si] ... ... retcode ends
这里还是存在一个问题,如果在主程序中用到了一个xx寄存器,然后在子程序中也用到了这个xx寄存器,那么当子程序返回到主程序的时,主程序中存放参数的内存地址已经没有记录了,程序出错。
内存存放法(改进)
为了解决这个问题,我们需要每次进入子程序时,将子程序中的需要用到的寄存器,push到栈中,每次退出子程序时,将相应寄存器pop出来。
子程序都应遵循下面的模式:
capital: push cx push sichange: mov cl,[si] mov ch,0 jcxz ok and byte ptr[si],11011111B inc si jmp short changeok: pop si pop cx ret
0 0
- 汇编语言-子程序调用
- 汇编语言--如何调用子程序
- 汇编语言子程序调用call和ret
- 拓展:汇编语言的子程序
- 汇编语言showStr测试子程序
- 调用子程序
- 【按键精灵】sub子程序、调用子程序
- 冒泡排序_汇编语言的子程序调用与宏定义实现
- 汇编语言子程序设计 查找电话号码
- 汇编语言--王爽--实验9 子程序
- 汇编语言:简单的子程序设计
- 汇编语言 递归子程序实现阶乘
- COBOL子程序调用
- COBOL子程序调用
- 子程序调用语句
- CMD 调用子程序&从子程序返回
- 用汇编语言随机产生字母的子程序
- 8、王爽《汇编语言》笔记_子程序一
- 取消Android ListView 下拉到两端发荧光的效果
- lightOJ 1294 - Positive Negative Sign 【规律题】
- 【C】【笔记】《C和指针》第10章 结构和联合 第11章 动态内存分配 第12章 使用结构和指针 第13章 高级指针话题 第14章预处理器
- Zookeeper在Windows上安装
- 继承
- 汇编语言-子程序调用
- SQLite数据库的应用
- 文档字符串
- 数值优化(Numerical Optimization)学习系列-二次规划(Quadratic Programming)
- C++中的IO类(iostream, fstream, stringstream)小结
- 浅谈C++中指针和引用的区别
- 字符串
- 【C】【笔记】《C和指针》第15章 输入/输出函数
- hdu1176 免费馅饼 (动态规划)