汇编程序设计与计算机体系结构软件工程师教程笔记:汇编语法基础知识

2023-11-20

《汇编程序设计与计算机体系结构: 软件工程师教程》这本书是由Brain R.Hall和Kevin J.Slonka著,由爱飞翔译。中文版是2019年出版的。个人感觉这本书真不错,书中介绍了三种汇编器GAS、NASM、MASM异同,全部示例代码都放在了GitHub上,包括x86和x86_64,并且给出了较多的网络参考资料链接。这里只摘记了NASM和MASM,测试代码仅支持Windows和Linux的x86_64。

3. 汇编语言及其语法的基础知识

3.2 基本元素:

汇编代码的五大支柱:保留字(reserved word)、标识符(identifier)、命令(directive, 也称为指示或伪操作)、区段(section或segment, 简称段)以及指令(instruction)。

(1). 保留字:是一种具备特定用途的字词。例如MOV就是个保留字,它代表一条特定的指令,即MOV指令。你不能把它当成变量名来用,也不能做其它用途。汇编语言的保留字不区分大小写。指令(例如MOV)、命令(例如PROC)、寄存器(例如eax)、属性(例如可以当作.MODEL命令参数值的FLAT)等,都是保留字。

(2). 标识符:是由程序员所定义的名称,用来表示变量、常量及过程等事物,它最多可以包含247个字符。第一个字符不能是数字,且必须从英文字母(大写的A至Z及小写的a至z)、下划线(_)、问号(?)、at符号(@)及美元符号($)这五种中选择,其后的字符则可以使用数字

(3). 命令:是与指令集无关的一些操作,可以指挥汇编器去做某件事,例如定义变量、指明内存段等。

下表列出了32位程序MASM版本特有的命令:用MASM编写64位程序的时候不需要使用此表中的命令。

(4). 程序段(program section或program segment):是用相关命令所标出的特殊段落。汇编器预先定义了几种这样的段落。下表列出了撰写汇编代码时常有的几种程序段:

(5). 指令:是程序中的可执行语句。指令由两个基本部分组成,其语法如下:”mnemonic  [operands]”,其中mnemonic(助记符)是指令的名称,开发者用它来指代某个架构所支持的一套指令集里的一条指令。助记符通常是个缩写形式或首字母缩略形式的词,实际上也可以认为是数字形式的操作码所对应的英语写法。有些指令不需要操作数,有些则需要一个、两个或三个操作数。

字面量(literal value, 字面值):也叫做立即值(immediate, 立即数),用来表示那些由开发者明确指定的值,例如整数、实数、字符、字符串等。

整数字面量(integer literal):一般写为十进制(或者说以10为底的进制)的整数。在有些情况下也可以(甚至是必须)采用其它进制来写。MASM及NASM允许开发者在字面量之后写上一个表示基数的字符,以指出这个字面量所采用的进制。如二进制b、十进制d、十六进制h、八进制o或q。有一种情况要注意,十六进制数的数位中可能会出现A至F这几种英文字符。如果某个十六进制数(例如内存地址)是以英文字符开头的,那么汇编器就会把它当成标识符看待,为了令其能够正确地将该值解读为字面量,你应该在前面添一个0.

字符字面量(character literal):是由单个字符所构成的值,与整数字面量一样,也用来表示那种开发者在编写程序代码的时候就已经很清楚的值。MASM与NASM中的字符字面量可以用一对单引号括起来,也可以用一对双引号括起来,这两种写法是等效的。字符在存储器中是以整数形式的ASCII编码来表示的。

字符串字面量(string literal):是由多个字符字面量所组成的,通常用来表示单词或短语。MASM与NASM的字符串与单个字符类似,也可以用一对单引号或双引号括起来。如果字符串的内容本身就有引号,那么对于MASM及NASM来说,你必须用另外一种引号把这个字符串括起来。字符串通常保存成字节数组,其中的每个字节都与字符串中处在该位置上的字符相对应,字节的内容就是字符的ASCII码。

标签(label):可以用来划分代码,以表达某种与编程或设计有关的想法。它不仅可以令代码读起来更加清晰,而且有的时候还能够帮助开发者实现跳转或循环等功能,使得程序可以跳到标签所标识的这个地方。标签的写法是在标识符后面跟一个冒号。标签可以单独占据一行也可以与指令写在同一行。NASM的标签用在.text段里    的标签区分大小写,MASM的标签写在.code段里则不区分大小写

汇编语言的注释可以分成两种:单行注释与多行注释。MASM及NASM的单行注释以分号(;)开头。注释可以单独占据一行也可以写在某行代码的后面。多行注释只能在MASM中用。MASM的多行注释必须与其它代码分别写在不同的行里,而且要由四部分组成:COMMENT、起始字符、注释文本、终止字符。起始字符与终止字符必须采用同一种字符,而且要注意不能与注释文本中的任何一个字符相同(否则注释就会提前结束)。MASM的多行注释习惯上采用感叹号(!)作为起、止字符。

3.3 定义数据:

汇编语言的数据类型根据数据的大小来确定(例如8位、16位、32位)。下表列出了各种汇编器所支持的数据类型:无论采用哪种汇编器,.data段里定义的变量都必须予以初始化,也就是必须具备初始值

变量采用下列语法来定义:

NASM:[标识符:] 命令 初始化器 [, 初始化器] …

MASM:[标识符] 命令 初始化器 [, 初始化器] …

一个标识符后面带有多个初始化器的写法可以用来创建数组(array),也就是创建一系列大小相同的值。这些值都可以通过数组的名称加以引用,该名称本身指的是序列中的第一个值(或序列中的第一个值在内存中的位置)。充当数组名称的标识符其实是指向数组中首个值的引用,它表示的是该值在内存中的位置。

有的时候,程序中需要定义未初始化的变量。这种变量不具备初始值,它主要是为了在内存中预留一定的空间以供开发者使用。对于这种变量,不同的汇编器所采用的定义方式之间有很大的区别。NASM要求.data段里的变量必须用明确的值来初始化,而MASM则允许开发者在该段中采用问号(?)充当变量的初始化器来定义未初始化的变量

MASM的初始化器可以用DUP括起来,以便反复创建大小与内容均相同的多个值。凡是有效的初始化器都可以用DUP命令加以重复,这也包括问号。

NASM要求未初始化的变量必须创建在.bss段中(bss的意思是Block Started by Symbol,以符号开始的块),而且要用特定的命令来创建,如下表所示:能够通过相应的命令,以单个变量或数组的形式来预留各种数据类型的未初始化空间。

字符串是以BYTE(字节)数组的方式存储的。字符串必须以null结尾,也就是说,其最后一个字节必须是值为0的ASCII码。不同的汇编器采用不同的方式来定义这种字符串。MASM与NASM则是直接用字面量0来设置最后一个字节。一个涉及字符串的重要问题是换行。不同的汇编器采用不同的方式换行。MASM用十六进制码0Dh与0Ah来表示CR/LF这两个符号并以此实现换行(CR的意思是carriage-return, 回车)。NASM则只用0Ah这一个十六进制码(也就是LF)表示换行

符号常量(symbolic constant)可以在MASM版本的汇编代码里取代某些变量,用以表示程序执行期间绝对不会变化的值。x86的符号常量能够表示32位整数,x86_64的符号常量能够表示64位整数,常量所表示的都是基于整数的数据。你可以用等号(=)定义这样的常量。MASM里的符号常量不占内存,因为MASM在对代码作汇编的时候,会把所有出现符号常量的地方都改成该常量所对应的实际值。采用等号来定义符号常量的写法只适用于MASM汇编器。此外,MASM的符号常量还可以用来表示字符串值。

所有的汇编器都可以把表达式的值表示成符号常量。符号必须用EQU命令来定义。与定义变量时的要求不同,用EQU所创建的符号既可以出现在数据段也可以出现在代码段(对于MASM汇编器,它可以出现在.data与.code段,对于NASM汇编器,它可以出现在SECTION .data与SECTION .text段)。这些汇编器在对代码作汇编的时候会把每一个出现这种符号的地方都替换成对应的表达式。建议只针对数值表达式来使用EQU命令。EQU命令还有一个用途,是通过创建符号常量来表示某个标识符所指代的数据占用了多大的内存空间。当前位置计数器(current location counter)用来指代位置计数器的当前内存地址(MASM及NASM用美元符号$表示),将该地址与前一个字符串的起始内存地址相减即可算出字符串所占据的字节数。MASM可以通过等号(=)把计算结果定义成标识符。

MASM还提供了一种写法,能够创建动态符号,称为文本宏(text macro)。由TEXTEQU命令所创建的符号可以表示涉及其它符号的表达式,甚至还可以表示指令。注意,由于指令不是整数表达式,因此它的左右两端是用尖括号括起来的。

Windows上使用VS编译MASM汇编操作步骤

(1). 创建一个Win32控制台应用程序AssemblyLanguage_Test;

(2). 右键单击该项目-->生成依赖项-->生成自定义:勾选masm复选框,点击确定;

(3). 添加一个新建文件funset.asm;

(4). 右击funset.asm-->属性:常规:项类型调整为:Microsoft Macro Assembler;

(5). 右键单击该项目-->属性:链接器:系统:子系统:调整为:窗口 (/SUBSYSTEM:WINDOWS);链接器:高级:入口点:填写为_main;

(6). 向funset.asm编写汇编代码,测试代码来自于:https://github.com/brianrhall/Assembly/blob/master/Chapter_3/Program%203.2/x86_64/Program_3.2_MASM.asm

可以在适当的位置设置断点,F5运行程序,打开寄存器、内存、反汇编、监视等窗口查看相关内容;可以在寄存器窗口中单击鼠标右键,选择”标志”查看标志寄存器的值,结果如下图所示:

Ubuntu上编译NASM汇编操作步骤

(1). 新建文件funset.asm,测试代码来自于:https://github.com/brianrhall/Assembly/blob/master/Chapter_3/Program%203.2/x86_64/Program_3.2_NASM.asm

(2). 脚本文件build.sh内容如下:

#! /bin/bash

nasm -f elf64 -o funset.o funset.asm
ld -e _main -melf_x86_64 -o funset funset.o
#./funset

可以通过gdb查看寄存器、变量等相关值,结果如下图所示:

GitHubhttps://github.com/fengbingchun/CUDA_Test

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

汇编程序设计与计算机体系结构软件工程师教程笔记:汇编语法基础知识 的相关文章

  • 当非特权用户运行 C/asm 程序时,会对 Linux 造成什么危害?

    我一直在考虑一种场景 让用户 可以是任何人 可能有恶意 提交在 Linux PC 我们称之为基准节点 上运行的代码 目标是为单线程例程创建一种自动化基准测试环境 假设一个网站向代理发布了一些代码 该代理将此代码交给基准节点 而基准节点仅与代
  • elf .rel.text 部分中 R_386_32/R_386_PC32 的含义

    为了理解重定位的概念 我编写了一个简单的 chk c 程序 如下所示 1 include
  • 左/右旋转进位的实际用途

    循环左进位和循环右进位指令有哪些实际用途 在我的汇编课上 我们无法想出一个有用的好例子 如果要将位从一个操作数移出并移入另一个操作数 SHL EAX 1 move sign bit of EAX RCL EDX into LSB of ED
  • ARM 调用约定是否允许函数不将 LR 存储到堆栈中?

    正如标题所示 我在理解 ARM 架构的调用约定时遇到问题 特别是 我仍然很难知道当你调用子程序时 LR 寄存器会发生什么 我认为 当您进入子程序时 处理 LR 寄存器的最明显 最安全的方法是将其存储到堆栈中 但该行为没有出现在文档中 因此我
  • DASM 汇编器中的 ASCII 到 C64 屏幕代码

    我正在通过 C64 模拟器学习 6502 micro 的汇编 目前正在尝试将字符串输出到屏幕 这是我的代码 processor 6502 org 1000 ldx 00 using x register as column counter
  • 编写 AMD64 SysV 程序集时使用哪些寄存器作为临时寄存器?

    我正在使用实现一个功能cpuid根据 AMD64 SysV ABI 进行组装 我需要在函数本身中使用 2 个临时寄存器 第一个用于累积返回值 第二个用作计数器 我的功能目前如下所示 zero argument function some c
  • x86-64 上这个语句有什么问题?

    该函数的目的是获取堆栈的起始地址 unsigned long find start void asm movq rsp eax 当我编译它时 出现错误 Error suffix or operands invalid for movq mo
  • 遍历内存编辑每个字节

    我正在编写汇编代码 提示用户输入一串小写字符 然后输出包含所有大写字符的相同字符串 我的想法是迭代从特定地址开始的字节 并从每个字节中减去 20H 将小写变为大写 直到到达具有特定值的字节 我对 Assembly 相当缺乏经验 所以我不确定
  • 即使我确实为变量设置了初始值,数据段也没有被初始化

    我已经编写了一个代码 该代码应该生成某种数字列表 但是即使我为它们分配了初始值 我的数据段变量也没有被初始化 This is how DS 0000 looks when I run it 这是我的代码 但数据段只保留垃圾值 MODEL s
  • 减法进位标志

    我正在使用 MASM32 有了这个代码 mov eax 5 sub eax 10 CF 状态标志将被设置 但使用我的铅笔和纸 我实际上看到 MSB 没有任何进位 是的 我知道从较少的数字中减去大的数字集CF 但我想知道为什么 因为使用这段代
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • 使用 Easy 68K (68000) 组装范围内的随机数

    我正在使用 Easy 68K 模拟器创建一个简单的黑杰克游戏 需要使用随机数来分配牌 我的牌必须在 2 到 11 的范围内 我似乎每次都得到相同的数字 但它不在我预期的范围内 我的卡值需要以 D3 结束 因此我有以下随机数代码 CLR L
  • 有没有办法使用 i387 fsqrt 指令获得正确的舍入?

    有没有办法使用 i387 fsqrt 指令获得正确的舍入 除了改变精确模式在 x87 控制字中 我知道这是可能的 但这不是一个合理的解决方案 因为它存在令人讨厌的重入型问题 如果 sqrt 操作中断 精度模式将出错 我正在处理的问题如下 x
  • 如何知道寄存器是否是“通用寄存器”?

    我试图了解寄存器必须具备什么标准才能被称为 通用寄存器 我相信通用寄存器是一个可以用于任何用途的寄存器 用于计算 将数据移入 移出等 并且是一个没有特殊用途的寄存器 现在我读到了ESP寄存器是通用寄存器 我猜是ESP寄存器可以用于任何事情
  • 弹出 x86 堆栈以访问函数 arg 时出现分段错误

    我正在尝试链接 x86 程序集和 C 我的C程序 extern int plus 10 int include
  • 使用 NEON 优化 Cortex-A8 颜色转换

    我目前正在执行颜色转换例程 以便从 YUY2 转换为 NV12 我有一个相当快的函数 但没有我预期的那么快 主要是由于缓存未命中 void convert hd uint8 t orig uint8 t result uint32 t wi
  • 为什么如果内存组织为字,则程序计数器加 1;如果内存组织为字节,则程序计数器加 2?

    如果在计算机中一条指令是 16 位 并且如果存储器被组织为 16 位字 则通过在当前指令的地址中加 1 来计算下一条指令的地址 如果内存是按字节组织的 可以单独寻址 那么我们需要在当前指令地址上加二 得到顺序执行的下一条指令的地址 为什么会
  • MikeOS 引导加载程序中的堆栈段

    我不明白这段代码 mov ax 07C0h Set up 4K of stack space above buffer add ax 544 8k buffer 512 paragraphs 32 paragraphs loader cli
  • X86 预取优化:“计算 goto”线程代码

    我有一个相当重要的问题 我的计算图有循环和多个 计算路径 我没有制作一个调度程序循环 其中每个顶点将被一一调用 而是将所有预先分配的 框架对象 放置在堆中 代码 数据 这有点类似于线程代码 甚至更好 CPS 只是在堆中跳转 执行代码 每个代
  • 如何在程序中将自己缝合到自己的尾部,无限循环地封装 64KB 代码段?

    如果指令的顺序执行经过偏移量 65535 则8086将从同一代码段中的偏移量 0 处获取下一个指令字节 接下来的 COM 程序利用这一事实 不断将其整个代码 总共 32 个字节 缝合到自己的尾部 环绕在 64KB 代码段中 你可以称之为二元

随机推荐

  • 系统架构设计师-计算机网络

    目录 一 计算机网络技术概述 1 网络概述 2 网络有关指标 3 网络分类 4 5G技术 二 组网技术 1 交换技术 2 基本交换原理 三 TCP IP协议簇 1 DHCP 2 DNS 四 网络规划与设计 一 计算机网络技术概述 1 网络概
  • Unity动画系统详解

    目录 动画编辑器 编辑器面板 动画复用 前言 人形重定向动画 Humanoid 通用动画 Generic 旧版本动画 Legacy 动画控制器 系统状态 切换条件 状态机脚本 IK动画 反向动力学 BlendTree 混合树 Animato
  • iis服务器网站加速,iis6配置gzip给网页减肥加快网页加载速度的方法

    gzip是一款网页压缩组件 开启了之后可以大大压缩网站文件 达到加快浏览速度的目的 尤其国外vps或者较大的网页 效果极为明显 linux vps或服务器 我们在配置环境的时候一般面板都集成安装了 会自动开启 但是还是有很多朋友喜欢用win
  • git 建立分支仓库

    Git 命令版本 查看本地分支及追踪 找一个文件夹目录 clone 仓库 Git branch vv 查看所有分支 Git branch a 查看本地分支 git branch 查看远程分支 git branch r 创建本地分支dev g
  • 对Unity3D 静态批处理和动态批处理的理解

    Draw Call就是CPU调用图像编程接口 像OpenGL或者 DirectX 简单来说 Draw Call就是由CPU发起的一个命令 添加到一个命令缓冲区 当GPU完成了上一次的渲染任务之后 会从命令缓冲区的命令队列中再取出一个并执行
  • hive有没有python api_python 访问hive

    pip install impyla 0 14 1pip install pure sasl 0 5 1pip install thriftpy 0 3 9pip install thrift sasl 0 2 1pip install t
  • 君正周生雷:MIPS架构授权促成本降至ARM 1/2

    转自 http laoyaoba com forums viewthread php tid 1525231 君正周生雷 MIPS架构授权促成本降至ARM 1 2 12月24日消息 腾讯科技日前走访了国内CPU企业君正集成电路有限公司 君正
  • vue3+uni——watch监听props中的数据(组件参数接收与传递defineProps、defineEmits)

    案例说明 A页面引用的子组件B A页面
  • 利用Git Diff比较Excel-推荐一款小工具

    PowerShell DiffExcel is an open source and text based tool to compare excel it supports Git diff 前言 ExcelBDD把Excel存储到Git
  • Spring Boot+thymeleaf 静态资源上下文的问题

    我在使用Spring Boot thymyleaf过程中修改server context path上下文属性后 页面的静态资源需要上下问来定位 那下面的js为例子 因为静态资源的访问地址是 localhost 8080 scripts ap
  • 看懂2020年智能浪潮,我们从百度和谷歌的AI足迹出发

    2020年已经过去 无论我们过得顺遂平安 还是过得无比艰难 我们应该都会记住这一年 回顾2020年 在这个不同寻常的疫情之年 科技成为人类抗击疫情的关键 而人工智能技术投入抗疫战争之中 可以说是人类有史以来的第一次 而与此同时 AI技术已经
  • [Note ]B站翼王10TB和100TB FreeNas硬件笔记以及配置

    BV18W411f7u9 DIY一台高性能的MINI ITX文件服务器 还要能使用万兆网络 BV1qE411672a 年轻人的第一台自己组装的100TB 容量的文件服务器 准备自己在家里搭Nas 家里人的手机存储也经常不够 自己也对硬件特别
  • SCSI、ISCSI、iSER、NVMe、NVMe-oF、NVMe-oF over RDMA

    在存储系统中 上层协议可以泛指 指令 也就是比如 读出从某某开始的多少长度的扇区 指令包含三大关键信息 1 操作码 Opreation Code 或称为OP code 比如write read等等 2 起始地址 从哪里开始读 如果是文件的话
  • 利用Redis实现分布式全局唯一ID

    Component public class RedisIdWorker 开始时间戳 private static final long BEGIN TIMESTAMP 1640995200L 序列号的位数 private static f
  • windows或者任何系统通过二进制安装最新的Protocol Buffer Compiler

    此处使用二进制法安装 适用于任何操作系统 安装预编译的二进制文件 任何操作系统 要从预编译的二进制文件安装最新版本的协议编译器 请按照以下说明操作 1 从 github com google protobuf releases 手动下载与您
  • 组合型模式

    概述 对于这个图片肯定会非常熟悉 上图我们可以看做是一个文件系统 对于这样的结构我们称之为树形结构 在树形结构中可以通过调用某个方法来遍历整个树 当我们找到某个叶子节点后 就可以对叶子节点进行相关的操作 可以将这颗树理解成一个大的容器 容器
  • Python 房价预测 kaggle 线性回归 SVM 神经网络 随机森林 集成模型

    摘要 现如今房产成为大多数家庭总资产中占比最大的一部分 也成为国人投资的重要渠道 研究和预测房产价格对我国人民和宏观经济发展都有重要价值 本文对包含房产各项基本信息及价格的数据进行处理 利用包括线性回归 核岭回归 支持向量回归 神经网络 决
  • C、C++ 中\n、\t、\r的具体用法功能

    简单介绍 n 表示换行操作 光标会移动到下一行 next line t 表示水平制表空行操作 相当于Tab键 不会换行 r 相当于回车 相当于光标回到本行首位置 不会换行 用法实例演示 我们以一个9x9乘法表C 具体代码为例 演示一个三个的
  • 使用七牛云进行文件上传

    目录 一 七牛云入门测试 1 注册七牛云账号 完成后选择对象存储 2 在里面创建空间 一个空间相当于一个文件夹 就是将对象上传到的地方 3 查看个人秘钥 注册完成账号后 会有一个秘钥 上传文件的时候进行授权和认证 4 文件上传测试 二 封装
  • 汇编程序设计与计算机体系结构软件工程师教程笔记:汇编语法基础知识

    汇编程序设计与计算机体系结构 软件工程师教程 这本书是由Brain R Hall和Kevin J Slonka著 由爱飞翔译 中文版是2019年出版的 个人感觉这本书真不错 书中介绍了三种汇编器GAS NASM MASM异同 全部示例代码都