zoukankan      html  css  js  c++  java
  • 使用MASM01 Win32汇编语言009

    使用MASM01

     

    让编程改变世界

    Change the world by program


     

    使用MASM

      经过上一讲的准备工作,相信大家已经搭建好了 Win32 汇编的工作环境,并已经知道编译、链接一个程序的过程和原理了。 现在,我们让例子回归到经典: [codesyntax lang="c"]
    #include <stdio.h>
    int main(void)
    {
        Printf(“Hello, worldn”);
    } // 事实上想想,这不正是初生的婴儿?!
    [/codesyntax]  

    Win32汇编源程序的结构

      麻雀虽小,五脏俱全。刚刚那个C语言的”Hello, world”程序包含了C语言中的最基本的格式。 在C语言的源程序中,我们不需要为堆栈段、数据段和代码段的定义而烦恼,编译器会自己解决。   回顾一下,在DOS 下的汇编这段代码会变成什么样? 在例子中我们看到,stack、data、code都找到了自己的小窝。 回归主题,在Win32 汇编语言下,小麻雀”Hello World” 又会变成什么样子呢? 是不是又不同了?但是,我们怎么就发觉Win32 汇编其实是前边两种形态的集大成者?! 接下来,小甲鱼带大家逐段来理解和接受这个新先的语言!  

    模式定义

      程序的第一部分是模式和源程序格式的定义语句 [codesyntax lang="asm"]
    .386
    .model flat,stdcall
    option casemap:none
    [/codesyntax]   这些指令定义了程序使用的指令集、工作模式和格式。  

    1)指定使用的指令集

    .386语句是汇编语句的伪指令,类似的指令还有:.8086、.186、.286、.386/.386p、.486/.486p和.586/.586p等,用于告诉编译器在本程序中使用的指令集。 在DOS的汇编中默认使用的是8086指令集,那时候如果在源程序中写入80386所特有的指令或使用32位的寄存器就会报错。 Win32环境工作在80386及以上的处理器中,所以这一句.386是必不可少的。   另外,后面带p的伪指令则表示程序中可以使用特权指令,如:mov cr0,eax 这一类指令必须在特权级0上运行,如果只指定.386,那么使用普通的指令是可以的,编译时到这一句就会报错。   如果我们要写的程序是VxD等驱动程序,中间要用到特权指令,那么必须定义.386p,在应用程序级别的Win32编程中,程序都是运行在优先级3上,不会用到特权指令,只需定义.386就够了。 80486和Pentium处理器指令是80386处理器指令的超集,同样道理,如果程序中要用80486处理器或Pentium处理器的指令,则必须定义.486或.586。   另外,Intel公司的80x86系列处理器从Pentium MMX开始增加了MMX指令集,为了使用MMX指令,除了定义.586之外,还要加上一句.mmx伪指令: [codesyntax lang="asm"]
    .386
    .mmx
    [/codesyntax]    

    2)model语句

    .model语句在低版本的宏汇编中已经存在,用来定义程序工作的模式,它的使用方法是: .model 内存模式 [,语言模式] [,其他模式] 内存模式的定义影响最后生成的可执行文件,可执行文件的规模从小到大,可以有很多种类型。   详见下表: [caption id="attachment_673" align="aligncenter" width="780"] 内存模式[/caption]   Windows?程序运行在保护模式下,系统把每一个Win32应用程序都放到分开的虚拟地址空间中去运行。 也就是说,每一个应用程序都拥有其相互独立的4GB地址空间。   对Win32程序来说,只有一种内存模式,即flat(平坦)模式,意思是内存是很平坦地从0延伸到4GB,再没有64KB段大小限制。 对比一下DOS的Hello World和Win32的Hello World开始部分的不同,DOS程序中有这样语句 [codesyntax lang="asm"]
    mov ax,data
    mov ds,ax
    [/codesyntax]   意思是把数据段寄存器DS指向data数据段,data数据段在前面已经用data segment语句定义,只要DS不重新设置,那么从此以后指令中涉及的数据默认将从data数据段中取得。 所以下面的语句是从data数据段取出szHello字符串的地址后再显示: [codesyntax lang="asm"]
    mov ah,9
    mov dx,offset szHello
    int 21h
    [/codesyntax]   纵观Win32汇编的源程序,没有一处可以找到ds或es等段寄存器的使用。 因为所有的4GB空间用32位的寄存器全部都能访问到了,不必在头脑中随时记着当前使用的是哪个数据段,这就是平坦内存模式带来的好处。   如果定义了.model flat,MASM自动为各种段寄存器做了如下定义: ASSUME cs:FLAT, ds:FLAT, ss:FLAT, es:FLAT, fs:ERROR, gs:ERROR 也就是说,CS,DS,SS和ES段全部使用平坦模式,FS和GS寄存默认不使用,这时若在源程序中使用FS或GS,在编译时会报错。   如果有必要使用它们,只需在使用前用下面的语句声明一下就可以了: assume fs:nothing, gs:nothing 或者 assume fs:flat, gs:flat   在Win32汇编中,.model语句中还应该指定语言模式,即子程序和调用方式。 例子中用的是stdcall,它指出了调用子程序或Win32 API时参数传递的次序和堆栈平衡的方法。 相对于stdcall,不同的语言类型还有C, SysCall, BASIC, FORTRAN 和PASCALL,虽然各种高级语言在调用子程序时都是使用堆栈来传递参数。 Windows的API调用使用是的stdcall格式,所以在Win32汇编中没有选择,必须在.model中加上stdcall参数。  

    话题:理解stdcall和cdecl

     

    (1)_stdcall调用

    _stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,被调函数自身在返回前清空堆栈。WIN32 Api都采用_stdcall调用方式。  

    (2)_cdecl调用

    _cdecl是C/C++的缺省调用方式,参数采用从右到左的压栈方式,传送参数的内存栈由调用者维护。 _cedcl约定的函数只能被C/C++调用,每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。 [buy] 获得所有教学视频、课件、源代码等资源打包 [/buy] [Downlink href='http://urlxf.qq.com/?Ez26je7']视频下载上[/Downlink] [Downlink href='http://urlxf.qq.com/?32aaiim']视频下载下[/Downlink]
  • 相关阅读:
    dedecms 权重排序问题
    HTML5学习笔记简明版(1):HTML5介绍与语法
    通过jquery 获取文本框的聚焦和失焦方法
    14种网页图片和文字特效的jQuery插件代码
    input文本框实现宽度自适应代码实例,input文本框
    html5,html5教程
    css的#和.的区别
    css style与class之间的区别,cssclass
    网页点击按钮弹出遮罩层,拖动和关闭效果
    基于CSS+dIV的网页层,点击后隐藏或显示
  • 原文地址:https://www.cnblogs.com/LoveFishC/p/3846138.html
Copyright © 2011-2022 走看看