addr和offset指令的区别
来源:互联网 发布:java 合并两个list 编辑:程序博客网 时间:2024/05/17 07:00
一、相同点
1、addr 和 offset 操作符都是获得操作数的偏移地址;
2、addr 和 offset 的处理都是先检查处理的是全局还是局部变量,若是全局变量则把其地址放到目标文件中。
二、不同点
1、addr 伪操作符,只能用在 invoke 伪指令语句中,不能用于赋值操作;
2、offset 伪操作符可以用在任何可能涉及偏移地址的指令(当然包括 invoke 伪指令)并想获取操作数偏移地址的场合中;
3、addr 不能处理向前引用(即 addr 引用的操作数必须在使用 addr 前就得定义或声明),而offset 则能(不管引用的操作数是其前或其后定义或声明);
所谓向前引用是指:标号的定义是在invoke 语句之后,比如在如下的例子:
invoke MessageBox,NULL, addr MsgBoxText,addr MsgBoxCaption,MB_OK //引用MsgBoxText、MsgBoxCaption 在先
......
MsgBoxCaption db "Iczelion Tutorial No.2",0 //定义或声明 MsgBoxCaption 在 addr 后
MsgBoxText db "Win32 Assembly is Great!",0 //定义或声明 MsgBoxText 在 addr 后
如果你是用addr 而不是offset 的话,那MASM就会报错
4、addr 是运行阶段在堆栈中分配内存空间,offset 是编译阶段由编译器解释。因此,addr 可以处理局部变量而 offset 则不能。
5、addr 如果检查到待处理的变量是局部变量,就在执行 invoke 语句前产生如下指令序列:
lea eax,operand
push eax
因为 lea 指令能够在运行时决定标号的有效地址,所以有了上述指令序列,就可以保证invoke的正确执行了。addr 面对全局变量时直接调用offset.
总结:为了避免出现错误,建议除在局部变量中引用 addr 操作符外,其它场合使用 offset。
说明:某些文章中对 addr 和 offset 所引用的对象仅用了“变量或标号”,我是用“操作数”来阐述的,本人的观点是:
变量或标号感觉上包含的概念过窄,比如结构、函数等等,因此,觉得使用操作数好像感觉准确些。
; Test1.asm.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data val db 11h, 22h, 33h, 44h, 55h, 66h, 77h, 88h.codemain proc xor eax, eax ;清空 EAX, 同 mov eax, 0 mov eax, dword ptr val ; PrintHex eax ;44332211 xor eax, eax ; mov eax, dword ptr val+1 ; PrintHex eax ;55443322 xor eax, eax ; mov ax, word ptr val ; PrintHex eax ;00002211 xor eax, eax ; mov al, byte ptr val ; PrintHex eax ;00000011 retmain endpend main
OFFSET: 获取全局变量或标号的偏移地址
; Test2.asm.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data v1 db 'abcdefg', 0 v2 dd 11223344h.codemain proc PrintHex offset v1 ;00403000 PrintHex offset v2 ;00403008 PrintHex offset main ;00401000 - 这里的 main 是个标号 ret;本例中的 offset 不能用 addr 代替main endpend main
ADDR: 类似 offset 也是获取变量的地址...
; Test3.asm.386.model flat, stdcall;include windows.incinclude kernel32.incincludelib kernel32.libinclude user32.incincludelib user32.lib.data v1 dd 00434241h ;ABC v2 dd 00636261h ;abc.codemain proc invoke MessageBox, 0, offset v1, offset v2, 0 ;现在 v1、v2 是全局变量 invoke MessageBox, 0, addr v2, addr v1, 0 ;使用 offset 和 addr 均可 invoke ExitProcess, 0main endpend main
获取局部变量的地址只能使用 ADDR:
; Test4.asm.386.model flat, stdcall;include windows.incinclude kernel32.incincludelib kernel32.libinclude user32.incincludelib user32.lib.codemain proc LOCAL v1,v2 mov v1, 00434241h mov v2, 00636261h ;invoke MessageBox, 0, offset v1, offset v2, 0 ;offset 不能获取局部变量的地址 invoke MessageBox, 0, addr v2, addr v1, 0 invoke ExitProcess, 0main endpend main
; Test5.asm.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data TextAddr equ this byte ;伪指令 this 可让当前变量和下一个变量同址 szText db 'Asm', 0.codemain proc PrintHex offset szText ;00403000 PrintHex offset TextAddr ;00403000 PrintString szText ;Asm mov [TextAddr], 'a' ;给 TextAddr 赋值 PrintString szText ;asm retmain endpend main
转载自: http://genime.blog.163.com/blog/static/167157753201148103615697/
- addr和offset指令的区别
- addr和offset指令的区别
- addr和offset区别
- win32汇编中伪指令addr和offset指令的区别
- win32汇编中伪指令addr和offset指令的区别
- Win32汇编中addr和offset的区别联系
- 浅谈OFFSET、ADDR&LEA的区别
- addr 与 offset 区别
- addr和offset
- lea和offset、addr
- 汇编中addr和offset
- 汇编中addr和offset
- 汇编中addr和offset的异同点
- Win32汇编的 PTR, OFFSET, ADDR
- lea和offset的区别
- offset()和position()的区别
- offset和position的区别
- PTR、OFFSET、ADDR
- 什么是I帧,P帧,B帧
- 8 Android gallery
- Shell 函数
- sprintf详解
- PHP_Filter过滤多个输入
- addr和offset指令的区别
- oracle字符集
- Path Sum
- Ext4.1.0 中文API文档已经全部翻译完成!
- 汽车租赁管理系统-期末项目
- 微信公众平台取代APP?开发者总结六大理由
- 算法整理(一)----选择排序
- http://blog.sina.com.cn/s/blog_b95b79f90101jhrv.html
- SQL语言参考