程序的机器级表示(一)汇编,汇编格式和数据传输指令

news2024/11/15 15:25:01

系列文章

: 深入理解计算机系统笔记

文章目录

  • 系列文章
  • 3 程序的机器级表示
    • 3.1 历史观点
    • 3.2 程序编码
      • 3.2.1 机器级代码
      • 3.2.2 代码示例
      • 3.2.3 关于格式的注解
    • 3.3 数据格式
    • 3.4 访问信息
      • 3.4.1 操作数指示符
      • 3.4.2 数据传送指令
      • 3.4.3 数据传送示例
      • 3.4.4 压入和弹出栈数据

3 程序的机器级表示

  • 计算机执行机器代码,编译器基于编程语言的规则、目标机器的指令集,操作系统遵循的惯例生成机器代码。
  • 汇编代码是机器代码的文本表示。高级代码可移植性较好,而汇编代码与特定机器密切相关
  • 现在不要求使用汇编语言编制程序,能够阅读和理解编译器转化的汇编语言的细节和方式,并分析代码中隐含的低效率。
  • 精通细节是理解更深和更基本概念的先决条件

3.1 历史观点

  • Intel处理器系列俗称x86,每个后续处理器都是向下兼容的(所以指令集中会有一些奇怪的东西),x86(64位)
  • 摩尔定律: 晶体管数目18个月翻一番。

3.2 程序编码

  • 使用较高级别优化的代码会严重变形(和源代码的格式),机器代码和初始源代码之间的关系难以理解。实际中,从程序性能考虑,较高级别的优化是较好的选择(O2用的比较多)。
  • 汇编器产生的目标代码是机器代码的一种形式,它包含二进制形式表示的所有指令,但还没有填入全局值的地址。链接之后才形成可执行代码,可执行代码是机器代码的第二种形式

3.2.1 机器级代码

  • 对机器级编程尤为重要的两种抽象
    1.指令集架构:定义了处理器状态、指令的格式、指令对状态的影响。
  1. 虚拟地址:机器级程序使用虚拟地址,即将内存看成一个按字节寻址的数组。
  • 一些通常对语言级隐藏的处理器状态(机器级可见)
  1. 程序计数器(PC):下一条执行指令的地址
  2. 整数寄存器文件:保存临时数据或重要的程序状态
  3. 条件码寄存器:最近执行的算术或逻辑指令的状态信息
  4. 一组向量寄存器:保存一个或多个整数或浮点数值
  • 机器代码和汇编代码中不区分有符号数和无符号数,不区分指针的不同类型,不区分指针和整数。
  • 因为虚拟内存的大小通常比较大,程序实际使用和访问的内存大小通常远小于虚拟内存看起来的大小。所以在任意的时刻,只有有限的虚拟内存是合法的,操作系统负责管理虚拟内存(通过表翻译为实际的物理地址)。
  • 一条机器指令只执行一个非常基本的操作。

3.2.2 代码示例

#include <stdio.h>

// 声明 multstore 函数
void multstore(long x, long y, long *dest);

// 声明 mult2 函数
long mult2(long a, long b);

int main() {
    long d;
    multstore(2, 3, &d);
    printf("2 * 3 --> %ld\n", d);
    return 0;
}

// 定义 multstore 函数
void multstore(long x, long y, long *dest) {
    *dest = mult2(x, y);
}

// 定义 mult2 函数
long mult2(long a, long b) {
    long s = a * b;
    return s;
}

gcc -S a.c -o multstore.s

 //部分汇编,不同优化等级和环境产生的不一样
 //这个和书上差别有亿点大
 63 mult2:
 64 .LFB2:
 65     .cfi_startproc
 66     pushq   %rbp
 67     .cfi_def_cfa_offset 16
 68     .cfi_offset 6, -16
 69     movq    %rsp, %rbp
 70     .cfi_def_cfa_register 6
 71     movq    %rdi, -24(%rbp)
 72     movq    %rsi, -32(%rbp)
 73     movq    -24(%rbp), %rax
 74     imulq   -32(%rbp), %rax
 75     movq    %rax, -8(%rbp)
 76     movq    -8(%rbp), %rax
 77     popq    %rbp
 78     .cfi_def_cfa 7, 8
 79     ret
 80     .cfi_endproc
  • -S选项产生汇编代码
  • 反汇编是根据机器代码反推出汇编的,逆向和一些安全漏洞分许就会用到这个
  • 机器代码与反汇编表示的特性:
  1. x86-64 的指令长度范围为 1~15 字节常用指令和操作数少的指令所需字节少。
  2. 指令格式设计方式为:可以将字节唯一的解码成机器指令。
  3. 反汇编器基于机器代码文件中的字节序列确定汇编代码,与源代码和编译时的汇编代码无关
  4. 指令结尾的 ‘q’ 是大小指示符,大多数情况下可以省略。
  • 从源程序转换来的可执行目标文件中,除了程序过程的代码,还包含启动和终止程序的代码,与操作系统交互的代码。

3.2.3 关于格式的注解

 81 .LFE2:
 82     .size   mult2, .-mult2
 83     .ident  "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
 84     .section    .note.GNU-stack,"",@progbits

像这样的汇编代码,以 ‘.’ (点) 开头的行是指导汇编器和链接器工作的伪指令。我们一般忽略它们。

  • 在汇编语言中,Intel 和 AT&T 是两种主要的语法格式它们在指令格式、操作数顺序、寄存器命名等方面有显著的区别。
  1. Intel 语法: 目的操作数在前,源操作数在后。
    AT&T 语法: 源操作数在前,目的操作数在后。
  2. 操作数大小
    Intel 语法: 操作数大小由操作码决定,不需要额外的后缀。
    AT&T 语法: 使用后缀来指明操作数大小(b 表示字节,w 表示字,l 表示双字,q 表示四字)。
  3. 寄存器命名
    Intel 语法: 寄存器名称直接使用。
    AT&T 语法: 寄存器名称前面加 % 符号。
  4. 立即数
    Intel 语法: 立即数不需要前缀。
    AT&T 语法: 立即数前面加 $ 符号
  • 还有一些符号上的小差距,总的来说两者操作数顺序恰好相反,
  • 我个人觉得Intel语法在许多方面更加简洁
  • 有些C语言访问不到的机器特性,我们可以考虑包含(asm伪指令)或者链接一部分汇编指令来优化程序

3.3 数据格式

在这里插入图片描述
汇编代码指令最后一个字符的后缀:movb, movw, movl, movq。
这里说的都是整数,浮点数使用一组完全不同的指令和寄存器,“l”既可以表示四字节整数,也可以表示8字节的双精度浮点数。

3.4 访问信息

在这里插入图片描述

  • 名称
  1. 起初的8086只有8个16位的寄存器:%ax到%bp (r是特殊的栈指针)
  2. 后面IA32架构扩展至32位,前缀一个e,也就是%eax到%ebx
  3. x86-64架构扩展至16个64位,自带一个r,大小由尾缀决定,编号也挺草率的,几个版本主打一个风格迥异
  • 低位操作的规则
  1. 将寄存器作为目标位置时,生成字节和字的指令会保持剩下的字节不变。(放字节,字(2字节)的时候就不改其他位的值了)
  2. 生成双字的指令会把高位四字节置为 0。(32位扩展的一部分内容
  • 16个寄存器的作用
    a:返回值
    s:栈指针
    d, s, d, c, 8, 9:第 1 到第 6 个参数
    b,bp, 12~15:被调用者保存
    10, 11:调用者保存

3.4.1 操作数指示符

  • 三种主要的操作数类型:
  1. 立即数 (Immediate),表示常数值
    考研好像是Intel格式
//Intel 语法示例
mov eax, 10   ; 将立即数 10 移动到寄存器 eax
add eax, 5    ; 将立即数 5 加到寄存器 eax
//AT&T 语法示例
movl $10, %eax   ; 将立即数 10 移动到寄存器 eax
addl $5, %eax    ; 将立即数 5 加到寄存器 eax
  1. 寄存器 (Register),使用寄存器中的全部位或者低位的内容
//Intel 语法示例
mov eax, ebx   ; 将寄存器 ebx 的值移动到寄存器 eax
add eax, ecx   ; 将寄存器 ecx 的值加到寄存器 eax
//AT&T 语法示例
movl %ebx, %eax   ; 将寄存器 ebx 的值移动到寄存器 eax
addl %ecx, %eax   ; 将寄存器 ecx 的值加到寄存器 eax
  1. 内存引用 (Memory Reference),寻址,可以是直接地址、间接地址或基于寄存器的地址计算。带了()或者[],和解引用指针很像
//Intel 语法示例
mov eax, [ebx]          ; 将内存地址 [ebx] 的值移动到寄存器 eax
mov [ecx + 4], edx      ; 将寄存器 edx 的值移动到内存地址 [ecx + 4]
add eax, [esi + edi*4]  ; 将内存地址 [esi + edi*4] 的值加到寄存器 eax
//AT&T 语法示例
movl (%ebx), %eax            ; 将内存地址 (%ebx) 的值移动到寄存器 eax
movl %edx, 4(%ecx)           ; 将寄存器 edx 的值移动到内存地址 4(%ecx)
addl (%esi, %edi, 4), %eax   ; 将内存地址 (%esi, %edi, 4) 的值加到寄存器 eax

在这里插入图片描述

  • 最后一种最常用也最重要(其他格式是它的一个特例)
  • Imm(rb, ri, s)
  • Imm(立即数偏移) + R[rb] (基址) + R[ri] (变址)s (比例因子)
  • s 只能是 1,2,4,8 中的一个

3.4.2 数据传送指令

  • 简单的四种mov指令
    movb, movw, movl,movq:传送字节、字、双字、四字
  • movabsq(move absolute quadword):传送绝对的四字。用于将一个 64 位的立即数传送到一个 64 位寄存器中。用于初始化寄存器或处理大数机器码九字节(1+8),较大。
  • mov的五种组合:
  1. 立即数到寄存器 (Immediate to Register)
    将一个立即数传送到一个寄存器中。
  2. 立即数到内存 (Immediate to Memory)
    将一个立即数传送到一个内存位置中。
  3. 寄存器到寄存器 (Register to Register)
    将一个寄存器的值传送到另一个寄存器中。
  4. 内存到寄存器 (Memory to Register)
    将一个内存位置的值传送到一个寄存器中。
  5. 寄存器到内存 (Register to Memory)
    将一个寄存器的值传送到一个内存位置中。
  • 示例
	; Intel 语法
    ; 立即数到寄存器
    mov eax, 10
    ; 立即数到内存
    mov [var1], 20
    ; 寄存器到寄存器
    mov ebx, eax
    ; 内存到寄存器
    mov ecx, [var1]
    ; 寄存器到内存
    mov [var2], ebx
	; AT&T 语法
	; 立即数到寄存器
    movl $10, %eax
    ; 立即数到内存
    movl $20, var1
    ; 寄存器到寄存器
    movl %eax, %ebx
    ; 内存到寄存器
    movl var1, %ecx
    ; 寄存器到内存
    movl %ebx, var2
  • 较小的源值复制到较大的目的地使用movz或者movs
    他们的后缀字符第一个指定源的大小,第二个指定目的大小
    movz,将剩余部分填充为0。
    movs,将剩余部分填充为符号位。
    在这里插入图片描述

3.4.3 数据传送示例

  • 3.4.2已经示范差不多了
  • 局部变量通常保存在寄存器中。
  • 函数返回指令 ret 返回的值为寄存器 rax 中的值
  • 强制类型转换可通过 mov 指令实现的。
  • 当指针存在寄存器中时,a = p 的汇编指令为: mov (rdi), rax

3.4.4 压入和弹出栈数据

  • 栈:向下增长(所以压栈时减[%rsp]),后进先出
  • push:压栈
  • pop:出栈
  • %rsp:(64位) 栈指针,栈顶元素的地址
  • 指令尾缀代表操作的大小(bwlq)
  • 其实压栈操作等价于先减栈指针值,再将指定寄存器的值写入栈,反之,出栈先读出栈顶数据到指定寄存器,在加栈指针的值。而push,pop只被编码为一个字节即可完成这两步需要8个字节指令大小的操作。
    在这里插入图片描述
  • 使用 mov 指令和标准的内存寻址方法可以访问栈内的任意位置,而非仅限于栈顶。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1950675.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何做校园圈子小程序,需要哪些功能?可打包APP小程序H5,源码交付,支持二开!

独立学校首页 支持每个学校独立首页!每个学校都可以拥有专属首页&#xff0c;打造不同风格的学校首页展示效果 多业务覆盖 可实现校园内外卖、跑腿、超市、药店水果、快餐店等业务全覆盖!所有配送业务平台都可开展 多站点运营 支持多学校多站点运营&#xff0c;各分站管理员可独…

【日记】办个护照不至于有这种刑事罪犯一样的待遇吧……(737 字)

正文 暴晒&#xff0c;中午出去骑共享单车&#xff0c;座垫都不敢坐。 至于为什么&#xff0c;中午觉都不睡跑出去&#xff0c;是因为今天他们办承兑汇票的业务&#xff0c;搞了一天&#xff0c;中午不休息&#xff0c;说可能还会用到我的指纹&#xff0c;让我 on call。我心想…

基础IO(文件系统)

一、块组的宏观理解 1、分区和分组 首先一台电脑就一个磁盘&#xff0c;一般800GB到1TB&#xff0c;为了管理这么大的内存数据&#xff0c;我们就对磁盘进行分区&#xff0c;分区之后才是我们看到的C盘&#xff0c;D盘等。 但是其实分区之后空间还是太大不好管理&#xff0c;…

习题2.23

不解释了&#xff0c;这么简单的题目。 (defn for-each[f item](if (not (empty? item));(println (f (first item)))(f (first item)))(if (not (empty? item))(for-each f (rest item)));(f (first item)))执行结果如下

FastGPT、Dify、Coze产品功能对比分析

在当前的人工智能领域&#xff0c;模型接入、应用发布、应用构建、知识库和工作流编排等功能是衡量一个AI平台综合能力的重要指标。本文将对FastGPT、Dify和Coze这三款产品的功能进行详细对比分析&#xff0c;以帮助用户更好地了解它。 订阅模式及市场概况 在订阅模式及市场概…

CSS常见属性详解——内边距与外边距

内边距与外边距 内边距 外边距 应用场景 在网页排版布局时&#xff0c;我们经常会希望元素与元素之间有一定的间距&#xff0c;此时我们可能会用到CSS的外边距或内边距属性&#xff0c;这两个属性都能让元素之间产生距离&#xff0c;那么他们之间有什么不同呢&#xff1f; …

【SpringBoot】1 Gitee

本项目 Gitee 地址&#xff1a;https://gitee.com/Lin_DH/system idea中可能装个gitee的插件&#xff0c;这样操作起来比较方便。 1&#xff09;登录 Gitee 官网&#xff08;https://gitee.com/&#xff09;&#xff0c;新建仓库。 2&#xff09;复制新建的 Gitee 仓库地址&am…

大麦抢票-狠货

大部分购买方式已迁移至手机端&#xff0c;专注研究移动端 小白操作–仅供学习 注意在帐号按权重的第三方账号设置解绑淘宝&#xff0c;否则有可能在抢票时候出现滑块&#xff0c;影响抢票,抢票优先选择大麦 ⚠️核心内容参考&#xff1a; 据悉&#xff0c;在购票环节&…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] LYA的朋友排队(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

深入分析 Android ContentProvider (五)

文章目录 深入分析 Android ContentProvider (五)ContentProvider 的性能优化和实践案例1. 性能优化技巧1.1. 数据库索引优化示例&#xff1a;添加索引 1.2. 批量操作与事务管理示例&#xff1a;批量插入操作 1.3. 使用异步操作示例&#xff1a;使用 AsyncTask 进行异步查询 1.…

FastAPI(七十八)实战开发《在线课程学习系统》接口开发-- 评论

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 梳理下思路 1.判断是否登录 2.课程是否存在 3.如果是回复&#xff0c;查看回复是否存在 4.是否有权限 5.发起评论 首先新增pydantic模型 class Cour…

如何为 DigitalOcean 上的托管数据库收集可观测指标

DigitalOcean 在 2024 年 5 月开始支持在托管数据库&#xff08;PostgreSQL、MySQL、Redis和Kafka&#xff09;中收集可观测指标。我们将在本偏内容中&#xff0c;告诉大家如何使用部署在 DigitalOcean App Platform 上的网络应用程序&#xff0c;为 DigitalOcean 上的 Postgre…

C语言 | Leetcode C语言题解之第283题移动零

题目&#xff1a; 题解&#xff1a; void swap(int *a, int *b) {int t *a;*a *b, *b t; }void moveZeroes(int *nums, int numsSize) {int left 0, right 0;while (right < numsSize) {if (nums[right]) {swap(nums left, nums right);left;}right;} }

新手必备:iPhone新机官网验机流程详解

目录 一、准备工作 二、外包装检查 三、序列号查询 四、开箱验机 五、开机验机 六、功能检测 七、售后服务验证 八、总结 一、准备工作 检查包裹&#xff1a;确保快递包裹完好无损。准备录像设备&#xff1a;使用另一台设备录制整个验机过程&#xff0c;以防日后发生纠…

C# 贪吃蛇游戏

贪吃蛇游戏可分为手动玩法和自动玩法 冯腾飞/贪吃蛇

海山数据库(He3DB)性能优化方案解析

前端优化是一个永恒的话题&#xff0c;每个前端开发者都希望自己的页面能够快速加载&#xff0c;给用户良好的体验。但往往事与愿违。因此&#xff0c;本文从编码优化、构建优化、部署优化三方面入手进行web页面性能优化。 1. 编码优化 1.1. Css优化 1.1.1. 合理使用css选择…

昇思25天学习打卡营第33天|共赴算力时代

文章目录 一、平台简介二、深度学习模型2.1 处理数据集2.2 模型训练2.3 加载模型 三、共赴算力时代 一、平台简介 昇思大模型平台&#xff0c;就像是AI学习者和开发者的超级基地&#xff0c;这里不仅提供丰富的项目、模型和大模型体验&#xff0c;还有一大堆经典数据集任你挑。…

QSqlQuery增删改查

本文记录使用QSqlQuery实现增删改查的过程。 目录 1. 构建表格数据 声明变量 表格、数据模型、选择模型三板斧设置 列表执行查询 列表的水平表头设置 2. 新增一行 构建一个空行 通过dialog返回的修改行数据&#xff0c;update更新 3. 更新一行 获取到需要更新的行 通…

qt--电子相册

一、项目要求 设计一个电子相册&#xff0c;点击上一张&#xff0c;切换到上一张图片&#xff0c;点击下一张&#xff0c;切换到下一张图片。 要求&#xff1a;图片的展示可以循环&#xff08;QList<QString>&#xff09; 要求&#xff1a;界面美观 二、项目代码 本质是通…

力扣141环形链表问题|快慢指针算法详细推理,判断链表是否有环|龟兔赛跑算法

做题链接 目录 前言&#xff1a; 一、算法推导&#xff1a; 1.假设有环并且一定会相遇&#xff0c;那么一定是在环内相遇&#xff0c;且是快指针追上慢指针。 2.有环就一定会相遇吗&#xff1f;快指针是每次跳两步&#xff0c;有没有可能把慢指针跳过去&#xff1f; 3.那一定…