call 和 ret 指令
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;} th{border: 1px solid gray; padding: 4px; background-color: #DDD;} td{border: 1px solid gray; padding: 4px;} tr:nth-child(2n){background-color: #f8f8f8;}
; CPU 执行 ret 指令 1、(IP)=((SS)*16+(SP)) 2、(sp)=(sp)+2 相当于: pop IP |
; CPU 执行 retf 指令 1、(IP)=((SS)*16+(SP)) 2、(SP)=(SP)+2 3、(CS)=((SS)*16+(SP)) 4、(SP)=(SP)+2 相当于: pop IP pop CS |
;程序执行 ret 指令后, (IP)=0,CS:IP指向代码段第一条指令
assume cs:code
stack segment
db 16 dup (0)
stack ends
code segment
mov ax , 4c00h
int 21h
start: mov ax , stack
mov ss , ax
mov sp , 16
mov ax , 0
push ax
mov bx , 0
ret ; ip 被设置为0,指令转移到mov ax , 4c00
code ends
end start
assume cs:code
code segment
mov ax , 4c00h
int 21h
start:
mov ax , 0
push ax
mov bx , 0
ret
code ends
end start ; 一样的效果 |
;程序执行 reft 后,CS:IP 指向代码段第一条指令
assume cs:code
stack segment
db 16 dup (0)
stack ends
code segment
mov ax , 4c00h
int 21h
start: mov ax , stack
mov ss , ax
mov sp , 16
mov ax , 0
push cs
push ax
mov bx , 0
retf
code ends
end start
assume cs:code
code segment
mov ax , 4c00h
int 21h
start:
mov ax , 0
push cs
push ax
mov bx , 0
retf
code ends
end start |
CPU 执行这种指令进行如下操作
1、(SP)=(SP)-2 ((SS)*16+(SP))=(IP)
2、(IP)=(IP)+16 位位移
CPU 执行 “call 标号”时,相当于: push IP jmp near ptr 标号 |
内存地址 | 机器码 | 汇编指令 |
076A:0 076A:3 076A:6 076A:7 |
B8 00 00 E8 01 00 40 58 |
mov ax , 0 call s ; 执行时 call 0007 inc ax s: pop ax |
当 IP=3的时候指向 call s ;执行这条指令的时候 IP 偏移到 6,也就是下一条指令;call s == push IP jmp near ptr 标号 此时栈中只有一个数据6,最后pop ax , 所以ax=6; |
转移的目的地址在指令中的 call 指令
“call far ptr 标号” 实现的是段间转移。 1、(SP)=(SP)-2 ((SS)*16+(SP))=(CS) (SP)=(SP)-2 ((SS)*16+(SP))=(IP) |
2、 (CS)=标号所在段的段地址 (IP)=标号在段中的偏移地址 相当于进行: push CS push IP jmp far ptr 标号 |
内存地址 | 机器码 | 汇编指令 |
076A:0 076A:3 076A:8 076A:9 076A:A |
B8 00 00 9A 09 00 6A 07 40 58 5B |
mov ax , 0
call far ptr s ; call 076A:0009
inc ax
s: pop ax
pop bx
|
执行call far ptr s 的时候,cpu把下一条指令的位置 CS:IP =076A:0008 压入栈中保存,然后计算到标号 s 的偏移,转到标号处执行;此时出栈 ax=IP=0008,bx=CS=076A; |
指令格式:call 16 位寄存器 功能:(SP)=(SP)-2 ((SS)*16+(SP))=(IP) (IP)=(16位寄存器) |
相当于进行: push IP jmp 16位寄存器 |
内存地址 | 机器码 | 汇编指令 |
076A:0 076A:3 076A:5 076A:6 076A:8 076A : B |
B8 00 00 FF D0 40 8B EC 03 46 00 58 |
mov ax , 6
call ax
inc ax
s: mov bp , sp
add ax , [bp] ; ax=000B , 这里取的是ss:bp内存里的值,因为sp==bp,所以是堆栈顶数据5,5+6=B
pop ax ; ax=0005
|
1、call word ptr 内存单元地址 相当于: push IP jmp word ptr 内存单元地址 mov sp , 10h
mov ax , 0123h
mov ds:[0] , ax
call word ptr ds:[0] ;执行这条指令,IP进栈,栈中存放000D
执行后:(IP)=0123H,(SP)=0EH
|
2、call dword ptr 内存单元地址 相当于: push CS push IP jmp dword ptr 内存单元地址 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 |
assume cs:codesg
codesg segment
start: mov ax , 1
mov cx , 3
call s ; 栈中进栈(IP),执行到这行指令的时候,IP指向mov bx , ax
mov bx , ax ;(bx)=8Z
mov ax , 4c00h
int 21h
s: add ax , ax
loop s
ret ;从栈中取一个数当做ip(刚好指向mov bx , ax)
codesg ends
end
|
1、两个相乘的数:两个数相乘要么都是8位,要么都是16位。如果都是8位,一个默认放在 AL 中,另外一个放在 8 位寄存器或内存字节单元中;如果是16位,一个默认放在 AX 中,另外一个放在16位寄存器或内存字单元中。 | 2、结果:如果是8位乘法,结果默认放在 AX 中;如果是16位乘法,结果默认高位放在 DX ,低位在 AX 中存放。 |
指令格式: mul reg mul 内存单元 |
内存单元可以用不同的寻址方式给出,eg: mul byte ptr ds:[0] 含义:(ax)=(al)*((ds)*16+0) mul word ptr [bx+si+8] 含义:(ax)=(ax)((ds)*16+(bx)+(si)+8) ; 结果的低16位 (dx)=(ax)((ds)*16+(bx)+(si)+8) ; 结果的高16位 |
; 计算 100*10 ; 两个数都小于255,可以做8位乘法 mov al , 100 mov bl , 10 mul bl 结果:(ax)=1000(03E8H) |
; 计算 100*10000
; 10000大于255,必须做16位乘法
mov ax , 100
mov bx , 10000
mul bx
结果:(ax)=4240H , (dx)=000FH ; F4240H=1000000
|
assume cs:codesg , ds:datasg
datasg segment
dw 1,2,3,4,5,6,7,8 ;(16个字节(00))
dd 0,0,0,0,0,0,0,0 ;(32个字节(00) )
datasg ends
codesg segment
start: mov ax , datasg
mov ds , ax
mov si , 0 ;偏移0指向第一个数1
mov di , 16 ;偏移16指向存放结果内存单元的首地址
mov cx , 8 ; 8个数,进行8次循环
s: mov bx , [si]
call cube
mov [di] , ax ;把结果的低16位放到低位两个字节(00 01)
mov [di].2 , dx ;把结果的高16位放到高位的两个字节(02 03)
add si , 2 ;偏移2个单位取到下一个数2
; ds:si 指向下一个 word 单元
add di , 4 ;偏移到下一个存储结果的内存地址(04 05 06 07)
; ds:di 指向下一个 dword 单元
loop s
mov ax , 4c00h
int 21h
cube: mov ax , bx ; 对拿到的数进行立方运算
mul bx
mul bx
ret
codesg ends
end start
|
// 改写程序的初始第一个值为9 9的三次方等于 2D9 , 低16位存放2D9 (D9 02), 高16位存放0(00 00) |
assume cs:codesg , ds:datasg
datasg segment
db 'conversation'
datasg ends
codesg segment
start: mov ax , datasg
mov ds , ax
mov si , 0 ; ds:si指向字符串(批量数据)所在空间的首地址
mov cx , 12 ; cx 存放字符串的长度
call capital
mov ax , 4c00h
int 21h
capital:and byte ptr [si] , 11011111b
inc si
loop capital
ret
codesg ends
end start
|
除了用寄存器传递参数外,还有一种通用的方法就是用栈来传递参数。 |
;改进上面的程序,字符串后面加一个0表示结束,就可以不用cx assume cs:codesg , ds:datasg
datasg segment
db 'conversation' , 0
datasg ends
codesg segment
start: mov ax , datasg
mov ds , ax
mov si , 0
call capital
mov ax , 4c00h
int 21h
capital:mov cl , [si] ; 当读到最后一个的时候为 0
mov ch , 0
jcxz ok ; 读到最后 (cx)=0
and byte ptr [si] , 11011111b
inc si
jmp short capital
ok: ret ; 出栈,设置cs:ip指向 mov ax , 4c00h
codesg ends
end start
|
|
;编写程序将 data 段中的字符串全部转化为大写 assume cs:code , ds:data
data segment
db 'word' , 0
db 'unix' , 0
db 'wind' , 0
db 'good' , 0
data ends
code segment
start: mov ax, data
mov ds , ax
mov bx , 0
mov cx , 4 ; 设置循环次数4
s: mov si , bx
call capital ; 调用子程序处理字符串
add bx , 5 ; 偏移量加 5 ,处理下一个字符串
loop s
mov ax , 4c00h
int 21h
capital: push cx ; 执行子程序防止有冲突寄存器,先压栈保存主程序寄存器值
push si
change: mov cl , [si]
mov ch , 0
jcxz ok ; 判断(cx)是否等于0,如果等于0表示读完一个字符串
and byte ptr [si] , 11011111b
inc si
jmp short change
ok: pop si ; 结束了一次子程序的调用,恢复主程序的相应寄存器的值
pop cx
ret ; 返回call下一行指令,执行下一次循环
code ends
end start
|
call 和 ret 指令的更多相关文章
- 汇编语言---call和ret指令
汇编语言--call和ret指令 call和ret指令 call和ret指令都是转移指令,它们都修改IP,或同时修改CS和IP. 它们经常被共同用来实现子程序的设计. ret和retf ret指令用栈 ...
- 汇编学习笔记(7)call和ret指令
ret和retf CPU执行ret指令时进行以下两步操作: (IP)=((ss)*16+(sp)) (sp)=(sp)+2 这相当于pop IP CPU执行retf指令时进行以下四步操作: (IP)= ...
- [汇编学习笔记][第十章 CALL和RET指令]
第十章 CALL和RET指令 call和ret指令都是转移指令,它们都修改CS和IP.经常被共同用于实现子程序的设计.这一章,我们讲解call和ret指令的原理 10.1 ret和retf ret指令 ...
- 汇编-10.0-CALL和RET指令
call和ret指令都是转移指令,他们都是修改IP,或同时修改CS和IP.它们常被共同用来实现子程序设计. 1.ret和retf ret指令用栈中的数据,修改IP的内容,从而实现近转移: retf指令 ...
- 第十章 Call 和 Ret 指令
引言 想想程序之间的加载返回过程. call 和 ret 指令都是转移指令,它们都修改 IP,或同时修改 CS 和 IP. call 和 ret 经常被共同用来实现自程序的设计. 这一章,我们讲解 c ...
- 汇编语言笔记 CALL和RET指令
转载地址:http://www.cnblogs.com/dennisOne ☞模块化程序设计 模块化程序设计 汇编语言通过call和ret指令实现了模块化程序设计.可以实现多个相互联系.功能独立的子程 ...
- 自己总结:汇编CALL和RET指令
ret指令,相当于 pop IP:修改IP的内容,从而实现近转移 retf指令,相当于 pop IP pop CS:修改CS和IP的内容,从而实现远转移 -------------- CPU执行cal ...
- call和ret指令
call和ret都是用来修改ip或cs:ip,可以用来实现子程序的设计: 1.ret和retf ret ->修改ip的内容,从而实现近转移: retf ->同时修改cs和i ...
- 王爽汇编第十章,call和ret指令
目录 王爽汇编第十章,call和ret指令 call和ret指令概述: ret和retf ret指令 retf指令 call 和 ret 的配合使用 call指令详解 call原理 call指令所有写 ...
随机推荐
- JQuery 网页瞄点
$("html,body").animate({ scrollTop: $("#Content1").offset().top }, 3000); 代码说明:h ...
- Linux笔记---硬盘添加
BZ创建了一个块云硬盘添加到了虚拟机里,然后按照平时挂在U盘的方式去挂载硬盘: mount -t ext4 /dev/vdb /mnt/xxxx 结果报出以下错误: mount: wrong fs ...
- Centos6.5 登录时,提示Module is unkown
前一段时间,因工作需要在物理机上装了一个Centos6.5,但是,用了一段时间,发现再登录时,无论如何也登不进去了,并且也不提示用户名或者密码错误.我一度以为是在profile以及.bashrc或者. ...
- DAY4-打卡第四天-2018-1-12
刚经历C语言考试,提前一个小时交卷出来在学一点咯!! 字符串不是一个基本类型,不能用恒等== 而应该用: 变量名.equals(""); 变量名.equalsIgnoreCase( ...
- JDK源码 - ArrayList
/** * ArrayList源码分析 * @author liyong * */ public class Util { @SuppressWarnings("unchecked" ...
- js--Dom Bom操作
– 基础 – 内置对象 ● String对象:处理所有的字符串操作 ● Math对象:处理所有的数学运算 ● Date对象:处理日期和时间的存储.转化和表达 ● Array对象:提供 ...
- OOAD-设计模式(一)概述
前言 在我们很多时候设计代码都是需要用到各种不一样的设计模式的,接下来着几篇给大家领略一下设计模式.知道设计模式的作用,以及在代码的具体体现.很多时候我们看不懂代码就是因为我们不知道它使用的设计模式. ...
- 51 Nod 1028 大数乘法 V2【Java大数乱搞】
1028 大数乘法 V2 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 给出2个大整数A,B,计算A*B的结果. Input 第1行:大数A 第2行:大数B (A ...
- BZOJ 1207: [HNOI2004]打鼹鼠【妥妥的n^2爆搜,dp】
1207: [HNOI2004]打鼹鼠 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3259 Solved: 1564[Submit][Statu ...
- c语言基础学习09_复合类型
=============================================================================涉及到的知识点有:一.结构体1.定义结构体st ...