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指令所有写 ...
随机推荐
- CSS3 Media Queries 特性的妙用
第一招: 在网页中,pixel与point比值称为 device-pixel-ratio,普通设备都是1,iPhone 4是2,有些Android机型是1.5. 那么-webkit-min-devic ...
- jQuery 核心函数 (十一)
函数 描述 jQuery() 接受一个字符串,其中包含了用于匹配元素集合的 CSS 选择器. jQuery.noConflict() 运行这个函数将变量 $ 的控制权让渡给第一个实现它的那个库.
- IdentityServer Topics(6)- Windows身份验证
在支持的平台上,您可以让IdentityServer使用Windows身份验证(例如,对Active Directory)对用户进行身份验证. 当您使用以下身份托管IdentityServer时,当前 ...
- kmalloc、vmalloc、__get_free_pages()的区别
一.分布位置上的区别: kmalloc()和__get_free_pages()函数申请的内存位于物理内存的映射区域,而且在物理上也是连续的,它们与真实的物理地址只有一个固定的偏移,因此存在简单的线性 ...
- java_web学习(四) Date的理解与应用
1.日期 1.1 日期的本质: 是一个长整型long,最小单位是毫秒 1.2 日期的格式: 本次运用子类simpleDateformat定义格式 1.3 日期的运算 本次运用calendar类来的ad ...
- 【转载】wifi一键配网smartconfig原理及应用
物联网给我们又提供了一种窃取WiFi密码的好方式:让智能设备主动断线. 同时也提供一种让智能设备连接到恶意WiFi的方式:设备一键配置功能时疯狂广播恶意WiFi的信息. 转自:http://blog. ...
- VSTS/TFS Auto Build
前几天使用VSTS配置自动部署前端网站(AngularJS)和RESTfulAPI(.NET)到客户环境. 由于都是参考官方文档 https://docs.microsoft.com/zh-cn/vs ...
- 给“file”类型的input框赋值的问题
开发"新闻编辑"功能时,会遇到给"file"类型的input框赋值的问题,用来展示之前上传的文件,但由于file类型的input框受到安全限制,所以不能被赋值, ...
- echarts饼图点击事件
/** * 点击事件 */myChart2.on('click', function (param) { var index = param.dataIndex; alert(index);});
- 洛谷 P1028 数的计算【递推】
P1028 数的计算 题目描述 我们要求找出具有下列性质数的个数(包含输入的自然数n): 先输入一个自然数n(n<=1000),然后对此自然数按照如下方法进行处理: 1.不作任何处理; 2.在它 ...