[go]汇编语言

news2024/11/19 9:37:38

文章目录

    • 计算机结构
    • 常量与变量
      • 全局变量
      • 常量
      • 数组
      • 字符串
    • 函数
      • 参数与返回值
      • goroutine

Go汇编程序无法独立使用,必须以Go包的方式组织,同时包中至少要有一个Go语言文件用于指明当前包名等基本包信息。如果Go汇编代码中定义的变量和函数要被其它Go语言代码引用,还需要通过Go语言代码将汇编中定义的符号声明出来。

查看汇编代码:go tool compile -S asm.go

计算机结构

X86 CPU体系结构
x86-structure

左边为常见内存布局:

  • text一般为代码段(只读),存储要执行的指令数据;
  • rodata(只读)与data数据段,一般存放全局数据;
  • heap段用于动态管理数据;
  • stack段为栈数据(一般函数调用与局部变量);

中间为X86寄存器:

  • BP记录当前函数帧的开始位置(函数调用会隐式影响其值);
  • SP对应当前栈(顶)指针的位置;

Go汇编为了简化汇编代码的编写,引入了PC、FP、SP、SB四个伪寄存器(详见《go汇编ASM简介》)

amd-register

在AMD64环境:

  • 伪PC寄存器是IP指令计数器寄存器的别名;
  • 伪FP寄存器对应的是函数的帧指针,一般用来访问函数的参数和返回值;
  • 伪SP栈指针对应的是当前函数栈帧的底部(不包括参数和返回值部分),一般用于定位局部变量(真SP寄存器对应的是栈的顶部);
    • 使用SP时有一个临时标识符前缀(一般为局部变量名)就是伪SP:如a(SP)和b-8(SP)
    • 没有临时标识符前缀的是真SP寄存器:如(SP)和+8(SP)

常量与变量

Go汇编语言提供了DATA命令用于初始化包变量:

  • symbol为变量标识符;
  • offset为地址偏移;
  • width为内存宽度(大小)
  • value是初始化值(常量需以$开始,如$0xA1)
DATA symbol+offset(SB)/width, value

全局变量

全局变量是包一级的变量,全局变量一般有着较为固定的内存地址,声明周期跨越整个程序运行时间。

GLOBL symbol(SB), width

定义好的变量需要导出后,才可供其他代码引用(在汇编中定义变量,然后在go中使用):

// asm.go
package asm

var count int32  // 声明,会关联到.s中对应变量
var Name string

// asm_amd64.s  是amd64的汇编
#include "textflag.h"

GLOBL ·Id(SB),NOPTR,$4

DATA ·count+0(SB)/1,$1
DATA ·count+1(SB)/1,$2
DATA ·count+2(SB)/1,$3
DATA ·count+3(SB)/1,$4
// 或者(小端)
// DATA ·count+0(SB)/4,$0x04030201

GLOBL ·Name(SB),NOPTR,$24

DATA ·Name+0(SB)/8,$·Name+16(SB)
DATA ·Name+8(SB)/8,$6
DATA ·Name+16(SB)/8,$"gopher"

常量

Go汇编语言中常量以$美元符号为前缀。常量的类型有整数、浮点数、字符和字符串等几种类型。数值型常量,可通过表达式构造新的常量:

$1           // 十进制
$0x1234ABCD  // 十六进制
$1.5         // 浮点数
$'a'         // 字符
$"abcd"      // 字符串

$2+2      // == $4
$(3&1)<<2 // == $4

数组

Go语言中数组是一种扁平内存结构的基础类型:

var num [2]int

// asm
GLOBL ·num(SB),$16
DATA ·num+0(SB)/8,$0
DATA ·num+8(SB)/8,$0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mOFliZ1F-1670753220575)(pitures/2022-go-asm-array-2int.png)]

:切片与字符串类似,是一种带Header的结构

字符串

字符串(只读类型,要避免在汇编中直接修改字符串底层数据的内容)在go中是一个struct(包含数据地址与长度);amd64环境中StringHeader有16个字节大小,因此在汇编中定义一个16字节大小的变量(·helloworld):

// data of string
GLOBL text<>(SB),NOPTR,$16
DATA text<>+0(SB)/8,$"Hello Wo"
DATA text<>+8(SB)/8,$"rld!"

// header of string
GLOBL ·helloworld(SB),$16
DATA ·helloworld+0(SB)/8,$text<>(SB) // StringHeader.Data
DATA ·helloworld+8(SB)/8,$12         // StringHeader.Len

函数

函数标识符通过TEXT汇编指令定义,其后的指令一般对应函数的实现:
TEXT symbol(SB), [flags,] $framesize[-argsize]

各部分说明:

  • symbol:函数名(当前包的路径可以省略)后面是(SB),表示是函数名符号相对于SB伪寄存器的偏移量,二者组合在一起形成最终的绝对地址。
  • flags:标志(textlags.h文件中定义):
    • NOSPLIT:不生成或包含栈分裂(栈大小检测)代码(一般用于没有任何其它函数调用的叶子函数);
    • WRAPPER:表示这个是一个包装函数,在panic或runtime.caller等某些处理函数帧的地方不会增加函数帧计数;
    • NEEDCTXT:表示需要一个上下文参数,一般用于闭包函数;
  • framesize:表示函数的局部变量需要多少栈空间,包含调用其它函数时准备调用参数的隐式栈空间;
    asm-call

参数与返回值

Go汇编语言要求,任何通过FP伪寄存器访问的变量必和一个临时标识符前缀组合后才能有效,一般使用参数对应的变量名作为前缀。函数的第一个参数和第一个返回值会分别进行一次地址对齐。

call-frame

goroutine

Goroutine是Go中最基本的执行单元。goroutine就是一段代码加一个函数入口,以及在堆上为其分配的堆栈(初始4k,可随需要增长收缩);因此其非常廉价。

goroutine调用与普通函数类似:

  • 先设定参数;
  • 将函数地址(f)和参数大小(12)压栈;
  • 调用runtime.newproc
    • 新建一个栈空间,将参数复制到新栈;
    • 保存函数(f存放到strcut G的entry中);
    • 等待调度;
  • 恢复栈
  MOVL    $1, 0(SP)
  MOVL    $2, 4(SP)
  MOVL    $3, 8(SP)
  PUSHQ   $f(SB)
  PUSHQ   $12
  CALL    runtime.newproc(SB)
  POPQ    AX
  POPQ    AX

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

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

相关文章

Spark的架构与基本运行流程

Spark的架构与基本运行流程一、Spark中的核心概念二、Spark中的核心架构设计一、Spark中的核心概念 &#xff08;1&#xff09;RDD&#xff0c;Spark中最核心的概念就是RDD&#xff08;Resillient Distributed Dataset&#xff0c;弹性分布式数据集&#xff09;。换而言之&…

MySQL---事务及锁机制

MySQL之事务以及锁机制 文章目录MySQL之事务以及锁机制事务事务的操作1、开启事务&#xff1a;start Transaction2、提交事务&#xff1a;commit Transaction3、回滚事务&#xff1a;Rollback Transactionset命令事务的特性---ACID事务的隔离级别1.READ UNCOMMITTED 读未提交2.…

毒鸡汤 | PHPStudy搭建web项目

文章目录前言展示准备工作环境创建网站新建数据库PHP7现成版自己折腾版前言 折腾了很久&#xff0c;终于自己改成功了。问题不多&#xff0c;主要原因是自己没怎么开发过&#xff0c;不熟悉数据库连接原理&#xff0c;现在回头看真的改的很简单。问题主要是现在用的PHP7和旧版的…

I-03数据结构与算法(python版)

最近学习数据结构&#xff0c;对于从未接触过数据结构的我来说&#xff0c;老师不仅讲解理论&#xff0c;还有代码的逐层分析&#xff0c;非常不错&#xff0c;受益匪浅&#xff01;&#xff01;&#xff01;&#xff08;以下是学习记录&#xff09; 数据结构与算法&#xff0…

DEiT:通过注意力训练数据高效的图像transformer 蒸馏

摘要 最近&#xff0c;纯基于注意力的神经网络被证明可以解决图像理解任务&#xff0c;如图像分类。这些高性能的是使用大型基础设施预先训练数以亿计的图像&#xff0c;从而限制了它们的采用。 本文仅通过在Imagenet上训练&#xff0c;产生有竞争力的无卷积transformer。我们…

react原理-transition概念

在react18之中&#xff0c;引入了transition的概念。而且有一个新的api和两个新的hooks startTransitionuseTransitionuseDeferredValue 场景应用&#xff1a; 比如通过输入框输入内容更新列表内容&#xff0c;对于用户来说&#xff0c;输入框输入之后立马反馈的优先级是高过…

VS ChatGPT 中文版插件安装

1.打开Visual Studio Code 2.搜索chatGpt中文版 3.安装完后&#xff0c;重启一下软件 有国模式和国外模式&#xff0c;更多的教程请看插件作者的视频教程

分布式事物

Seata实践 XA模式 AT模式 TCC模式 性能 Saga模式 高可用------集群的形式 Seata实践解决方案 解决方式 Seata 引入服务协调者模式 实践步骤&#xff1a; 分布式事物的入口方法&#xff0c;会调用其他的微服务&#xff0c;每次调用的服务都是一个分支事物调用了多少个分支事…

SpringSecurity 认证实现

在之前一篇 博客 已经说明了 SpringSecurity 认证与授权的原理。这篇用来具体实现一下。 1、新建SecurityConfig 并创建认证管理器 Bean public AuthenticationManager authenticationManager() {... }2、新建认证提供者 Configuration public class SystemUserPasswordAuth…

Oracle项目管理之PrimaveraUnifier组织-业主/合作伙伴公司

目录 一、业主公司 二、合作伙伴公司 三、成员公司 Oracle Primavera Unifier 是企业项目协同管理系统&#xff0c;在国际化项目管理中&#xff0c;在进行常规的业务管理之外&#xff0c;对合同公司/EPC或分包供应商也有一定的管理要求&#xff0c;在Unifier中为了更好的实现…

sja1000 CAN驱动学习、调试记录(基于PeliCan Mode)

一、基础知识 网上讲sja1000 CAN总线控制器的资料很多&#xff0c;这里放一个引路贴&#xff1a;(151条消息) CAN总线控制器SJA1000_FATE的博客-CSDN博客_sja1000 BasicCAN Mode&#xff1a;仅支持11位的ID。 PeliCan Mode&#xff1a;在扩展模式下&#xff0c;允许使用 11 位 …

找出DataFrame中指定数据类型的列:select_dtypes()函数

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 找出DataFrame中指定数据类型的列 select_dtypes()函数 选择题 下列说法错误的是? import pandas as pd myDF pd.DataFrame({A:[1,2],B:[1.0,2.0],C:[a,b]}) print("【显示】myDF&qu…

leecode#同构字符串#反转链表

题目描述&#xff1a; 给定两个字符串 s 和 t &#xff0c;判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t &#xff0c;那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符&#xff0c;同时不改变字符的顺序。不同字符不能映射到同一…

ReentrantLock详解

JUC中的锁API 在juc中有一个Lock接口他的作用和synchronized相似都是为了保证线程安全性提供的解决方案 Lock中定义了一系列释放锁和抢占锁相关的API lock() 抢占锁资源 如果当前线程没有抢占到锁 则阻塞 tryLock() 尝试抢占锁资源 如果抢占成功则返回true 否则返回false unlo…

简单的深度活体智能记忆模型

🍿*★,*:.☆欢迎您/$:*.★* 🍿 正文

基于Antd Input组件自定义Input的成功状态

前言 Ant Design的Input组件的有一个状态的Api 需求 公司自研UI组件&#xff0c;在Antd的基础上进行开发。其中Input组件除了警告与错误状态外&#xff0c;还增加了成功的状态。如下图⬇️ 开发实现 方案一&#xff1a;覆盖CSS样式 一开始准备通过判断状态来增加类名&am…

软件工程习题

软件工程第一章 软件与软件工程作业第二章 可行性研究作业第三章 需求分析作业第四章 总体设计作业第五章 详细设计作业第六章 软件编码测验第七章 软件测试作业选择判断简答题第一章 软件与软件工程作业 一、单选题&#xff08;共7题&#xff0c;58.1分&#xff09; 1、软件是…

刷题13-左右两边子数组的和相等

题目012-左右两边子数组的和相等 思路&#xff1a;用到了三个循环&#xff0c;从头到尾遍历数组&#xff0c;比较左右两边数组的和是否相等&#xff0c;当然这种思路时间复杂度也比较高 核心代码&#xff1a; class Solution {public int pivotIndex(int[] nums) {int sum1,…

6.2 、MyBatis 高级映射(resultMap 标签多表联查 , 一对多,多对一关系)

文章目录一、实现多表联查&#xff08;association 标签&#xff09;1、实现多对一关系结果集映射二、实现多表联查&#xff08;collection 标签&#xff09;一、实现多表联查&#xff08;association 标签&#xff09; association 标签&#xff1a; 实现一对一&#xff0c;多…

因果推断1--基本方法介绍(个人笔记)

目录 一、因果推断介绍 1.1 什么是因果推断 1.2为什么研究因果推断 1.3因果推断阶梯 1.4因果推断问题分类 二、因果推断理论框架 2.1 定义&#xff08;这些定义后面会经常用到&#xff09; 2.2 Assumptions&#xff08;三大基本假设&#xff09; 三、因果效应估计 3.1 因果效应…