首页 > 编程语言 >汇编语言简易教程(6):工具链以及调试器

汇编语言简易教程(6):工具链以及调试器

时间:2024-04-10 12:24:29浏览次数:30  
标签:文件 教程 汇编语言 汇编器 指令 example 调试器

汇编语言简易教程(6):工具链以及调试器

通常,用于创建程序的编程工具集称为工具链。

就本文而言,工具链包括以下内容

  1. 汇编器 Assembler
  2. 连接器 Linker
  3. 加载器 Loader
  4. 调试器 Debugger

虽然工具链有很多选项,但本文使用了一组相当标准的开源工具,这些工具可以很好地协同工作并完全支持 x86 64 位环境.

概览

从广义上讲,汇编、链接和加载过程是将程序员编写的源文件转换为可执行程序的过程.

汇编器将人类可读的源文件转换为目标文件。

在最基本的形式中,目标文件由链接器转换为可执行文件。

加载器会将可执行文件加载到内存中.

典型流程

image

Assembler(汇编器)

assembler 是一个程序,它将读取汇编语言输入文件并将代码转换为机器语言二进制文件。

输入文件是包含人类可读形式的汇编语言指令的汇编语言源文件。

机器语言输出称为object file​。

作为此过程的一部分,注释将被删除,变量名称和标签将被转换为适当的地址(根据 CPU 在执行期间的要求)

汇编器命令

yasm -g dwarf2 -f elf64 example.asm -l example.lst

  • -g dwarf2​:这是调试信息格式的选项。dwarf2​ 是一种调试信息格式,用于在生成的目标文件中包含调试信息,使调试器能够更好地理解程序的结构。dwarf​ 是目前最常见的调试格式之一,dwarf2​ 表示这种格式的一个版本。
  • -f elf64​:这个选项指定了目标文件的格式。elf64​ 表示生成的是64位环境下的 ELF (Executable and Linkable Format) 格式的目标文件。ELF 是一种常用的文件格式,用于定义程序、库或者其他一些二进制文件的结构。
  • example.asm​:这是输入文件的名称,即你要汇编的源代码文件。
  • -l example.lst​:这个选项告诉 yasm​ 需要生成一个列表文件(.lst​),其中包含源代码和对应的机器码。example.lst​ 是生成的列表文件的名称。

综上所述,整个命令的作用是:使用 yasm​ 汇编器,将 example.asm​ 文件中的源代码汇编成64位 ELF 格式的目标文件,并生成调试信息(使用 dwarf2​ 格式),同时输出一个包含汇编源代码和机器码的列表文件 example.lst​。这对于开发者调试汇编程序是非常有用的。

List文件

汇编器的一个可选项是创建List文件.

example.lst

List文件显示了指令的行号、相对地址、机器语言版本(包括变量引用)以及原始源代码.

List文件在Debug时非常有作用

data定义

36 00000009 40660301          dVar1    dd  17000000
37 0000000D 40548900          dVar2    dd  9000000
38 00000011 00000000          dResult  dd  0
  • 36​指代行号

  • 0x00000009​表示该数据存储的地址, 即指针位置, 因为dVar1是两字长度, 占用4个byte, 所以下一个变量 dVar2​的起始位置是0x0000000D

  • 0x40660301​表示这个变量的实际值, 16进制表示, 存储在内存中, 17000000的实际表示是0x01036640​但是因为内容中的存储是小端存储, 所以每两位颠倒.

    参考下图

    image

text示例

95                            last: 
96 0000005A 48C7C03C000000       mov     rax, SYS_exit
97 00000061 48C7C300000000       mov     rdi, EXIT_SUCCESS
98 00000068 0F05                 syscall
  • 96 行号
  • 0x0000005A​将放置代码行的相对地址。
  • 0x48C7C03C000000 ​是 CPU 读取和理解的指令的机器语言版本(十六进制)。该行的其余部分是原始的汇编语言源指令。
  • 标签last​:没有机器语言指令,因为该标签用于引用特定地址并且不是可执行指令

二阶段汇编

汇编器将读取源文件并将程序员输入的每个汇编语言指令转换为CPU知道是该指令的一组1和0。

1 和 0 被称为机器语言。汇编语言指令和二进制机器语言之间存在一一对应的关系。这种关系意味着可执行文件形式的机器语言可以转换回人类可读的汇编语言。

当然,注释、变量名称和标签名称都丢失了,因此生成的代码可能非常难以阅读。

当汇编器读取每一行汇编语言时,它会为该指令生成机器代码。这对于不执行跳转的指令非常有效。但是,对于可能更改控制流的指令(例如 IF 语句、无条件跳转),汇编器无法转换指令。

例如,给出以下代码片段

image

这被称为 forward reference (我不知道该如何翻译, 或许是前向引用​), 如果汇编器只读取一次, 此时其完全不知道skipRest​的位置甚至是否有定义skipRest

此问题可以通过两次读取汇编源码文件来解决.

第一次

在不同的汇编器上的表现可能不太一致, 但是可以概括为:

  1. 创建符号表
  2. 展开宏
  3. 计算常量表达式

展开宏

会在11章节细聊

计算常量表达式

常量表达式是完全由常量组成的表达式。由于表达式只是常量,因此可以在汇编时对其进行完全评估。例如,假设定义了常量 BUFF,则以下指令包含常量表达式:

mov	rax, BUFF+5

这种类型的常量表达式通常用在大型或复杂的程序中

地址被分配给程序中的所有语句。符号表是所有程序符号、变量名和程序标签及其在程序中各自地址的列表或表

第二次

在不同的汇编器上的表现可能不太一致, 但是可以概括为:

  1. 最终生成代码
  2. 创建List文件(如果需要)
  3. 创建Object文件

“代码生成”是指将程序提供的汇编语言指令转换为CPU可执行的机器语言指令.由于一对一的对应关系,这可以针对在第一遍或第二遍中不使用符号的指令来完成.

应该注意的是,根据汇编器设计,大部分代码生成可能在第一遍完成,或者全部在第二遍完成。无论哪种方式,最终生成都是在第二遍中执行的。这将需要使用符号表来检查程序符号并从表中获取适当的地址

列表文件虽然是可选的,但对于调试很有用。如果需要,它将在第二遍时生成.如果没有错误,则在第二遍时创建最终目标文件。

Linker(链接器)

定义

组合一个或多个object file成为一个可执行文件. 也可能会将用户或系统的lib包含起来.

使用

以GNU的ld作为参考

一个典型的ld命令: ld -g -o example example.o

  • -g​ 表示包含debug信息, 在最终的可执行文件中. 会增加可执行文件的大小, 但为了有效的调试是必要的

  • -o​ 指定可执行文件的名称, 如果文件名称被忽略, 那么会默认成a.out

    .
    ├── a.out // 未添加-o 的 默认的结果
    ├── eg // 添加 -o 指定的结果
    ├── eg.asm
    ├── eg.o
    └── example.lst
    

链接多个文件

ld -g -o example main.o funcs.o

需要在args中指定所有需要的 *.o

链接的过程

作为组合目标文件的一部分,链接器必须根据需要调整可重定位地址。

假设有两个源文件,主源文件和次源文件包含一些函数,这两个源文件都已被组装成目标文件main.o和funcs.o。

汇编每个文件时,将使用外部汇编器指令声明对正在汇编的文件外部的例程的调用。该代码不可用于外部引用,此类引用在目标文件中被标记为外部。

列表文件将针对此类可重定位地址标记为 R。链接器必须满足外部引用。此外,外部引用的最终位置必须放置在代码中。

示例

image

这里,函数 fnc1 位于 main.o 目标文件外部,并用 R 标记。

实际函数 fnc1 位于 funcs.o 文件中,该文件从 0x0(在文本部分中)开始其相对寻址,因为它不知道关于主要代码。

当目标文件合并时,fnc1 的原始相对地址(显示为 0x0100:)将更改为其在可执行文件中的最终地址(显示为 0x0400:)。

链接器必须将此最终地址插入到 main 中的调用语句中(显示为 call 0x0400:),以完成链接过程并确保函数调用正常工作。

代码和数据的所有可重定位地址都会发生这种情况。

请注意:

实际调用的main.o​并不知道func.o的内容, 实际是通过代码位置的地址调用的来实现. 所以linker的一个作用就是处理各个函数/变量的地址, 并准确的处理其调用.

动态链接

Linux 操作系统支持动态链接,它允许推迟某些符号的解析,直到程序正在执行为止

实际指令不会放置在可执行文件中,而是在需要时在运行时解析和访问:

  1. 常用的库(例如标准系统库)只能存储在一个位置,而不是在每个二进制文件中重复
  2. 如果库函数中的错误得到纠正,所有动态使用它的程序都将从纠正中受益(在下一次执行时)。否则,通过静态链接使用此功能的程序必须在应用更正之前重新链接

缺点:

  1. 不兼容的更新库将破坏依赖于先前版本库的行为的可执行文件
  2. 程序及其使用的库可以作为包进行认证(例如,正确性、文档要求或性能),但不能替换组件

在 Linux/Unix 中,动态链接的目标文件通常具有 .so(共享对象)扩展名。在 Windows 中,它是 .dll(动态链接库)扩展名。动态链接的更多细节超出了本文的范围.

Loader(加载器)

加载器是操作系统的一部分组件, 将程序从次级存储载入主存.

加载器将尝试查找,如果找到,则读取格式正确的可执行文件,创建一个新的进程. 并将代码加载到内存中并将程序标记为准备执行。操作系统调度程序将决定执行哪个进程以及何时执行该进程.

Debugger(调试器)

调试器通常用于控制程序的执行以执行测试或调试工作.

使用的调试器是 GNU DDD 调试器,它为 GNU 命令行调试器 gdb 提供可视化前端。

DDD 网站和文档在第 1 章简介的参考资料部分中注明。由于调试器的复杂性和重要性,为调试提供了单独的一章

使用

ddd ./eg

设置

image

断点

image

运行

image

点击**run**

单步调试

Next​命令将执行到下一条指令。

这包括在必要时执行整个函数。步骤命令将执行一步,如有必要,单步执行函数。

对于单个非功能指令,Next​命令和Step​命令之间没有区别

查看寄存器状态

Status→ Registers

image

默认只显示整数寄存器, 可以打开显示浮点数寄存器.

标签:文件,教程,汇编语言,汇编器,指令,example,调试器
From: https://www.cnblogs.com/pDJJq/p/18125760/simple-tutorial-of-assembly-language-6-tool-chain

相关文章

  • 汇编语言简易教程(4):基本语法
    汇编语言简易教程(4):基本语法以yasm语法为主注释​;​分号之后的所有内容全都是注释,没有实际作用.数值数值必须是10进制/16进制/八进制最终都会被转为16进制的数字,以0x​开头,例如127​->0x7f​当使用8进制的时候:511​->777q​默认基数(基数)为十进制,......
  • 汇编语言简易教程(5):环境构建
    汇编语言简易教程(5):环境构建最近在学习assembly64时,需要对程序进行编写->生成汇编代码->调试->执行.本文聚焦于如果在Windows环境下,尽可能精简并且完整的构建一个汇编环境.基于Windows11,WSLUbuntu22.04,vscode,其他的系统/WSL发行版本.您可以以本文作为......
  • 汇编语言简易教程(6):工具链以及调试器
    汇编语言简易教程(6):工具链以及调试器通常,用于创建程序的编程工具集称为工具链。就本文而言,工具链包括以下内容汇编器Assembler​连接器Linker​加载器Loader​调试器Debugger虽然工具链有很多选项,但本文使用了一组相当标准的开源工具,这些工具可以很好地协同工作并......
  • WebClient类 详细使用教程
    原文链接:https://blog.csdn.net/nutian/article/details/2913670   https://blog.csdn.net/m0_58015531/article/details/131322801WebClient类如果只想从特定的URI请求文件,则可以使用的最简单.NET基类就是System.Net.WebClient。这个类是非常高层的类,它主要用于执行带有一......
  • Python教程‘r’的使用技巧
    嗨,大家好!今天,我们将探讨Python中一个重要但经常被忽视的小技巧'r'。 在Python中,r是一个前缀,它用于处理原始字符串(rawstrings)。原始字符串与普通字符串不同,它们让你在字符串中使用反斜杠符号\而不必担心它们被解释成转义字符。为什么要使用原始字符串?原始字符串......
  • 博客园美化教程
    博客园美化教程前言之前一直想美化博客园,但一直没有找到比较喜欢的主题。最近找到了一个还比较满意的主题,SimpleMemory,特此分享。正文一、申请js权限首先点击这里--->博客后台-博客园(cnblogs.com),来到博客园后台管理页面,点击设置下滑,在基本设置里找到申请js权......
  • ArcGls10.8保姆式安装教程
    ArcGIS10.8保姆式安装教程ArcGIS是由美国Esri公司开发的一套地理信息系统软件,可进行地理信息数据的采集、管理、分析和发布等操作。ArcGIS10.8是ArcGIS系列的最新版本,具有更加强大的功能和更好的性能。本文将介绍ArcGIS10.8的保姆式安装教程,帮助您快速安装和配置ArcGIS10.......
  • 2024年幻兽帕鲁/Palworld服务器部署指南:从入门到精通的实战教程
    随着幻兽帕鲁(Palworld)这款游戏的持续升温,越来越多的玩家渴望能够拥有自己的专属服务器,与好友们畅享不受限的组队冒险。好消息是,现在搭建幻兽帕鲁服务器,比以往任何时候都要简单。今天,就让我带你走进这个神秘而富有创意的幻兽世界,手把手教你如何轻松搭建自己的游戏服务器。一、......
  • 幻兽帕鲁/Palworld服务器部署教程:从入门到精通的完整创建流程
    近期,备受瞩目的游戏《幻兽帕鲁》风潮再起,无数热爱冒险与探索的玩家们都渴望在这片神秘的土地上留下自己的足迹。然而,随着玩家数量的激增,官方服务器开始显现出其不稳定性,卡顿、掉线等问题时有发生。这时,拥有一台专属的《幻兽帕鲁》游戏服务器便成了许多玩家的新追求。好消息是,......
  • 百度网盘2024永久免费svip免费兑换码及使用教程
    很多新手用户在使用百度网盘时找不到自己下载后的文件在哪,其实百度网盘安装之后就会有默认的下载路径,其实只要跟着小编下面的教程一起操作,就能快速找到文件的下载路径。百度网盘下载的文件在哪?https://snsyun.baidu.com/sl/mg8TQEO​​​​​​​电脑端下载路径:1、打开百......