Win32汇编的 PTR, OFFSET, ADDR

 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 
 
在没有寄存器名存在的情况下,用操作符 X ptr 指明内存单元的长度,X在汇编指令中可以为word或byte等等
 例如:
下面的指令中,用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.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值