win32汇编源程序结构

先看一个实例:

; 使用 Win32ASM 写的 Hello, world 程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Hello.asm
; Link /subsystem:windows Hello.obj
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.386.model flat,stdcalloption casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include        \masm32\include\windows.inc
include        \masm32\include\user32.inc
includelib    \masm32\lib\user32.lib
include        \masm32\include\kernel32.inc
includelib    \masm32\lib\kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.data
szCaption    db    'win32-Compilation exercise', 0
szText        db    'Hello, World !', 0;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.code
start:invoke    MessageBox,NULL,offset szText,offset szCaption,MB_OKinvoke    ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>end    start

模式定义 

程序的第一部分是模式和源程序格式的定义语句:

.386
.model flat,stdcall
option casemap:none

这些指令定义了程序使用的指令集、工作模式和格式。

1.指定使用的指令集


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

2.model语句
 

.model语句在低版本的宏汇编中已经存在, 用来定义程序工作的模式, 它的使用方法是:

.model 内存模式 [,语言模式]  [,其他模式]
内存模式的定义影响最后生成的可执行文件,可执行文件的规模从小到大,可以有很多种类型, 在DOS的可执行程序中, 有只用到64KB的.com文件, 也有大大小小的.exe文件。到了Win 32环境下, 又有了可以用4GB内存的PE格式可执行文件, 编写不同类型的可执行文件要用.model语句定义不同的参数, 具体如表3.1所示。

在前面章节中已经提到过:Windows程序运行在保护模式下, 系统把每一个Win 32应用程序都放到分开的虚拟地址空间中去运行,也就是说,每一个应用程序都拥有其相互独立的4GB地址空间, 对Win 32程序来说, 只有一种内存模式, 即flat(平坦) 模式, 意思是内存是很“平坦”地从0延伸到4GB, 再没有64KB段大小限制。
如果定义了.model flat, MASM自动为各种段寄存器做了如下定义:
ASSUME CS:FLAT,ds:FLAT,SS:FLAT,es:FLAT,fs:ERROR,gs:ERROR
 

在Win 32汇编中, .model语句中还应该指定语言模式, 即子程序的调用方式, 例子中用的是stdcall, 它指出了调用子程序或Win32API时参数传递的次序和堆栈平衡的方法, 相对于stdcall, 不同的语言类型还有C, SysCall, BASIC, FORTRAN和PASCAL, 虽然各种高级语言在调用子程序时都是使用堆栈来传递参数,但它们的处理方法各有不同。要和其他语言配合, 就必须指定相应的语言种类。Windows的API调用使用的是stdcall格式, 所以在Win 32汇编中没有选择, 必须在.model中加上stdcall参数
 

3.option语句
 

用option语句定义的选项有很多, 如option language定义和option segment定义等, 在Win 32汇编程序中, 需要的只是定义option case map:none, 这个语句定义了程序中的变量和子程序名是否对大小写敏感, 由于Win32API中的API名称是区分大小写的, 所以必须指定这个选项, 否则在调用API的时候会有问题。
 

段的定义
 

1.段的概念
 

把上面的Win32的Hello World源程序中的语句归纳精简一下,再列在下面:

       .386.model flat,stdcalloption casemap:none<一些include语句>.data<一些字符串、变量定义>.code<代码><开始标号><其他语句>end 开始标号

下面是包含全部段的源程序结构:
 

.386.model flat,stdcalloption casemap:none<一些include语句>.stack [堆栈段的大小].data<一些初始化过的变量定义>.data?<一些没有初始化过的变量定义>.const<一些常量定义>.code<代码><开始标号><其他语句>end 开始标号

.stack, .data,.data?, .const和.code是分段伪指令, Win 32中实际上只有代码和数据之分, .data, .data?和.const都是数据段, .code是代码段, 与DOS汇编不同, 由于Win 32汇编不必考虑堆栈, 系统会为程序分配一个向下扩展的、足够大的段作为堆栈段, 所以.stack段定义常常被忽略。

2.数据段
 

.data, .data?和.const定义的是数据段, 分别对应不同方式的数据定义, 在最后生成的可执行文件中也分别放在不同的节区(Section) 中。程序中的数据定义一般可以归纳为3类。
第一类是可读可写的已定义变量。这些数据在源程序中已经被定义了初始值,而且在程序的执行中有可能被更改, 如一些标志等, 这些数据必须定义在.data段中, .data段是已初始化数据段,其中定义的数据是可读可写的,在程序装入完成的时候,这些值就已经在内存中了, .data段一般存放在可执行文件的_DATA节区内。
第二类是可读可写的未定义变量。这些变量一般是当做缓冲区或者在程序执行后才开始使用的, 这些数据可以定义在.data段中, 也可以定义在.data?段中, 但一般把它放到.data?段中。虽然定义在这两种段中都可以正常使用, 但定义在.data?段中不会增大.exe文件的大小。举例说明,如果要用到一个100KB的缓冲区,可以用下面的语句定义:
 

szBuffer         db           100 * 1024 dup (?)

这个语句如果放在.data段中, 编译器认为这些数据在程序装入时就必须有效, 所以它在生成可执行文件的时候保留了所有的100KB的内容,即使它们是全零!假设程序其他部分的大小是50KB, 那么最后的.exe文件就会是150KB大小, 如果缓冲区定义为1MB, 那么.exe文件会增大到1050KB。.data?段则不同, 其中的内容编译器会认为程序在开始执行后才会用到,所以在生成可执行文件的时候只保留了大小信息,不会为它浪费磁盘空间。在与上面同样的情况下, 即使缓冲区定义为1MB, 可执行文件同样只有50KB!总之, .data?段是未初始化数据段, 其中的数据也是可读可写的, 但在可执行文件中不占空间, .data?段在可执行文件中一般存放在_BSS节区中。
第三类数据是一些常量。如一些要显示的字符串信息,它们在程序装入的时候也已经有效, 但在整个执行过程中不需要修改, 这些数据可以放在.const段中, .const段是常量段,它是可读不可写的。为了方便起见, 在小程序中常常把常量一起定义到.data段中, 而不另外定义一个.const段。在程序中如果不小心用了对.const段中的数据做写操作的指令, 会引起保护错误, Windows会显示一个如图3.2所示的提示框并结束程序。

如果不怕程序可读性不佳的话, 把.const段中定义的东西混到.code段中去也可以正常使用, 因为.code段也是可以读的。
 

3.代码段
 

.code段是代码段, 所有的指令都必须写在代码段中, 在可执行文件中, 代码段一般是放在_TEXT节区中的。Win 32环境中的数据段是不可执行的, 只有代码段有可执行的属性。对于工作在特权级3的应用程序来说, .code段是不可写的, 在编DOS汇编程序的时候, 好事的程序员往往有个习惯,就是靠改动代码段中的代码来做一些反跟踪的事情,如果企图在Win 32汇编下做同样的事情, 结果就是和上面同样的“非法操作”。
当然事物总有两面性, 在Windows 95下, 在特权级0下运行的程序对所有的段都有读写的权利,包括代码段。另外,在优先级3下运行的程序也不是一定不能写代码段,代码段的属性是由可执行文件PE头部中的属性位决定的, 通过编辑磁盘上的.exe文件, 把代码段属性位改成可写,那么在程序中就允许修改自己的代码段。一个典型的应用就是一些针对可执行文件的压缩软件和加壳软件, 如Up x和PeCompact等, 这些软件靠把代码段进行变换来达到解压缩或解密的目的,被处理过的可执行文件在执行时需要由解压代码来将代码段解压缩,这就需要写代码段,所以这些软件对可执行文件代码段的属性预先做了修改


4.堆栈段


在程序中不必定义堆栈段,系统会自动分配堆栈空间。惟一值得一提的是,堆栈段的内存属性是可读写并且是可执行的,这样靠动态修改代码的反跟踪模块可以拷贝到堆栈中去边修改边执行。一些病毒或者黑客工具用到的缓冲区溢出技术也用到了这个特征,有兴趣了解的读者可以查阅相关的资料。
 

程序结束和程序入口
 

在C语言源程序中,程序不必显式地指定程序由哪里开始执行,编译器已经约定好从main() 函数开始执行了。而在汇编源程序中, 并没有一个main函数, 程序员可以指定从代码段的任何一个地方开始执行, 这个地方由程序最后一句的end语句来指定:
end    [开始地址]

这句语句同时表示源程序结束, 所有的代码必须在end语句之前, 例如:

end start

上述语句指定程序从start这个标号开始执行。当然, start标号必须在程序的代码段中有所定义。
但是,一个源程序不必非要指定入口标号,这时候可以把开始地址忽略不写,这种情况发生在编写多模块程序的单个模块的时候。当分开写多个程序模块时,每个模块的源程序中也可以包括.data, .data?, .const和.code段, 结构就和上面的Win32 HelloWorld一样, 只是其他模块最后的end语句必须不带开始地址。当最后把多个模块链接在一起的时候,只能有一个主模块指定入口地址,在多个模块中指定入口地址或者没有一个模块指定了入口地址,链接程序都会报错。
 

注释和换行
 

注释是源程序中不可忽略的一部分,汇编源程序的注释以分号(;)开始,注释既可以在一行的头部,也可以在一行的中间,一行中所有在分号之后的字符全部当做注释处理,但在字符串的定义中包含在引号内的分号不当做是注释的开始。

当源程序的某一行过长,不利于阅读的时候,可以分行书写,分行的办法是在一行的最后用反斜杠(\)做换行符,如:

“一行的最后”指的是最后一个有用的字符,反斜杠后面多几个空格或加上注释并不影响换行符的使用, 如上例所示, 这一点与makefile文件中换行符的规定有所不同。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/154470.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

three.js学习之vR展厅

目标 1、需要会的知识点three.js的场景&#xff0c;摄像机&#xff0c;渲染器&#xff0c;轨道控制器&#xff0c;坐标轴&#xff0c;场景适配&#xff0c;渲染循环创建立方缓冲几何体、纹理、3d物体 实现&#xff1a;创建立方几何体&#xff0c;纹理贴图镜面反向渲染&#xf…

Springboot使用sqlcipher4加密sqlite数据库

在有些业务场景&#xff0c;需要使用sqlite数据库&#xff0c;但sqlite数据库生的db文件&#xff0c;是明文的&#xff0c;该文件被别人拿到&#xff0c;就可以看到里面的所有数据&#xff0c;非常不安全&#xff0c;市面上有很多对sqlite数据库文件加密的方式&#xff0c;但都…

vscode远程ssh服务器且更改服务器别名

目录 1、打开VS Code并确保已安装"Remote - SSH"扩展。如果尚未安装&#xff0c;请在扩展市场中搜索并安装它。 2、单击左下角的"Remote Explorer"图标&#xff0c;打开远程资源管理器。 3、在远程资源管理器中&#xff0c;单击右上角的齿轮图标&#x…

1712A 300A嵌入式电源系统

1712A 300A嵌入式电源系统 1712A 300A嵌入式电源系统采用模块化设计、组合式结构&#xff0c;由控制器、整流模块、交流配电单元、直流配电单元等组成。该系统将交流电转换成稳定的-48V直流电&#xff0c;用于铁塔、移动、电信、联通等公司的传输、接入网&#xff0c;以及专网等…

vscode 连接ubuntu git下载缓慢

在ubuntu20.04下载&#xff1a; git clone https://github.com/introlab/rtabmap.git src/rtabmap 挂掉情况 export https_proxyhttp://10.10.10.176:7890export http_proxyhttp://10.10.10.176:7890 其中 10.10.10.176是我本机的ip地址&#xff0c;7890是我的代理后几位 如…

【PPT】ppt里面使用svg图标

要想编辑好的PPT&#xff0c;少不了小图标的美化&#xff0c;图标可以使PPT变得更有趣&#xff0c;更易懂&#xff0c;更美观。 对于png&#xff0c;主要处理它的颜色&#xff0c;可使用【重新着色】功能。 对于jpg&#xff0c;主要处理它的背景&#xff0c;删除背景后同png处…

JSONUtil.parse将java对象转为json时,需要在java对象中设置get、set方法

想要使用JSONUtil.parse将java对象转为json格式&#xff0c;但是一直为空&#xff0c;代码如下 public class MyTest {public static void main(String[] args) {Test3<String> test3 new Test3<>("2","hhhhhhaaa");System.out.println(JSON…

UI设计师岗位的基本职责八篇

UI设计师岗位的基本职责1 职责&#xff1a; 1. 负责公司互联网产品app、web、h5等的用户界面设计工作; 2. 负责运营活动相关的平面及视频设计支持; 3. 负责完成产品相关的界面、图标、动画等的图形界面设计&#xff0c;并参与制定、编写产品视觉设计规范文档; 4. 整理和分…

Oracle 云服务即将支持 PostgreSQL!

2023 年 9 月 19 日&#xff0c;Oracle 产品团队发布了一篇文章&#xff0c;宣布 Oracle 云基础架构&#xff08;OCI&#xff09;开始提供 PostgreSQL 服务。目前支持的版本为 PostgreSQL 14.9&#xff0c;提供有限支持&#xff0c;12 月份将会提供正式版本。 众所周知&#x…

京东获取推荐商品列表 API

item_recommend-获取推荐商品列表 请求参数 请求参数&#xff1a;type 参数说明&#xff1a;type:推荐类型 进入API测试页 响应参数 Version: Date: 名称类型必须示例值描述 items items[]0获取推荐商品列表 num_iid Bigint010021415166448宝贝ID detail_url String0http…

Tabby All configured authentication methods failed

文章目录 重要序言错误原因tabby的连接设置 总结 重要序言 Tabby是一款美观耐用的软件&#xff0c;平常一直用来输入密码方法SSH公司服务器&#xff0c;后来为了另外一台服务器加了SSH私钥&#xff0c;之后Tabby SSH连接死活不成功&#xff0c;哎&#xff0c;折腾了好久&#…

C++ stack和queue模拟实现

目录 stack习题练习逆波兰表达式求值基本计算器 stack模拟实现queuequeue模拟实现deque了解priority_queuepriority_queue模拟实现仿函数 stack stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提…

修炼k8s+flink+hdfs+dlink(三:安装dlink)

一&#xff1a;mysql初始化。 mysql -uroot -p123456 create database dinky; grant all privileges on dinky.* to dinky% identified by dinky with grant option; flush privileges;二&#xff1a;上传dinky。 上传至目录/opt/app/dlink tar -zxvf dlink-release-0.7.4.t…

asp.net饭店订餐管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio计算机设计定制

一、源码特点 asp.net 饭店订餐管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语 言开发 asp.net饭店订餐系统 二、功能介…

HTML5开发实例-3D全景(ThreeJs全景Demo) 详解(图)

前言 在现在市面上很多全景H5的环境下,要实现全景的方式有很多,可以用css3直接构建也可以用基于threeJs的库来实现,还有很多别的制作全景的软件使用 本教学适用于未开发过3D全景的工程狮 如果觉得内容太无聊可以直接跳到最后 下载代码 理论 整个3D全景所用的相关理论就…

知识增强语言模型提示 零样本知识图谱问答10.8

知识增强语言模型提示 零样本知识图谱问答 摘要介绍相关工作方法零样本QA的LM提示知识增强的LM提示与知识问题相关的知识检索 摘要 大型语言模型&#xff08;LLM&#xff09;能够执行 零样本closed-book问答任务 &#xff0c;依靠其在预训练期间存储在参数中的内部知识。然而&…

在React中,什么是props(属性)?如何向组件传递props?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

QTableWidget 表格增删数据

QTableWidgetQTableWidgetQTableWidget部分使用方法&#xff0c;如在表格中插入或删除一行数据以及清空表格数据等。在添加数据时&#xff0c;设置了条件判断如正则表达式&#xff0c;若用户输入的数据不合法&#xff0c;则添加失败并提示用户错误的地方&#xff0c;便于用户修…

API接口安全运营研究(内附官方开发平台api接口接入方式)

摘 要 根据当前API技术发展的趋势&#xff0c;从实际应用中发生的安全事件出发&#xff0c;分析并讨论相关API安全运营问题。从风险角度阐述了API接口安全存在的问题&#xff0c;探讨了API检测技术在安全运营中起到的作用&#xff0c;同时针对API安全运营实践&#xff0c;提出…

Day 4 C++

算术运算符重载 种类&#xff1a; - * / % #include <iostream>using namespace std;class Cacu {friend const Cacu operator(const Cacu &l,const Cacu &r);friend const Cacu operator-(const Cacu &l,const Cacu &r);friend const Cacu operator*…