[go]汇编ASM简介

news2025/1/11 20:50:30

文章目录

    • 汇编(ASM)
      • 寄存器
      • 帧指针FP
    • 常见指令
      • 函数示例
    • 生成汇编

Go汇编代码主要用于优化和与底层系统交互,并不会像其它的经典汇编代码那样独立运行。

汇编(ASM)

Go ASM是一种被Go编译器使用的特殊形式的汇编语言(伪汇编),它基于Plan9输入风格;它是架构独立的,没有所谓的32或64位寄存器。

go汇编寄存器与x86_64对应关系:

AMD64  rax rbx rcx rdx rdi rsi rbp rsp r8 r9 r10 r11 r12 r13 r14 rip
Plan9  AX  BX  CX  DX  DI  SI  BP  SP  R8 R9 R10 R11 R12 R13 R14 PC

寄存器

Go ASM中有四个预定义的符号作为伪寄存器(虚拟寄存器,伪寄存器使用时一般需要一个标识符和偏移量为前缀):

  • FP: 帧指针,参数和局部变量;
  • PC: 程序计数器,跳转和分支;
  • SB: 静态基址指针,用来定义和读取文本区(代码区)、数据区的;
  • SP: 栈指针,栈的顶端;

伪寄存器SB可以看作是内存的起始地址。foo(SB)就是foo在内存中的地址,有两种修饰符<>和+N(整数)

  • foo<>(SB):表示一个私有元素,只有在同一个源文件中才可以访问;
  • +N:表示相对地址加上一个偏移量后得到的地址,如foo+8(SB)就指向foo之后8个字节处的地址;

帧指针FP

Go汇编使用的是caller-save模式,被调用函数的入参参数、返回值都由调用者维护、准备。因此,当需要调用一个函数时,需要先将这些工作准备好,才调用下一个函数,另外这些都需要进行内存对齐,对齐的大小是 sizeof(uintptr)。
在这里插入图片描述

伪寄存器FP是一个虚拟帧指针,被用来引用过程参数(由编译器负责维护):

  • 在64位机器上,0(FP)是第一个参数,8(FP)是第二个参数;
  • 为清晰和可读性的考虑,编译器会强制它们的命名使用:MOVL foo+0(FP),CX把第一个参数放入到物理上的CX寄存器;MOVL bar+8(FP),DX把第二个参数放入到DX寄存器中。

常见指令

栈调整(SP寄存器):

SUBQ    $24, SP  // 为函数分配函数栈帧
...
ADDQ    $24, SP  // 清除函数栈帧

加减操作:

ADDQ  AX, BX   // BX += AX
SUBQ  AX, BX   // BX -= AX

数据搬运:搬运的长度是由MOV的后缀决定

MOVB $1, DI      // 1 byte
MOVW $0x10, BX   // 2 bytes
MOVD $1, DX      // 4 bytes
MOVQ $-10, AX    // 8 bytes

// 加括号代表是指针的引用
MOVQ (AX), BX   // => BX = *AX 将AX指向的内存区域8byte赋值给BX
MOVQ 16(AX), BX // => BX = *(AX + 16)

//不加括号是值的引用
MOVQ AX, BX     // => BX = AX 将AX中存储的内容赋值给BX

跳转:

// 无条件跳转
JMP addr   // 跳转到地址,地址可为代码中的地址
JMP label  // 跳转到标签,可以跳转到同一函数内的标签位置
JMP 2(PC)  // 以当前指令为基础,向前/后跳转 x 行

// 有条件跳转
JLS addr

地址运算:

// 2代表 scale,scale只能是0、2、4、8
LEAQ (AX)(AX*2), CX // => CX = AX + (AX * 2) = AX * 3

函数示例

func neg(x uint64) int64为例,会生成类似如下的汇编代码:

TEXT ·neg(SB), NOSPLIT, $0-16
    MOVQ     x+0(FP), AX
    NEGQ     AX
    MOVQ     AX, ret+8(FP)
    RET

以中间点·作为名的分隔符;没有前缀的·foo等价于main·foo

  • TEXT: 标识位于text段;
  • ·neg: 函数名(包括包名);
  • (SB): 基址指针,代表函数地址;
  • NOSPLIT: 禁止stack拆分(即函数内部不需要判断栈空间是否足够,不会增长函数栈);编译器必须确保运行函数是安全的,即有足够的栈空间;
  • $0-16:其中0表示函数栈帧大小为0(即,没有局部变量);16表示参数及返回值的大小;

生成汇编

生成Go汇编:

  • go tool compile -S -N -l main.go直接输出汇编;
  • go build -gcflags="-N -l -S" main.go直接输出汇编;
    注意:加上对应的flag,避免某些逻辑被编译器优化掉,而看不到对应完整的汇编代码:
    • -l:禁止内联
    • -N:禁止优化
    • -S:输出汇编代码

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

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

相关文章

记录一次Powerjob踩的坑(Failed to deserialize message)

一. 问题描述: 在本地开发环境, server端和worker都运行正常. 但是发布到SIT环境(容器)的时候, 服务端却监测不到worker(worker可以找到服务端) 二. 问题表现: 1.服务端看不到Worker信息 2. 服务端日志信息 : Failed to deserialize message from [akka://oms111.111.111…

ECMAScript modules规范示例详解

引言 很多编程语言都有模块这一概念&#xff0c;JavaScript 也不例外&#xff0c;但在 ECMAScript 2015 规范发布之前&#xff0c;JavaScript 没有语言层面的模块语法。模块实际上是一种代码重用机制&#xff0c;要实现代码重用&#xff0c;将不同的功能划分到不同的文件中是必…

pycharm安装并加载编译器,设置背景图片,手把手详细操作

pycharm安装并加载编译器&#xff0c;设置背景图片&#xff0c;手把手详细操作 pycharm社区版&#xff08;免费&#xff09;下载官网 双击安装包&#xff0c;选择安装路径 勾选这两个&#xff0c;其实全不勾也没事 下一步默认就行&#xff0c;点install 安装完成后&#xf…

mimikatz抓取密码实战

必须下载最新版本 Releases gentilkiwi/mimikatz GitHubhttps://github.com/gentilkiwi/mimikatz/releases 有32和64之分&#xff0c;systeminfo查看自己版本 首先我们用后门得到权限&#xff0c;在用getsystem提权&#xff0c;因为mimikatz要system权限&#xff0c;getuid…

Python基础-1-环境搭建(初体验)

一&#xff1a;开发环境 Linux-5.15.0&#xff08;Ubuntu22.04&#xff09; 二&#xff1a;安装Python3 1、安装&#xff1a;sudo apt-get install python3 2、版本查询&#xff1a; python3 --version python3进入python解释器也可查询对应版本&#xff0c;按CtrlD或执行…

力扣(LeetCode)20. 有效的括号(C++)

栈模拟 一次遍历字符串 sss &#xff0c; 遇到左括号则入栈&#xff0c;遇到右括号则匹配栈顶。如果右括号匹配成功 &#xff0c; 栈顶元素弹栈 &#xff0c; 匹配不成功 &#xff0c; 则 returnfalsereturn\ \ falsereturn false 。 提示 : 当遍历完所有字符&#xff0c;记…

【计算机网络】扩展以太网方法总结

注&#xff1a;最后有面试挑战&#xff0c;看看自己掌握了吗 文章目录物理层扩展以太网链路层扩展以太网网桥网桥分类透明网桥源路由网桥多接口网桥----以太网交换机直通式交换机存储转发式交换机冲突域与广播域&#x1f343;博主昵称&#xff1a;一拳必胜客 &#x1f338;博主…

LinkedList详解

介绍 众所周知ArrayList底层数据结构是数组&#xff0c;但是数组有个缺点&#xff0c;虽然查询快&#xff0c;但是增删改会慢因为数组是在连续的位置上面储存对象的应用。当我们删除某一个元素的时候在他后面的元素的索引都会左移&#xff0c;导致开销会很大。所以LinkedList应…

Linux系统下交叉编译工具的安装实现

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何使用Linux系统下的交叉编译工具链的方法。 目录 第一:交叉编译工具链基本简介 ​第二&#xff1a;交叉编译工具安装方法 ​第三&#xff1a;安装相关库 ​第四&#xff1a;交叉编译工具验证 第一:交叉编译工具链基…

0100 蓝桥杯真题03

import java.util.Scanner; /* * 题目描述 * 如下图所示&#xff0c;3 x 3 的格子中填写了一些整数。 --*---- |10* 1|52| --****-- |20|30* 1| *******-- | 1| 2| 3| ------ *我们沿着图中的星号线剪开&#xf…

【Redis-04】Redis两种持久化方式(RDB和AOF)

Redis是基于内存的数据结构服务器&#xff0c;保存了大量的键值对数据&#xff0c;所以持久化到磁盘是非常必要的&#xff0c;Redis提供了两种持久化的方式&#xff0c;分别是RDB和AOF。下面我们看下这两种持久化方式的具体实现原理。 1.RDB持久化 首先&#xff0c;RDB持久化方…

Mysql基础

Mysql基础1. 数据库相关概念1.1 数据库1.2 数据库管理系统1.3 常见的数据库管理系统1.4 SQL2. Mysql的安装2.1 MySQL数据模型3. SQL概述3.1 SQL简介3.2 通用语法3.3 SQL分类4. DDL:操作数据库4.1 数据库的显示讲解4.2 查询4.3 创建数据库4.4 删除数据库4.5 使用数据库4.6 小结5…

linux Qt编译自己的动态库(.so),详细全流程

本篇记录Qt编译动态库全流程 1. 建立工程 首先&#xff0c;打开Qt&#xff0c;新建C Library 工程 点击choose之后&#xff0c;输入项目名称为Example&#xff0c;一直下一步即可 生成的项目里边有三个文件&#xff0c;分别是example.h, Example_global.h, example.cpp exam…

数据结构之:递归思想

&#xff08;一&#xff09;递归概念 将复杂问题 递推分解为最简问题 然后将结果回归的过程 Windows - Linux Linux Linux is not Unix 使用方法&#xff1a; 自己调用自己&#xff08;二&#xff09;斐波那契数列 兔子问题 有一对大兔子 每个月繁衍 一对小兔子&#xff08;一…

【Java 设计模式】UML 之类图

UML 之类图前言&#xff1a;什么是 UML &#xff1f;1 类图概念2 类的表示方式3 类与类之间关系的表示方式3.1 关联关系3.1.1 单向关联3.1.2 双向关联3.1.3 自关联3.2 聚合关系3.3 组合关系3.4 依赖关系3.5 继承关系3.6 实现关系前言&#xff1a;什么是 UML &#xff1f; 定义…

Linux 软件包下载加速工具:APT Proxy

本篇文章将继续介绍这个仅有 2MB 身材大小的 Linux 软件包缓存和加速工具&#xff1a;APT Proxy。 相比老牌的 apt cacher ng 而言&#xff0c;除了尺寸更小、内存占用更低&#xff08;10M以内&#xff09;、它还拥有无需配置&#xff0c;开箱即用等特点。 写在前面 年中的时…

!与~有什么区别

目录 将整型数据转换为二进制的函数 利用函数查看&#xff01;与~之后的数据有何不同 以一个非0数据作为例子 以0作为例子 我们都知道&#xff01;与~都是用于取反的。那么这两个有什么区别呢&#xff1f; 我们百度结果如下&#xff0c;很明显&#xff0c;八股文。我接下…

element-ui时间选择器(DatePicker )数据回显

系列文章目录 第一篇【element-ui】table表格底部合计自定义配置 目录 前言 一、element-ui时间选择器&#xff08;DatePicker &#xff09;是什么&#xff1f; DatePicker 日期选择器 二、返回数据格式 1.引入 总结 前言 需求&#xff1a;element-ui时间选择器&#…

【报错】QT Release NO CMAKE_CXX_COMPILER could be found

NO CMAKE_CXX_COMPILER could be found 错误&#xff1a; Tell CMake where to find the compiler by setting either the environmentvariable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path tothe compiler, or to the compiler name if it …

PostgreSQL数据库动态共享内存管理器——dynamic shared memory segment

首先看dynamic_shared_memory_type GUC参数&#xff0c;该参数用于指定dynamic shared memory implementation类型&#xff08;DSM_IMPL_POSIX、DSM_IMPL_SYSV、DSM_IMPL_WINDOWS、DSM_IMPL_MMAP&#xff0c;定义在src/include/storage/dsm_impl.h文件中&#xff09;。了解一下…