Win32 汇编学习 (1):基本概念

本贴最后更新于 2508 天前,其中的信息可能已经时异事殊

背景知识

Windows 把每一个 Win32 应用程序放到分开的虚拟地址空间中去运行,也就是说每一个应用程序都拥有其相互独立的 4GB 地址空间,当然这倒不是说它们都拥有 4GB 的物理地址空间,而只是说能够在 4GB 的范围内寻址。操作系统将会在应用程序运行时完成 4GB 的虚拟地址和物理内存地址间的转换。这就要求编写应用程序时必须格守 Windows 的规范,否则极易引起内存的保护模式错误。而过去的 Win16 内存模式下,所有的应用程序都运行于同一个 4GB 地址空间,它们可以彼此"看"到别的程序的内容,这极易导致一个应用程序破坏另一个应用程序甚至是操作系统的数据或代码。

和 16 位 Windows 下的把代码分成 DATA,CODE 等段的内存模式不同,WIN32 只有一种内存模式,即 FLAT 模式,意思是"平坦"的内存模式,再没有 64K 的段大小限制,所有的 WIN32 的应用程序运行在一个连续、平坦、巨大的 4GB 的空间中。这同时也意味着您无须和段寄存器打交道,您可以用任意的段寄存器寻址任意的地址空间,这对于程序员来说是非常方便的,这也使得用 32 位汇编语言和用 C 语言一样方便。 在 Win32 下编程,有许多重要的规则需要遵守。有一条很重要的是:Windows 在内部频繁使用 ESI,EDI,EBP,EBX 寄存器,而且并不去检测这些寄存器的值是否被更改,这样当您要使用这些寄存器时必须先保存它们的值,待用完后再恢复它们,一个最显著的应用例子就是 Windows 的 CallBack 函数中。

内容

一般的 Win32 汇编都有下面的程序段,这是一个 Win32 汇编编程的基础框架,若您现在还不知道这些指令的确切意义的话,没关系, 随后我就会给大家详细解释。

.386 
.MODEL Flat, STDCALL 
.DATA 
    <Your initialized data> 
    ...... 
.DATA? 
   <Your uninitialized data> 
   ...... 
.CONST 
   <Your constants> 
   ...... 
.CODE 
   <label> 
    <Your code> 
   ..... 
    end <label> 

这就是一般 Win32 汇编编程的基础框架,其中各个关键词的解释说明如下:

.386

这是一个汇编语言伪指令,他告诉编译器我们的程序是使用 80386 指令集编写的。您还可以使用 .486、.586, 但最安全的还是使用.386。对于每一种 CPU 有两套几乎功能相同伪指令: .386/.386P、 486/.486P、 586/.586P。 带 P 的指令标明您的程序中可以用特权级指令。特权级指令是保留给操作系统的,如虚拟设备驱动程序。在大多数时间,您的程序都无须运行在 RING0 层,故用不带后缀 P 的伪指令已足够了。

.MODEL FLAT,STDCALL 

.MODEL 是用来指定内存模式的伪指令,在 Win32 下,只有一种内存模型,那就是 FLAT。 STDCALL 告诉编译器参数的传递约定。参数的传递约定是指参数传达时的顺序(从左到右或从右到左)和由谁恢复堆栈指针(调用者或被调用者)。在 Win16 下有两种约定:CPASCAL。C 约定规定参数传递顺序是从右到左,即最右边的参数最先压栈,由调用者恢复堆栈指针。

例如:为调用函数 foo ( int first_param, int second_param, int third_param ); 按 C 约定的汇编代码应该是这样的:

push [third_param]
push [second_param]
push [first_param]
call foo
add esp, 3 * 4 ;调用者自己恢复堆栈指针

PASCAL 约定和 C 约定正好相反,它规定参数是从左向右传递,由被调用者恢复堆栈。Win16 采用了 PASCAL 约定, 因为 PASCAL 约定产生的代码量要小。当不知道参数的个数时,C 约定特别有用。如在函数 wsprintf () 中, wsprintf 预先并不知道要传递几个参数,所以它不知道如何恢复堆栈。STDCALLC 约定和 PASCAL 约定的混合体,它规定参数的传递是从右到左,恢复堆栈的工作交由被调用者。Win32 只用 STDCALL 约定,但除了一个特例,即:wsprintf

.DATA 
.DATA? 
.CONST 
.CODE

上面的四个伪指令是"分段"(SECTION)伪指令。我们上面刚讲过 Win32 下没有"段"(SEGMENT)的概念,但是您可以把您的程序分成不同的"分段", 一个"分段"的开始即是上一个"分段"的结束。WIN32 中只有两种性质的"分段":DATACODE

其中 DATA"分段"又分为三种:

  • .DATA 其中包括已初始化的数据。
  • .DATA? 其中包括未初始化的数据。比如有时您仅想预先分配一些内存但并不想指定初始值。使用未初始化的数据的优点是它不占据可执行文件的大小,如:若您要在 .DATA? 段中分配 10,000 字节的空间,您的可执行文件的大小无须增加 10,000 字节,而仅仅是要告诉编译器在装载可执行文件时分配所需字节。
  • .CONST 其中包括常量定义。这些常量在程序运行过程中是不能更改的。 应用程序并不需要以上所有的三个"分段", 可以根据需要进行定义。
  • .CODE 这是代码"分段"。

实际上,分段并不是象在 Dos 下一样,为不同的段分别指出不同的段寄存器,因为 Windows 下只有一个 4GB 的段,Windows 程序中的分段表现在当程序装载时,赋予不同的分段不同的属性,比如说当你的程序加载时,对于 Ring3 程序来说,.code 段是不可写的,而 .data 段是可写的,如果你尝试象在 Dos 下一样写自己的代码部分,你会得到一个蓝屏错误

<label> 
end <label> 

是用来唯一标识您的代码范围的标签, 两个标签必须相同,应用程序的所有可执行代码必须在两个标签之间。

  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    223 引用 • 474 回帖
  • asm
    15 引用 • 5 回帖
  • 阅读
    85 引用 • 242 回帖 • 4 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
Akkuman
python与二次元爱好者,开车司机 荆州

推荐标签 标签

  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    78 引用 • 391 回帖
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 603 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 518 关注
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    354 引用 • 1823 回帖 • 1 关注
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 772 关注
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 1 关注
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    142 引用 • 442 回帖
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 637 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 400 关注
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 653 关注
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    166 引用 • 595 回帖
  • Typecho

    Typecho 是一款博客程序,它在 GPLv2 许可证下发行,基于 PHP 构建,可以运行在各种平台上,支持多种数据库(MySQL、PostgreSQL、SQLite)。

    12 引用 • 65 回帖 • 446 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    91 引用 • 751 回帖 • 1 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 416 关注
  • 反馈

    Communication channel for makers and users.

    123 引用 • 913 回帖 • 250 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 63 关注
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    88 引用 • 1235 回帖 • 410 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    90 引用 • 562 回帖 • 1 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 75 关注
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 335 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖 • 2 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    288 引用 • 734 回帖
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    26 引用 • 196 回帖 • 17 关注
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 50 关注
  • V2Ray
    1 引用 • 15 回帖 • 1 关注
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    123 引用 • 74 回帖 • 2 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 370 关注