汇编语言 Part 1——简介、基本语法、内存分段与内存地址

简介

什么是汇编语言?

汇编语言是一种低级的编程语言,在程序的语句和体系结构的机器代码指令之间有很强的对应关系。

每种汇编语言都特定于特定的计算机体系结构,但需要解释或编译。汇编语言也可以称为符号机器代码。

汇编语言通常每个机器指令都有一个语句,通常也支持汇编指令、程序和内存位置的宏和符号标签。

汇编代码被汇编器转换为可执行的机器代码。转换过程称为汇编。

计算机编程语言的演进

机器语言

与模拟和机电计算机的早期工作不涉及我们所了解编程语言。由于早期的计算机需要直接对每个问题集进行连线,所以设置插头的过程取代了基于文本的算法蒸馏。

随着汞延迟线和磁鼓记忆装置取代机电设备,在无需重新布线的情况下直接写入内存中的地址并提供指令变得更加容易。这通常指的是编写我们称之为 "机器代码 "的内容。现在通常被称为"十六进制",因为现代的32位和64位微处理器系统以8或16十六进制块每时钟周期的速度读取二进制数据。

在计算机级别编写代码是困难的:它要求程序员知道在硬件中寄存器和处理器的指令集的特定位置。阅读机器代码通常比编写它更困难,因此跟踪代码更改几乎是不可能的。

汇编语言

汇编语言的出现意味着第一次升级到计算机代码级别的编程。他提供了一种用字符串操纵符和名称来编写机器代码的方法,而不是原始的二进制版本。它仍然是难以阅读,仍然需要知道哪些指令和寄存器位置,但它可以在纸或屏幕上阅读并汇编成机器代码。

我们还在使用汇编,大多数计算机外设的设备驱动程序都是用C代码编写的,但有些实时故障最好通过手动优化C编译器中途生成的汇编代码来解决。

高级语言——FORTRAN

FORTRAN 代表了公式翻译 (FORmula TRANslation)。这门语言是在上世纪50年代中期的IBM 704系列计算机上发明的。

高级语言——BASIC

在计算机编程中,BASIC (Beginner's All-purpose Symbolic Instruction Code) 是一个高级语言族。它最初于 1963年由Dartmouth College的John George Kemeny和Thomas Eugene Kurtz设计,使得非科学领域的学生接触到了计算机。当时所有的电脑使用需要编写自定义软件,这是只有科学家和数学家倾向于做的事情。二十世纪八十年代,它在家用微型计算机上变得普遍,现在在少数大幅演变的语言中仍然流行。

高级语言——COBOL

COBOL (COmmon Business Oriented Language) 是一个上世纪60年代出现的高级编程语言,并仍然用于业务应用。它广泛应用于金融服务行业使用的基于大型机的应用。它使用类似英语语句的指令,并为程序设定了一个整体框架。COBOL 的设计目标是一种自文档化的语言,可以方便地对其进行修改和维护。

高级语言——PL/1

Programming Language 1 是为科学、工程和业务应用程序设计的高级编程语言。它是最具特色的编程语言之一,也是最具功能丰富的一类中的第一个。它自上世纪60年代代初推出以来,已被各种学术、商业和工业用户使用,至今仍在积极使用。它支持递归和结构化编程。语言语法是类似于英语的,适合描述复杂的数据格式,有一组广泛的可用于验证和操作的函数。

汇编语言的优点

了解汇编语言使人知道——

  • 程序是如何与操作系统 (OS)、处理器和BIOS交互的;
  • 数据是如何在内存和其他外部设备中表示的;
  • 处理器是如何访问和执行指令的;
  • 指令是如何访问和处理数据的;
  • 程序是如何访问外部设备的。

使用汇编语言的其他优点是——

  • 它需要较少的内存和执行时间;
  • 它以更简单的方式允许特定于硬件的复杂工作;
  • 它适用于追求效率的工作;
  • 它最适合编写中断服务例程和其他内存驻留程序。

个人计算机硬件的基本特点

PC 的主要内部硬件由处理器、内存和寄存器组成。寄存器是保存数据和地址的处理器组件。在执行程序时,系统会将其从外部设备复制到内部内存中。处理器执行程序指令。

计算机存储的基本单元是位 (bit);它可以 ON (1),也可以是 OFF (0)。一组九个相关位组成一个字节,其中八位用于数据,最后一个用于奇偶校验。根据奇偶校验规则,每个是ON (1) 字节上的位数应该总是奇数。

因此,奇偶校验位的应用使由比特组成的字节数是奇数。如果奇偶校验是偶数,系统假定出现了奇偶校验错误 (尽管很少见),这可能是由于硬件故障或电气干扰造成的。

处理器支持以下数据大小——

  • 字(Word): 2 字节数据项
  • 双字(Doubleword): 4 字节(32位)数据项
  • 四字(Quadword): 8 字节(64位)数据项
  • 段落(Paragraph): 16 字节(128位)数据项
  • 千字节(Kilobyte): 1024 字节
  • 兆字节(Megabyte): 1,048,576 字节

在内存中寻址数据

处理器控制指令执行的过程被称为回迁—解码—执行 (fetch-decode-execute) 周期或执行周期 (execution cycle)。它包括三连续的步——

  • 从内存中获取指令
  • 解码或识别指令
  • 执行指令

处理器一次可以访问一个或多个字节的内存。让我们考虑一个十六进制数字0725H。此数字将需要两个字节的内存。高阶字节或最有效字节为 07,低阶字节为25。

处理器以反向字节序列存储数据,即低序字节存储在低内存地址和高内存地址中的高阶字节中。因此,如果处理器将值0725H从寄存器带到内存,它将首先将25传输到较低的内存地址,然后将07转换为下一个内存地址。

5baa391651bdd.png

x: 内存地址

当处理器将内存中获取数字数据送往寄存器时,它再次反转字节。有两种内存地址——

  • 绝对地址 (Absolute address) ——特定位置的直接引用。
  • 段地址 (或偏移量) (Segment address (or offset)) ——具有偏移值的内存段的起始地址。

基本语法

汇编程序可分为三部分——

  • 数据 (data) 部分,
  • bss (Block Started by Symbol) 部分,以及
  • 文本 (text) 部分。

数据 (data) 部分

数据 (data) 用于声明初始化的数据或常量。此数据在运行时不会更改。可以在本节中声明各种常量值、文件名或缓冲区大小等。

声明数据的语法是——

section.data

bss 部分

bss 用于声明变量。声明 bss 的语法是——

section.bss

文本 (text) 部分

文本 (text) 用于保留实际代码。本部分必须以声明 global _start 开始,它告诉内核程序执行的开始位置。

声明文本的语法为——

section.text
   global _start
_start:

注释

汇编语言注释以分号 (;) 开头。它可能包含任何可打印字符,包括空白。它可以出现在同一行,例如——

; 这个程序在屏幕上显示一条信息

或者,与指示在同一行,如——

add eax, ebx     ; 添加 ebx 到 eax

汇编语言语句

汇编语言程序包括三种类型的语句——

  • 可执行指令或指令,
  • 汇编指令 (assembler directives) 或伪指令 (pseudo-ops), 以及
  • 宏 (Macros)。

可执行指令或简称指令告诉处理器该做什么。每个指令由一个操作代码 (operation code) (opcode) 组成。每个可执行指令生成一台计算机语言指令。

汇编程序指令 (assembler directives) 或伪指令 (pseudo-ops) 告诉汇编程序关于汇编过程的各个方面。这些是不可执行的,不生成机器语言指令。

(Macros) 基本上是一种文本替换机制。

汇编语言语句的语法

汇编语言语句每行输入一个语句。每个语句遵循以下格式——

[标签(label)]   指令(mnemonic)   [操作数(operands)]   [;注释(comment)]

方括号中的字段是可选的。基本指令有两个部分,第一个是要执行的指令 (或助记键) 的名称,第二个是命令的操作数或参数。

以下是典型汇编语言语句的一些示例——

INC COUNT        ; 增加内存变量 COUNT

MOV TOTAL, 48    ; 将 48 传入内存变量 TOTAL
                      
ADD AH, BH       ; 将 BH 寄存器的内容添加到 AH 寄存器中
                      
AND MASK1, 128   ; 对变量 MASK1 和 128 执行 AND 操作
                      
ADD MARKS, 10    ; 将 10 添加到变量 MARKS 中

MOV AL, 10       ; 将值 10 转移到 AL 寄存器

内存分段 (Memory Segments)

分段内存模型将系统内存划分为位于段寄存器中的指针所引用的独立段组。每个段都用于包含特定类型的数据。一个段用于包含指令代码,另一个段存储数据元素,第三个段保留程序堆栈。

根据上述讨论,我们可以将各种内存段指定为——

  • 数据段 (Data segment) ——它由 .data.bss 表示。.data 部分用于声明内存区域,其中数据元素存储在该程序中。在声明数据元素后,此部分不能展开,并且在整个程序中保持静态。

    .bss 部分也是静态内存部分,其中包含要在程序中稍后声明的数据的缓冲区。此缓冲区内存为零填充。

  • 代码段 (Code segment) ——它由 .text 表示。这定义内存中存储指令代码的区域。这也是一个固定的区域。

  • 堆栈 (Stack) ——此段包含传递给程序中的函数和过程的数据值。

内存地址

在计算中,内存地址是对不同级别的软件和硬件所使用的特定内存位置的引用。内存地址是固定长度的数字序列,通常以无符号整数的形式显示和操作。这样的数字语义基于 CPU (如指令指针和增量地址寄存器) 的特性,以及内存的使用,如由各种编程语言支持的数组。

内存地址类型

物理地址

数字计算机的主内存由许多内存位置组成。每个内存位置都有一个物理地址(一个代码)。CPU (或其他设备) 可以使用代码访问相应的内存位置。通常只有系统软件,即 BIOS、操作系统和一些专门的实用程序 (如内存测试器),内存控制器使用机器代码操作数或处理器寄存器来寻址物理内存,指示 CPU 引导硬件设备,用内存总线或系统总线,或单独的控制地址和数据总线,以执行程序的命令。内存控制器总线由多个并行行组成,每个平行线由二进制数字 (位) 表示。因此,寻址存储单元的数量,以及每个单元中的比特数,在计算机之间会有所不同。

逻辑地址

计算机程序使用内存地址来执行机器代码,并存储和检索数据。在早期的计算机逻辑和物理地址对应,但自引入虚拟内存后,大多数应用程序对物理地址一无所知。而是使用计算机的内存管理单元和操作系统内存映射来处理逻辑地址或虚拟地址。

Virtual_address_space_and_physical_address_space_relationship_zh-CN

应用程序编程中的地址空间

在现代多任务环境中,应用程序进程通常在其地址空间中包含以下类型的内存块:

  • 机器代码,包括:
    • 程序本身的代码 (曾称为代码段 (code segment) 或文本段 (text segment));
    • 共享库 (shared libraries)。
  • 数据,包括:
    • 初始化数据 (数据段 (data segment));
    • 未初始化 (但已分配) 变量;
    • 运行时堆栈 (run-time stack);
    • 堆 (heap);
    • 共享内存和内存映射文件。

地址空间的某些部分可能根本没有映射。

本文大部分资料来自网络,本人对这些资料进行了总结,将课堂内容进行了扩充,有些方面翻译欠佳,敬请谅解。点击这里可以查看英文原版
附:在博客园中使用Markdown

转载于:https://www.cnblogs.com/jordangong/p/9707737.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值