http://tech.ddvip.com/2010-04/1270705496150170.html
PTR: 指定要操作的数据尺寸
OFFSET: 获取全局变量或标号的偏移地址
ADDR: 类似 offset 也是获取变量的地址(局部变量的地址只能用ADDR来获取)
PTR: 指定要操作的数据尺寸
; Test12_1
.
asm
.
386
.model flat, stdcall
include windows
.
inc
include kernel32
.
inc
include masm32
.
inc
include debug
.
inc
includelib kernel32
.
lib
includelib masm32
.
lib
includelib debug
.
lib
.data
val
db 11h, 22h, 33h, 44h, 55h, 66h, 77h, 88h
.code
main 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
ret
main endp
end
main
例如:下面的指令中,用word ptr 指明了指令访问的内存单元是一个字单元:
mov word ptr ds:[0],1 ; 把ds:[0]指向的内存(1 Word大小)赋值为1
inc word ptr [bx] ; 把ds:[bx]指向的内存(1 Word大小)赋值为1
inc word ptr ds:[0]
add word ptr [bx],2
下面的指令中,用byte ptr 指明了指令访问的内存单元是一个字单元:
mov byte ptr ds:[0],1
inc byte ptr [bx]
inc byte ptr ds:[0]
add byte ptr [bx],2
在没有寄存器参与的内存单元访问指令中,用word prt 或byte ptr 显性地指明所要访问的内存单元的长度是很必要的。否则,CPU无法得知所要访问的单元,还是字节单元。假如我们用Debug查看内存的结果如下:
2000:1000 FF FF FF FF FF FF ......
那么指令:
mov ax,2000H
mov ds,ax
mov byte ptr [1000H],1
将使内存中的内容变为:
2000: 1000 01 FF FF FF FF FF ......
而指令:
mov ax,2000H
mov ds,ax
mov word ptr [1000H],1
将使内存中的内容变为:
2000:1000 01 00 FF FF FF FF ......
这是因为 mov byte ptr [1000H],1访问的是地址为 ds:1000H 的字节单元,修改的是ds:1000H 单元的内容;而mov word ptr [1000H],1 访问的是地址为 ds:1000H 的字单元,修改的是 ds:1000H 和 ds:1001H 两个单元的内容。
OFFSET: 获取全局变量或标号的偏移地址
; Test12_2.asm
.386
.model flat, stdcall
include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
.data
v1 db 'abcdefg', 0
v2 dd 11223344h
.code
main proc
PrintHex offset v1 ;00403000
PrintHex offset v2 ;00403008
PrintHex offset main ;00401000 - 这里的 main 是个标号
ret
;本例中的 offset 不能用 addr 代替
main endp
end main
; Test12_4.asm
.386
.model flat, stdcall
;include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
.code
main 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, 0
main endp
end main
OFFSET 和 ADDR 的异同:
1、offset 不能获取局部变量的地址;
2、addr 只能用于调用函数(invoke)时, 不能用于赋值操作;
3、addr 面对局部变量时会转换为 lea 等指令, addr 面对全局变量时则直接调用 offset;
4、在 invoke 中应尽量使用 addr, 其他只用 offset.