X86汇编速成

平时用的电脑都是X86的,但是现在大家都在搞RISC-V,计组也都开始以RISC-V作为示例,所以专门回头来补一下X86的汇编,方便平时使用。

寄存器register

请添加图片描述
X86_64中一共有16个64位的通用寄存器,分别为:

  • RAX, RBX, RCX,RDX, RBP, RSI,RDI, RSP, R8–R15
    • RAX用来存储函数返回值,
    • RSP用来作为堆栈指针寄存器,RSP增大入站,减小出栈。
    • RBP,栈帧指针,标识当前栈帧的起始位置。
    • 其余的随便用
      Callee save表示当出现函数调用的时候,这些通用寄存器内的值由被调用者保存,即在进入被调用函数后由被调用函数存储到它的栈里面,并在返回前还原回去,与之对应的,Caller save则表示由调用者存储,在进入调用函数前就要自己提前push到自己的栈里面

32位的X86中只有8个通用寄存器,没有R8-R15

栈stack

请添加图片描述

指令

指令有两种形式,一种是AT&T的,一种是Intel的,我们用Intel风格的

opcode arg1,agr2

这是一段代码:

int add(int a, int b){return a+b;
}
int main(){int a = 1;int b = 2;int c = add(a,b);return c-a-b;
}

下面是使用gcc编译得到的汇编代码

.file   "test_asm.c".text.globl  add.type   add, @function
add:
.LFB0:.cfi_startprocendbr64pushq   %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq    %rsp, %rbp.cfi_def_cfa_register 6movl    %edi, -4(%rbp)movl    %esi, -8(%rbp)movl    -4(%rbp), %edxmovl    -8(%rbp), %eaxaddl    %edx, %eaxpopq    %rbp.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE0:.size   add, .-add.globl  main.type   main, @function
main:
.LFB1:.cfi_startprocendbr64pushq   %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq    %rsp, %rbp.cfi_def_cfa_register 6subq    $16, %rspmovl    $1, -12(%rbp)movl    $2, -8(%rbp)movl    -8(%rbp), %edxmovl    -12(%rbp), %eaxmovl    %edx, %esimovl    %eax, %edicall    addmovl    %eax, -4(%rbp)movl    -4(%rbp), %eaxsubl    -12(%rbp), %eaxsubl    -8(%rbp), %eaxleave.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE1:.size   main, .-main.ident  "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0".section        .note.GNU-stack,"",@progbits.section        .note.gnu.property,"a".align 8.long    1f - 0f.long    4f - 1f.long    5
0:.string  "GNU"
1:.align 8.long    0xc0000002.long    3f - 2f
2:.long    0x3
3:.align 8
4:

下面是在X86_64下使用objdump得到的反汇编指令代码

test_asm.o:     file format elf64-x86-64Disassembly of section .text:0000000000000000 <add>:0:   f3 0f 1e fa             endbr64               ; 引入指令序列断点,并启用64位模式4:   55                      push   %rbp           ; 保存调用者的栈帧指针到栈中,如上文提到的Callee save5:   48 89 e5                mov    %rsp,%rbp       ; 设置当前栈帧指针为栈顶指针8:   89 7d fc                mov    %edi,-0x4(%rbp) ; 将第一个参数存储到相对于栈帧指针偏移为-4的位置b:   89 75 f8                mov    %esi,-0x8(%rbp) ; 将第二个参数存储到相对于栈帧指针偏移为-8的位置e:   8b 55 fc                mov    -0x4(%rbp),%edx ; 将第一个参数加载到寄存器edx中11:   8b 45 f8                mov    -0x8(%rbp),%eax ; 将第二个参数加载到寄存器eax中14:   01 d0                   add    %edx,%eax       ; 执行加法操作,将edx和eax的值相加,结果存储在eax中16:   5d                      pop    %rbp            ; 恢复调用者的栈帧指针17:   c3                      retq                   ; 返回至调用者0000000000000018 <main>:18:   f3 0f 1e fa             endbr64               ; 引入指令序列断点,并启用64位模式1c:   55                      push   %rbp           ; 保存调用者的栈帧指针到栈中1d:   48 89 e5                mov    %rsp,%rbp       ; 设置当前栈帧指针为栈顶指针20:   48 83 ec 10             sub    $0x10,%rsp     ; 为局部变量分配16字节的栈空间24:   c7 45 f4 01 00 00 00    movl   $0x1,-0xc(%rbp) ; 将值1存储到相对于栈帧指针偏移为-12的位置2b:   c7 45 f8 02 00 00 00    movl   $0x2,-0x8(%rbp) ; 将值2存储到相对于栈帧指针偏移为-8的位置32:   8b 55 f8                mov    -0x8(%rbp),%edx ; 将第二个参数加载到寄存器edx中35:   8b 45 f4                mov    -0xc(%rbp),%eax ; 将第一个参数加载到寄存器eax中38:   89 d6                   mov    %edx,%esi       ; 将edx的值复制给esi寄存器,用作add函数的第二个参数3a:   89 c7                   mov    %eax,%edi       ; 将eax的值复制给edi寄存器,用作add函数的第一个参数3c:   e8 00 00 00 00          callq  41 <main+0x29>  ; 调用add函数41:   89 45 fc                mov    %eax,-0x4(%rbp) ; 将add函数返回值存储到相对于栈帧指针偏移为-4的位置44:   8b 45 fc                mov    -0x4(%rbp),%eax ; 将add函数返回值加载到寄存器eax中47:   2b 45 f4                sub    -0xc(%rbp),%eax ; 执行减法操作,将eax的值减去第一个参数的值4a:   2b 45 f8                sub    -0x8(%rbp),%eax ; 执行减法操作,将eax的值减去第二个参数的值4d:   c9                      leaveq                 ; 恢复栈帧并将栈顶指针设置为栈帧指针4e:   c3                      retq                   ; 返回至调用者

也确实是像大家说的,X86的手册太太太长了,X86为了向32位兼容,搞出来的很多机制令人头大

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

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

相关文章

【鸿蒙开发】if/else条件渲染,ForEach循环渲染

if/else 使用规则 支持if、else和else if语句。if、else if后跟随的条件语句可以使用状态变量。允许在容器组件内使用&#xff0c;通过条件渲染语句构建不同的子组件。条件渲染语句在涉及到组件的父子关系时是“透明”的&#xff0c;当父组件和子组件之间存在一个或多个if语句…

磁盘管理与文件管理

文章目录 一、磁盘结构二、MBR与磁盘分区分区的优势与缺点分区的方式文件系统分区工具挂载与解挂载 一、磁盘结构 1.硬盘结构 硬盘分类&#xff1a; 1.机械硬盘&#xff1a;靠磁头转动找数据 慢 便宜 2.固态硬盘&#xff1a;靠芯片去找数据 快 贵 硬盘的数据结构&#xff1a;…

golang实现定时监控 CLOSE_WAIT 连接的数量

文章目录 go实现定时检查大量的 CLOSE_WAIT 连接背景&#xff1a;为什么监控指定端口上的 CLOSE_WAIT 连接数量原因&#xff1a;什么是CLOSE_WAITgo实现定时检查大量的 CLOSE_WAIT 连接参考 go实现定时检查大量的 CLOSE_WAIT 连接 监控指定端口的连接状态&#xff0c;特别是关…

C++中的string设计成模板的原因

查看string的文档可以发现&#xff0c;string被设计成模板&#xff0c;为什么这样设计呢&#xff1f; string文档链接&#xff1a;<string> - C Reference (cplusplus.com) 随着计算机的发展&#xff0c;出现了很多编码&#xff08;用于管理字符&#xff09;&#xff0c…

K8S容器空间不足问题分析和解决

如上图&#xff0c;今天测试环境的K8S平台出现了一个问题&#xff0c;其中的一个容器报错&#xff1a;Free disk space below threshold. Available: 3223552 bytes (threshold: 10485760B)&#xff0c;意思服务器硬盘空间不够了。这个问题怎么产生的&#xff0c;又怎么解决的呢…

力扣LCR143---子结构判定(先序递归、Java、中等题)

题目描述&#xff1a; 给定两棵二叉树 tree1 和 tree2&#xff0c;判断 tree2 是否以 tree1 的某个节点为根的子树具有 相同的结构和节点值 。 注意&#xff0c;空树 不会是以 tree1 的某个节点为根的子树具有 相同的结构和节点值 。 示例 1&#xff1a; 输入&#xff1a;tree…

抖店商家必看:“违规操作”扣除保证金2000块!这些细节要避免!

哈喽~我是电商月月 很多没经验的新手朋友开抖店都会遇到一个问题&#xff1a; 那就是开抖音小店时&#xff0c;因操作不当被扣除保证金的该怎么办&#xff1f; 实话实说&#xff0c;被判违规扣除保证金是能申诉的。但通过几率几乎是没有的 所以想要继续开店&#xff0c;只能…

eclipse .project

.project <?xml version"1.0" encoding"UTF-8"?> <projectDescription> <name>scrm-web</name> <comment></comment> <projects> </projects> <buildSpec> <buil…

HarmonyOS 开发-短视频切换实现案例

介绍 短视频切换在应用开发中是一种常见场景&#xff0c;上下滑动可以切换视频&#xff0c;十分方便。本模块基于Swiper组件和Video组件实现短视频切换功能。 效果图预览 使用说明 上下滑动可以切换视频。点击屏幕暂停视频&#xff0c;再次点击继续播放。 实现思路 使用Sw…

Linux锁的使用

一、临界资源与临界区 多线程会共享例如全局变量等资源&#xff0c;我们把会被多个执行流访问的资源称为临界资源&#xff0c;我们是通过代码访问临界资源的&#xff0c;而我们访问临界资源的那部分代码称为临界区。 实现一个抢票系统 只有一个线程抢票时 #include <ios…

Docker速成:新手变专家!

Docker介绍 容器历史 1、Chroot Jail 就是常见的chroot命令的用法。它在1979年的时候就出现了&#xff0c;被认为是最早的容器化技术之一。它可以把一个进程的文件系统隔离起来。 2、The FreeBSD Jail &#xff08;监狱&#xff09;实现了操作系统级别的虚拟化&#xff0c;他…

外包干了25天,技术退步明显.......

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入杭州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…

Jeesite开源项目中ECharts折线图MarkPoint无法绘制问题的解决方案

Jeesite开源项目中ECharts折线图MarkPoint无法绘制问题的解决方案 在Jeesite开源项目的开发中&#xff0c;数据可视化是一个不可或缺的环节。ECharts作为一个功能强大的数据可视化库&#xff0c;在项目中经常被用来绘制各种图表。然而&#xff0c;在绘制折线图时&#xff0c;有…

【python】python的选择语句的三个题目

1.乘坐飞机时&#xff0c;有些航班没有行李额度&#xff0c;当乘客的行李小于等于20公斤时&#xff0c;按每公斤1.68元收费&#xff1b;大于20公斤时&#xff0c;按每公斤1.98元收费&#xff0c;编写程序计算收费情况&#xff08;保留两位小数&#xff09; air_bagfloat(input…

swiftUI macOS使用webview加载外部网址

import SwiftUI import WebKitstruct ContentView: View {var body: some View {VStack {Text("测试")WebView(urlString: "https://aweb123.com").frame(maxWidth: .infinity, maxHeight: .infinity) // 让 WebView 占据整个可用空间}.frame(minWidth: 20…

欧拉回路算法

1 基本概念 1.1 欧拉路径和欧拉回路 欧拉回路&#xff1a; 在一个图中&#xff0c;由i点出发&#xff0c;将每个边遍历一次最终回到出发点i的一条路径。具有欧拉回路的图称为欧拉图。 无向图 存在欧拉回路的充要条件是所有的点的度数均为偶数 因为每个点的度数为偶数&#xf…

OpenHarmony实战:轻量系统STM32F407芯片移植案例

介绍基于STM32F407IGT6芯片在拓维信息Niobe407开发板上移植OpenHarmony LiteOS-M轻量系统&#xff0c;提供交通、工业领域开发板解决方案。 移植架构采用Board与SoC分离方案&#xff0c;使用arm gcc工具链Newlib C库&#xff0c;实现了lwip、littlefs、hdf等子系统及组件的适配…

Todesstern:一款针对注入漏洞识别的强大变异器引擎

关于Todesstern Todesstern是一款功能强大的变异器引擎&#xff0c;该工具基于纯Python开发&#xff0c;该工具旨在辅助广大研究人员发现和识别未知类型的注入漏洞。 Todesstern翻译过来的意思是Death Star&#xff0c;即死亡之星&#xff0c;该工具是一个变异器引擎&#xff…

【剪映专业版】03云空间扩容

视频课程&#xff1a;B站有知公开课【剪映电脑版教程】 个人云空间&#xff1a;多端同步及素材、草稿保存 云空间默认为512M&#xff0c;可以免费提升至3GB 访问剪映官网-全能易用的桌面端剪辑软件-轻而易剪 上演大幕&#xff0c;后进入工作台 点击消息 小组云空间&#xff…