让编程改变世界
Change the world by program
szBuffer db 1024 dup ( )
然后mov ax, szBuffer
编译器会报一个错:error A2070: invalid instruction operands
意思是无效的指令操作,为什么呢?因为szBuffer是用db定义的,而ax的尺寸是一个word,等于两个字节,尺寸不符合。 在MASM中,如果要用指定类型之外的长度访问变量,必须显式地指出要访问的长度,这样编译器忽略语法上的长度检验,仅使用变量的地址。 使用的方法是: 类型 ptr 变量名 类型可以是byte, word, dword, fword, qword, real8和real10。 如:mov ax, word ptr szBuffer
mov eax, dword ptr szBuffer
在这里要注意的是,指定类型的参数访问并不会去检测长度是否溢出,看下面一段代码: [codesyntax lang="asm"].data bTest1 db 12h wTest2 dw 1234h dwTest3 dd 12345678h …… .code mov al, bTest1 mov ax, word ptr bTest1 mov eax, dword ptr bTest1 ……[/codesyntax] 上面的程序片断,每一句执行后寄存器中的值是什么呢? mov al, bTest1 这一句很显然使 al 等于 12h,下面的两句呢,ax 和 eax难道等于 0012h 和00000012h吗? 实际运行结果是 3412h 和 78123412h,为什么呢?(DOS汇编基础不错的同学,应该能理解) 现在我们先来看反汇编的内容:详见视频…… 所以说呢,刚才这个例子说明了汇编中用ptr强制覆盖变量长度的时候,实质上是只用了变量的地址而禁止编译器进行检验。 编译器并不会考虑定界的问题,程序员在使用的时候必须对内存中的数据排列有个全局概念,以免越界存取到意料之外的数据。 如果程序员的本意是类似于C语言的强制类型转换,想把bTest1的一个字节扩展到一个字或一个双字再放到ax 或 eax中,高位保持0而不是越界存取到其他的变量,要肿么办呢? 80386处理器提供的 movzx 指令可以实现这个功能,例如:
movzx ax,bTest1 ; ax == 0012h
movzx eax,bTest1 ; eax == 00000012h
movzx eax,cl ; eax == 000000(cl)
movzx eax,ax ; eax == 0000(ax)
用movzx指令进行数据长度扩展是Win32汇编中经常用到的技巧。 [buy] 获得所有教学视频、课件、源代码等资源打包 [/buy] [Downlink href='http://urlxf.qq.com/?YrYFFfM']视频下载[/Downlink]