汇编符号语言

56 篇文章 5 订阅

在这里插入图片描述
CSDN话题挑战赛第1期
活动详情地址第1期话题PK赛
参赛话题:汇编知识分享
话题描述:我们的计算机知识就像一座金字塔,底层是数学,上面是数字电路,然后是汇编,再往上是操作系统、网络,数据库、高级编程语言、框架等等…我们不可能精通这个金子塔的每一层, 但是想走的更远就必须要了解这个金字塔的底层。因此,学习汇编并不是为了用汇编在应用层设计程序,而是为了深刻理解机器运行程序的机理。就像对于人来说不能没有常识一样,尽管常识不能直接挣钱吃饭,但它影响谈吐,影响你的判断力和决断力,决定着你接受新事物和新知识的程度。汇编就是计算机语言里面的常识和基础。

大家好,我是格格巫。

每篇前言

汇编语言是最古老的编程语言,在所有的语言中,它与原生机器语言最为接近。它能直接访问计算机硬件,要求用户了解计算机架构和操作系统。

如果小伙伴正在学的大学课程的名称与下列课程之一相似,可以通过本教程学到更多的专业知识:
微计算机汇编语言
汇编语言编程
计算机体系结构导论
计算机系统基础
嵌入式系统编程

通过本教程有助于学习计算机体系结构、机器语言和底层编程的基本原理。可以学到足够的汇编语言,来测试其掌握的当今使用最广泛的微处理器系列的知识。不会学到用模拟汇编器来编写一个“玩具”计算机;MASM 是一个由业界专业人士使用的工业级汇编器。大家将从程序员的角度来了解 Intel 处理器系列的体系结构。

如果小伙伴计划成为 C 或 C++ 开发者,就需要理解内存、地址和指令是如何在底层工作的。在高级语言层次上,很多编程错误不容易被识别。因此,程序员经常会发现需要“深入”到程序内部,才能找出程序不工作的原因。

☀️作者简介:
🐋个人主页:
🎁系列专栏:
🌱每日一句:


要用汇编解决什么问题?

提示:这里描述在学习工作中遇到的要用汇编解决的问题&&或想分享的汇编知识

需要怎样的背景知识?
在学习本教程之前,至少使用过一种结构化高级语言进行编程,如 Java、C、Python 或 C++。需要了解如何使用 IF 语句、数组和函数来解决编程问题。
什么是汇编器和链接器?
汇编器(assembler)是一种工具程序,用于将汇编语言源程序转换为机器语言。链接器(linker)也是一种工具程序,它把汇编器生成的单个文件组合为一个可执行程序。还有一个相关的工具,称为调试器(debugger),使程序员可以在程序运行时,单步执行程序并检查寄存器和内存状态。
需要哪些硬件和软件?
一台运行 32 位或 64 位 Microsoft Windows 系统的计算机,并已安装了近期版本的 Microsoft Visual Studio。
MASM 能创建哪些类型的程序?
32 位保护模式(32-Bit Protected Mode):32 位保护模式程序运行于所有的 32 位和 64 位版本的 Microsoft Windows 系统。它们通常比实模式程序更容易编写和理解。从现在开始,将其简称为 32 位模式。

64 位模式(64-Bit Mode):64 位程序运行于所有的 64 位版本 Microsoft Windows 系统。

16 位实地址模式(16-Bit Real-Address Mode):16 位程序运行于 32 位版本 Windows 和嵌入式系统。 64 位 Windows 不支持这类程序。
汇编语言与机器语言有什么关系?
机器语言(machine language)是一种数字语言, 专门设计成能被计算机处理器(CPU)理解。所有 x86 处理器都理解共同的机器语言。

汇编语言(assembly language)包含用短助记符如 ADD、MOV、SUB 和 CALL 书写的语句。汇编语言与机器语言是一对一(one-to-one)的关系:每一条汇编语言指令对应一条机器语言指令。
C++ 和 Java 与汇编语言有什么关系?
高级语言如 Python、C++ 和 Java 与汇编语言和机器语言的关系是一对多(one-to-many)。比如,C++ 的一条语句就会扩展为多条汇编指令或机器指令。

大多数人无法阅读原始机器代码,因此,这里探讨的是与之最接近的汇编语言。例如,下面的 C++ 代码进行了两个算术操作,并将结果赋给一个变量。假设 X 和 Y 是 整数:
int Y;
int X = ( Y + 4 ) * 3;
与之等价的汇编语言程序如下所示。这种转换需要多条语句,因为每条汇编语句只对应一条机器指令:
mov eax,Y ;Y 送入 EAX 寄存器
add eax,4 ;EAX 寄存器内容加 4
mov ebx,3 ;3 送入 EBX 寄存器
imul ebx ;EAX 与 EBX 相乘
mov x,eax ;EAX 的值送入 X
寄存器(register)是 CPU 中被命名的存储位置,用于保存操作的中间结果。这个例子的重点不是说明 C++ 与汇编语言哪个更好,而是展示它们的关系。
汇编语言可移植吗?
一种语言,如果它的源程序能够在各种各样的计算机系统中进行编译和运行,那么这种语言被称为是可移植的(portable)。

例如,一个 C++ 程序,除非需要特别引用某种操作系统的库函数,否则它就几乎可以在任何一台计算机上编译和运行。Java 语言的一大特点就是,其编译好的程序几乎能在所有计算机系统中运行。

汇编语言不是可移植的,因为它是为特定处理器系列设计的。目前广泛使用的有多种不同的汇编语言,每一种都基于一个处理器系列。

对于一些广为人知的处理器系列如 Motorola 68x00、x86、SUN Sparc、Vax 和 IBM-370,汇编语言指令会直接与该计算机体系结构相匹配,或者在执行时用一种被称为微代码解释器(microcode interpreter)的处理器内置程序来进行转换。
为什么要学习汇编语言?
如果对学习汇编语言还心存疑虑,考虑一下这些观点:
如果是学习计算机工程,那么很可能会被要求写嵌入式(embedded)程序。嵌入式程序是指一些存放在专用设备中小容量存储器内的短程序,这些专用设备包括:电话、汽车燃油和点火系统、空调控制系统、安全系统、数据采集仪器、显卡、声卡、硬盘驱动器、调制解调器和打印机。由于汇编语言占用内存少,因此它是编写嵌入式程序的理想工具。
处理仿真和硬件监控的实时应用程序要求精确定时和响应。高级语言不会让程序员对编译器生成的机器代码进行精确控制。汇编语言则允许程序员精确指定程序的可执行代码。
电脑游戏要求软件在减少代码大小和加快执行速度方面进行高度优化。就针对一个目标系统编写能够充分利用其硬件特性的代码而言,游戏程序员都是专家。他们经常选择汇编语言作为工具,因为汇编语言允许直接访问计算机硬件,所以,为了提高速度可以对代码进行手工优化。
汇编语言有助于形成对计算机硬件、操作系统和应用程序之间交互的全面理解。使用汇编语言,可以运用并检验从计算机体系结构和操作系统课程中获得的理论知识。
一些高级语言对其数据表示进行了抽象,这使得它们在执行底层任务时显得有些不方便,如位控制。在这种情况下,程序员常常会调用使用汇编语言编写的子程序来完成他们的任务。
硬件制造商为其销售的设备创建设备驱动程序。设备驱动程序(device driver)是一种程序,它把通用操作系统指令转换为对硬件细节的具体引用。比如,打印机制造商就为他们销售的每一种型号都创建了一种不同的 MS-Windows 设备驱动程序。通常,这些设备驱动程序包含了大量的汇编语言代码。
汇编语言有规则吗?
大多数汇编语言规则都是以目标处理器及其机器语言的物理局限性为基础的。比如,CPU 要求两个指令操作数的大小相同。与C++ 或 Java 相比,汇编语言的规则较少,因为,前者是用语法规则来减少意外的逻辑错误,而这是以限制底层数据访问为代价的。

汇编语言程序员可以很容易地绕过高级语言的限制性特征。例如,Java 就不允许访问特定的内存地址。程序员可以使用 JNI(Java Native Interface)类来调用 C 函数绕过这个限制,可结果程序不容易维护。

反之,汇编语言可以访问所有的内存地址。但这种自由的代价也很高:汇编语言程序员需要花费大量的时间进行调试。

下表比较了汇编语言和高级语言对各种应用类型的适应性。

应用类型 高级语言 汇编语言
商业或科学应用程序,为单一的中型或大型平台编写 规范结构使其易于组织和维护大量代码 最小规范结构,因此必须由具有不同程度经验的程序员来维护结构。这导致对已有代码的维护困难
硬件设备驱动程序 语言不一定提供对硬件的直接访问。 即使提供了,可能也需要难以控制的编码技术,这导致维护困难 对硬件的访问直接且简单。当程序较短且文档良好时易于维护
为多个平台(不同的操作系统)编写的商业或科学应用程序 通常可移植。在每个目标操作系统上, 源程序只做少量修改就能重新编译 需要为每个平台单独重新编写代码, 每个汇编器都使用不同的语法。维护困难
需要直接访问硬件的嵌入式系统和电脑游戏 可能生成很大的可执行文件,以至于超出设备的内存容量 理想,因为可执行代码小,运行速度快
C 和 C++ 语言具有一个独特的特性,能够在高级结构和底层细节之间进行平衡。直接访问硬件是可能的,但是完全不可移植。大多数 C 和 C++ 编译器都允许在其代码中嵌入汇编语句,以提供对硬件细节的访问。

高级语言实现方法

代码部分:

运行时堆栈是内存数组,CPU 用 ESP(扩展堆栈指针,extended stack pointer)寄存器对其进行直接管理,该寄存器被称为堆栈指针寄存器(stack pointer register)。

32位模式下,ESP 寄存器存放的是堆栈中某个位置的 32 位偏移量。ESP 基本上不会直接被程序员控制,反之,它是用 CALL、RET、PUSH 和 POP 等指令间接进行修改。

ESP 总是指向添加,或压入(pushed)到栈顶的最后一个数值。为了便于说明,假设现有一个堆栈,内含一个数值。如下图所示,ESP 的内容是十六进制数 0000 1000,即刚压入堆栈数值(0000 0006)的偏移量。在图中,当堆栈指针数值减少时,栈顶也随之下移。
在这里插入图片描述

包含一个值得堆栈

上图中,每个堆栈位置都是32位长,这 是32位模式下运行程序的情形。

运行时堆栈工作于系统层,处理子程序调用。堆栈 ADT 是编程结构,通常用高级编程语言编写,如 C++ 或 Java。它用于实现基于后进先出操作的算法。
入栈操作
32 位入栈操作把栈顶指针减 4,再将数值复制到栈顶指针指向的堆栈位置。下图展示了把 0000 00A5 压入堆栈的结果,堆栈中已经有一个数值(0000 0006)。注意,ESP 寄存器总是指向最后压入堆栈的数据项。
下

将整数压入堆栈

上图中显示的堆栈顺序与之前示例给出的盘堆栈顺序相反,这是因为运行时堆栈在内存中是向下生长的,即从高地址向低地址扩展。入栈之前, ESP=0000 1000h;入栈之后,ESP=0000 0FFCh。图显示了同一个堆栈总共压入 4 个整数之后的情况。
在这里插入图片描述

压入数值00000001和00000002的堆栈
出栈操作
出栈操作从堆栈删除数据。数值弹岀堆栈后,栈顶指针增加(按堆栈元素大小),指向堆栈中下一个最高位置。下图展示了数值 0000 0002 弹出前后的堆栈情况。
在这里插入图片描述

从运行时堆栈弹出一个数值

ESP 之下的堆栈域在逻辑上是空白的,当前程序下一次执行任何数值入栈操作指令都可以覆盖这个区域。
堆栈应用
运行时堆栈在程序中有一些重要用途:
当寄存器用于多个目的时,堆栈可以作为寄存器的一个方便的临时保存区。在寄存器被修改后,还可以恢复其初始值。
执行 CALL 指令时,CPU 在堆栈中保存当前过程的返回地址。
调用过程时,输入数值也被称为参数,通过将其压入堆栈实现参数传递。
堆栈也为过程局部变量提供了临时存储区域。
在这里插入代码片


汇编语言如何实现

在汇编语言中,通常用术语过程(procedure)来指代子程序。在其他语言中,子程序也被称为方法或函数。

就面向对象编程而言,单个类中的函数或方法大致相当于封装在一个汇编语言模块中的过程和数据集合。汇编语言出现的时间远早于面向对象编程,因此它不具备面向对象编程中的形式化结构。汇编程序员必须在程序中实现自己的形式化结构。
定义过程
过程可以非正式地定义为:由返回语句结束的已命名的语句块。过程用 PROC 和 ENDP 伪指令来定义,并且必须为其分配一个名字(有效标识符)。到目前为止,所有编写的程序都包含了一个名为 main 的过程,例如:
main PROC
.
.
main ENDP

当在程序启动过程之外创建一个过程时,就用 RET 指令来结束它。RET 强制 CPU 返回到该过程被调用的位置:
sample PROC
.
.
ret
sample ENDP

过程中的标号
默认情况下,标号只在其被定义的过程中可见。这个规则常常影响到跳转和循环指令。在下面的例子中,名为 Destination 的标号必须与 JMP 指令位于同一个过程中:
jmp Destination

解决这个限制的方法是定义全局标号,即在名字后面加双冒号 (:😃。
Destination::

就程序设计而言,跳转或循环到当前过程之外不是个好主意。过程用自动方式返回并调整运行时堆栈。如果直接跳出一个过程,则运行时堆栈很容易被损坏。
示例:三个整数求和
现在创建一个名为 SumOf 的过程计算三个 32 位整数之和。假设在过程调用之前,整数已经分配给 EAX、EBX 和 ECX。过程用 EAX 返回和数:
SumOf PROC
add eax,ebx
add eax,ecx
ret
SumOf ENDP
过程说明
要培养的一个好习惯是为程序添加清晰可读的说明。下面是对放在每个过程开头的信息的一些建议:
对过程实现的所有任务的描述。
输入参数及其用法的列表,并将其命名为 Receives ( 接收 )。如果输入参数对其数值有特殊要求,也要在这里列岀来。
对过程返回的所有数值的描述,并将其命名为 Returns ( 返回 )。
所有特殊要求的列表,这些要求被称为先决条件 (preconditions),必须在过程被调用之前满足。列表命名为 Requires。例如,对一个画图形线条的过程来说,一个有用的先决条件是该视频显示适配器必须已经处于图形模式。

上述选择的描述性标号,如 ReceivesReturns 和 Requires,不是绝对的;其他有用的名字也常常被使用。

有了这些思想,现在对 SumOf 过程添加合适的说明:
;-------------------------------------------------------
; sumof
; 计算 3 个 32 位整数之和并返回和数。
; 接收:EAX、EBX和ECX为3个整数,可能是有符号数,也可能是无符号数。
; 返回:EAX=和数
;------------------------------------------------------
SumOf PROC
add eax,ebx
add eax,ecx
ret
SumOf ENDP
用高级语言,如 C 和 C++,编写的函数,通常用 AL 返回 8 位的值,用 AX 返回 16 位的值,用 EAX 返回 32 位的值。

本期内容就结束了,如果内容有误,麻烦大家评论区指出!
如有疑问可以在评论区留言!
下期预告: ******

CSDN话题挑战赛第1期
活动详情地址:
第1期话题PK赛

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值