汇编语言-子程序调用
2015-11-08 18:43
267 查看
汇编语言-子程序调用
ret与ref指令
ret
ret == pop IPret指令用栈中的数据,修改IP的内容,从而实现近转移;
功能介绍
retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移CPU执行ret指令时,进行下面两步操作:
[code](1)(IP) = ((ss) * 16 + (sp)) (2)(sp) = (sp) + 2
相当于进行:
[code]pop IP
retf
retf == pop IP + POP CS功能介绍
CPU执行retf指令时,进行下面两步操作:[code](1)(IP) = ((ss) * 16 + (sp)) (2)(sp) = (sp) + 2 (3)(CS) = ((ss) * 16 + (sp)) (4)(sp) = (sp) + 2
相当于进行:
[code]pop IP pop CS
call指令
call 标号
功能介绍
(把当前IP压栈后, 转到标号处执行指令)[code]a. (SP) = (SP) - 2 ((SS) * 16 + SP) = (IP) b. (IP) = (IP) + 16位位移
相当于:
[code]push IP jmp near ptr 标号
16位位移 = “标号”处的地址 - call指令后的第一个字节的地址;
16位位移的范围 -32768—-32767, 用补码表示;
16位位移由编译程序在编译时算出;
call far ptr 标号
功能介绍
(把当前CS,IP压栈后, 转到标号处执行指令)[code]a. (SP) = (SP) - 2 ((SS) * 16 + SP) = (CS) b. (SP) = (SP) - 2 ((SS) * 16 + SP) = (IP) c. (CS) = 标号所在段的段地址 (IP) = 标号在段中的偏移地址
相当于:
[code]push CS push IP jmp par ptr 标号
call 16位寄存器
功能介绍
[code](sp) = (sp) – 2 ((ss) * 16 + (sp)) = (IP) (IP) = (16位寄存器)
相当于:
[code]push IP jmp 16位寄存器
call word ptr 内存单元地址
功能介绍
[code]push IP jmp word ptr 内存单元地址
实例展示
[code]mov sp, 10h mov ax, 0123h mov ds:[0], ax call word ptr ds:[0] 执行后,(IP)=0123H,(sp)=0EH
call dword ptr 内存单元地址
功能介绍
[code]push CS push IP jmp dword ptr 内存单元地址
实例展示
[code]mov sp, 10h mov ax, 0123h mov ds:[0], ax mov word ptr ds:[2], 0 call dword ptr ds:[0] 执行后,(CS)=0,(IP)=0123H,(sp)=0CH ((IP)= ds:[0], (CS) = ds:[2])
子程序调用
通过上面介绍的两个指令,我们可以完成子程序的调用。简单调用程序如下:[code]assume cs:code code segment start: mov ax,1 mov cx,3 call s mov bx, ax mov ax,4c00H int 21H s: add ax,ax loop s ret code ends end start
子程序调用-传递参数问题
我们在写c语言或者其他高级语言的时候,要经常用到函数之间的参数传递这一个概念。那么在汇编语言中,我们怎么做到总程序和子程序之间的参数传递呢?寄存器存放法
首先可以考虑在寄存器中,存放数据,比如a存放在ax中,b存放在bx中。[code]mov ax,a mov bx,b
这种方式可以在参数比较少的时候使用,但是参数多了呢?那么那么多的寄存器给你存放。因此这种方式不是长久之计。
内存存放法
我们想到了一个比较好的思路,就是将参数保存到内存中,然后在寄存器中存放这些参数的首地址,通过首地址访问一系列的参数。这种方式,显然可以存放更多的数据,并且没有数量上的限制。[code];参数存放段 data segment db 'aaaaa',0 db 'aaaaa',0 db 'aaaaa',0 data ends code segment ... ... mov ax,data mov es,ax mov si,0 call sub1 ... ... sub1: mov ax,es[si] ... ... ret code ends
这里还是存在一个问题,如果在主程序中用到了一个xx寄存器,然后在子程序中也用到了这个xx寄存器,那么当子程序返回到主程序的时,主程序中存放参数的内存地址已经没有记录了,程序出错。
内存存放法(改进)
为了解决这个问题,我们需要每次进入子程序时,将子程序中的需要用到的寄存器,push到栈中,每次退出子程序时,将相应寄存器pop出来。子程序都应遵循下面的模式:
[code]capital: push cx push si change: mov cl,[si] mov ch,0 jcxz ok and byte ptr[si],11011111B inc si jmp short change ok: pop si pop cx ret
相关文章推荐
- 文档字符串
- SQLite数据库的应用
- 继承
- 汇编语言-子程序调用
- LINQ之延迟加载及其原理
- LINQ之延迟加载及其原理
- lightOJ 1294 - Positive Negative Sign 【规律题】
- Exchange Server简介与搭建
- 取消Android ListView 下拉到两端发荧光的效果
- 双十一京东图书购物清单,动动脑子节省300元
- 【C】【笔记】《C和指针》 第六章 指针 第七章 函数 第八章 数组 第九章 字符串、字符和字节
- 双十一京东图书购物清单,动动脑子节省300元
- 双十一京东图书购物清单,动动脑子节省300元
- 集合转换java:【List<-->数组、List<-->Set、数组<-->Set、Map-->Set、Map-->List】
- 《PHP从入门到精通》学习笔记之一
- git clone命令使用
- 【线性表】双向循环链表
- java中锁的优化
- 多种方法实现Fibonacci(斐波那契)数列的生成
- 《C++ primer》英文第五版阅读笔记(十二)——数组