惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园_首页
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
ThreatConnect
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 聂微东
H
Help Net Security
T
Threat Research - Cisco Blogs
Blog — PlanetScale
Blog — PlanetScale
A
Arctic Wolf
G
Google Developers Blog
量子位
U
Unit 42
I
InfoQ
V
V2EX
F
Fox-IT International blog
P
Privacy & Cybersecurity Law Blog
V
Visual Studio Blog
J
Java Code Geeks
大猫的无限游戏
大猫的无限游戏
C
CERT Recently Published Vulnerability Notes
博客园 - 三生石上(FineUI控件)
T
The Exploit Database - CXSecurity.com
T
Tailwind CSS Blog
SecWiki News
SecWiki News
Know Your Adversary
Know Your Adversary
MyScale Blog
MyScale Blog
宝玉的分享
宝玉的分享
The Hacker News
The Hacker News
Project Zero
Project Zero
Application and Cybersecurity Blog
Application and Cybersecurity Blog
月光博客
月光博客
Recent Commits to openclaw:main
Recent Commits to openclaw:main
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
GRAHAM CLULEY
C
Cisco Blogs
I
Intezer
Simon Willison's Weblog
Simon Willison's Weblog
O
OpenAI News
Recorded Future
Recorded Future
T
Tenable Blog
W
WeLiveSecurity
腾讯CDC
Stack Overflow Blog
Stack Overflow Blog
T
The Blog of Author Tim Ferriss
www.infosecurity-magazine.com
www.infosecurity-magazine.com
D
Docker
C
Cybersecurity and Infrastructure Security Agency CISA
PCI Perspectives
PCI Perspectives

文章列表

我是如何解决将 c++ 编译成可以在 node.js 中使用的 *.node,中间出现的一大堆问题的(指纹浏览器基石篇) eSIM Plus 爱沙尼亚手机号彻底翻车?“永久有效”悄然变成了一年! 接码平台 SMS-Activate 余额可以转移到新平台使用,截止日期:2026年1月29日 是时候将 hugo-theme-kiwi 主题提交到 themes.gohugo.io 站点上了 Flux2 刚开源就凉了?Z-Image 本地部署狠狠打了个样 声音的未来:Chatterbox —— 用「夸张度旋钮」提升表现力的开源 TTS 向导 还以为那只是换个背景?Qwen-Image-Edit 在 ComfyUI 中能做到更离谱的事 Windows 结合最新版 ComfyUI 部署阿里最新开源的 Qwen-Image 图像大模型 从零样本到跨场景:Seed-VC语音转换技术的革命性突破 大语音模型轻量化革命:MegaTTS3 如何重新定义文本生成语音的技术边界(windows篇) 竞赛级编程大模型OlympicCoder-7B之本地部署(Windows篇) 阿里开源了端到端全模态大模型Qwen-2.5-Omini-7B之本地部署(windows篇) 语音识别之whisper本地部署(实时语音之开篇) 甭管是个人还是企业都能部署的Mistral-Small3.1,远超同级别的模型 文生音乐开源项目DiffRhythm,8G显存本地部署之Windows篇 阿里QwQ-32B本地部署指南:用Ollama轻松运行320亿参数大模型 基于Qwen2.5大模型的Spark-TTS,零样本语音克隆,CPU可运行之本地部署(Windows篇) 智谱开源了文生图CogView4-6B模型,支持中文提示词之本地部署(Windows篇) 基于歌词生成整首歌的开源AI音乐模型,支持中、英、日、韩等多种语言,本地化部署YuE(windows篇) 阿里云开源的文生视频万相 Wan2.1之本地部署Wan2.1-T2V-1.3B模型 互动式开源AI图像编辑神器,Windows11本地部署 MagicQuill 本地部署Qwen2.5-VL-7B-Instruct多模态视觉大模型(Windows篇) 保持角色一致性的绘本生成AI开源项目之Story-Adapter本地部署Windows篇 本地部署 Stable Diffusion 3.5(最新 ComfyUI记录篇) 谁说Win7安装不了Node.js最新版的呢?都2025年,还不更新系统到Win11 vs code远程调试Linux服务器上的php代码 浏览器定制 | Windows11 编译 Chromium 133.0.6885.0(截稿前Chromium最新版之编译篇[一]) 不说是彻底搞懂,至少让你不再惧怕c/c++指针,以及各种奇葩指针变种 解决windows下php8.x及以上版本,在Apache2.4中无法加载CURL扩展的问题 在 Windows8.1 下编译 Chromium (103.0.5060.68 之三) 安装 depot_tools 和 Windows 10 SDK 为在Windows下构建基于 chromium 的浏览器(103.0.5060.68 之二) Windows构建基于 Chromium 的浏览器之环境准备篇安装 Visual Studio(103.0.5060.68 之一) 为什么网站加载速度总是那么不尽如人意呢?(网站优化篇) 海外云服务器安装 Redis 6.2.x (Ubuntu 18.04 记录篇三) 海外云服务器安装 MariaDB 10.6.X (Ubuntu 18.04 记录篇二) 海外云服务器安装 JDK8 (Ubuntu 18.04 记录篇) 虚拟机 Linux 安装 JDK(Vagrant 之二 CentOS7 篇) 怎样快速搭建 Linux 虚拟机呢?(vagrant 篇) 个人站点迁移之gitlab.com pages 绑定自定义域名 不要你掏腰包,就能搭建个人网站之 gitlab.com Pages 托管服务 国内 gitee.com Pages 下线了,致使众多站长纷纷改用其他托管平台 canvas绘制文本时,该如何处理首行缩进、自动换行、多内容以省略号结束、竖排的呢? 其实,低成本甚至免费的,也是可以搭建个人网站的哦! 腾讯云COS托管静态网站,以及如何解决访问出现了下载网页的情况 错误分析 (Machine Learning 研习十九) 多类别分类器(Machine Learning 研习十八) 使用CSS计数器,在目录名称前加上了序号,让目录看起来更加井然有序 使用 golang 以及 Gin 框架,将上传的图片在不保存至本地的情况下添加水印,并上传至阿里云 OSS 绘制特征曲线-ROC(Machine Learning 研习十七) 网站引入 Prism,使得代码高亮显示,并一键复制代码块 精确率(召回率)的权衡(Machine Learning 研习十六) 对模型性能进行评估(Machine Learning 研习十五) 图像识别之入门案例之数字识别(Machine Learning 研习十四) 微调模型——续(Machine Learning 研习之十三) 微调模型(Machine Learning 研习之十二) 解决 github.com port 443: Timed out 的问题 选择和训练模型(Machine Learning 研习之十一) 回望这风雨飘摇的一年过后,我们终将要整束行囊继续前行 一套由 Hugo 驱动的博客主题 hugo-theme-kiwi 开源啦 机器学习中的 Transformation Pipelines(Machine Learning 研习之十) 特征缩放和转换以及自定义Transformers(Machine Learning 研习之九) 为机器学习算法准备数据(Machine Learning 研习之八) 端到端的机器学习项目之探索数据(Machine Learning 研习之七) 端到端的机器学习项目(Machine Learning 研习之六) 机机器学习的测试和验证(Machine Learning 研习之五) 机器学习的主要挑战和任务(Machine Learning 研习之四) 对于大量数据集的解决方案便是在线学习或是增量学习(Machine Learning 研习之三) 现实生活中机器学习的具体示例(Machine Learning 研习之二) 让机器学习不再是过门不入,带您一起详解机器学习(机器学习 Machine Learning 研习之一) 把握住golang中的template,方能驾驭得了Hugo主题的template 云服务器到期,站点迁移,Nginx配置SSL以备后续只需! 玩以太坊链上项目的必备技能(库 [library]-Solidity之旅十七) 玩以太坊链上项目的必备技能(Constant 和 Immutable 状态变量-Solidity之旅十六) 玩以太坊链上项目的必备技能(修改器 [modifier]-Solidity之旅十五) 玩以太坊链上项目的必备技能(错误处理以及异常-Solidity之旅十四) 玩以太坊链上项目的必备技能(函数及其可见性和状态可变性-Solidity之旅十三) 玩以太坊链上项目的必备技能(事件-Solidity之旅十二) 玩以太坊链上项目的必备技能(OOP-接口-Solidity之旅十一) 玩以太坊链上项目的必备技能(OOP-抽象合约-Solidity之旅十) 玩以太坊链上项目的必备技能(OOP-合约继承-Solidity之旅九) 玩以太坊链上项目的必备技能(流程控制-Solidity之旅八) 玩以太坊链上项目的必备技能(单位以及全局变量-Solidity之旅七) 玩以太坊链上项目的必备技能(基本类型转换以及推断-Solidity之旅六) 玩以太坊链上项目的必备技能(变量作用域-Solidity之旅五) 玩以太坊链上项目的必备技能(类型-映射类型-Solidity之旅四) 玩以太坊链上项目的必备技能(类型-引用类型-Solidity之旅三) 花了不到1块5,玩了下全网最火的ChatGPT 玩以太坊链上项目的必备技能(类型-值类型-Solidity之旅二) 玩以太坊链上项目的必备技能(初识智能合约语言-Solidity之旅一) 在构建 Web3 前,需先知道什么是区块链,毕竟 Web3 是基于区块链 Web3 来了,让我们展开双手拥抱它吧! Go 语言中的 Moduels 管理(Let's Go 三十四) Go 语言中的包(Let's Go 三十三) Go 语言中的错误处理(Let's Go 三十二) Go 语言中的带有缓冲 Channel(Let's Go 三十一) Go 语言中的单向 Channel(Let's Go 三十) Go 语言中的 Channel(Let's Go 二十九) Go 语言中的并发编程(Let's Go 二十八) Go 语言中的空接口(Let's Go 二十七) Go 语言中的类型断言(Let's Go 二十六)
玩以太坊链上项目的必备技能(内联汇编 [inline assembly]-Solidity之旅十八)
2022-12-28 · via

在 Solidity 中使用 Assembly 的主要好处之一是节省 gas。 让我们尝试通过创建一个将 2 个值 x 和 y 相加并返回结果的函数来比较 Solidity 和 Assembly 之间的 gas 成本。

概要

大抵是讲到汇编,身为编程开发者的我们脑瓜子早就嗡嗡作响了。看那晦涩难懂的低级汇编代码,敢断言,那一行不是我写的,其他行也不是我写的。

自从C语言问世,而后类C语言犹如雨后春笋般地搅动着IT界,而这些语言有别于汇编语言那样。它们就是更贴切自然语言的高级编程语言,可这些高级编程语言最终还是要编译成机器语言(汇编语言)。

EVM(Ethereum Virtual Machine)是一种栈(Stack)结构,我们知道是一种先进后出(LIFO)的数据结构。

那为什么要用汇编来编写呢?

借您所问,既然 Solidity 可以编写出优秀的智能合约,那为什么还要使用低级地汇编语言呢?

在回答这个问题之前,我们来看看每个新的编程语言诞生都是为了解决当前编程语言无法解决,或者说使用当前编程语言解决起来比较麻烦,那么,新的编程语言就在这样的环境下应运而生,当然咯,并不是所有新编程语言都是为了解决当前编程语言不能解决的问题,才被开发出来,而是……(此处不便说出缘由,毕竟它也不是本文的重点)。

细粒度控制

Assembly允许您执行一些仅仅靠 Solidity 无法实现的逻辑,比如,指向特定的内存插槽(Memory Slot)

当我们在编写库(library)时,细粒度控制特别有用,因为它们会被重复使用。

节省 gas

在 Solidity 中使用 Assembly 的主要好处之一是节省 gas。 让我们尝试通过创建一个将 2 个值 x 和 y 相加并返回结果的函数来比较 Solidity 和 Assembly 之间的 gas 成本。

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

contract AssemblyExample {

    function addAssembly(uint x, uint y) public pure returns (uint) {
        assembly {
            let result := add(x, y)
            mstore(0x0, result)
            return(0x0, 32)
        }
    }

    function addSolidity(uint x, uint y) public pure returns (uint) {
        return x + y;
    }

}

img

Solidity 中两种方式实现 Assembly

  • 1、 内联汇编:也可以在 Solidity 代码中使用。
  • 2、 独立程序集:无需编写 Solidity 代码即可使用。

怎么使用 Assembly?

正如上面的例子那样,汇编代码运行在assembly { ...}汇编块中的。

汇编代码是使用YUL语言来编写的!

内联汇编块不共享命名空间,即不能在一个汇编块调用另一个汇编块中定义的变量。

assembly {
   // some assembly code here
}

img

以下是一个简单的示例,函数接受两个参数,并将它们的和作为返回值,看看使用 Assembly是怎么实现的?了解它们在 EVM的工作方式。

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

contract AssemblyExample {

   function addition(uint x, uint y) public pure returns (uint) {

    assembly {

        //声明一个 result 变量,并将 x,y之和赋值给它
        let result := add(x, y)   // x + y

        //使用 mstore 操作码将 result存在 memory 中,地址是 0x0
        mstore(0x0, result)       // store result in memory

        //返回 32 字节的 memory 地址
        return(0x0, 32)          

    }
}

}

img

数据存储

让我们来看看一个简单的例子。我们将数据存放在storage(存储)中,然后再去调用它。

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

contract StorageDataExample {

    function setData(uint256 newValue) public {
        assembly {
            sstore(0, newValue)
        }
    }

    function getData() public view returns(uint256) {
        assembly {
            let v := sload(0)
            mstore(0x80, v)
            return(0x80, 32)
        }
    }
}

img

setData函数使用了sstore操作码将变量newValue写入storage(存储)中。

getData函数先是用了sload操作码来加载storage(存储)中的数据,它并不能从storage中直接返回。所以才需要mstore操作码将其写入memory(内存)中,最后我们返回引用memory(内存)中存放数据的地址和 32 字节长度的数据。

https://docs.soliditylang.org/en/latest/yul.html

指令解释
stop()-F停止执行,与return(0, 0)相同
add(x, y)Fx + y
sub(x, y)Fx - y
mul(x, y)Fx * y
div(x, y)Fx / y 或 如果 y == 0,则为 0
sdiv(x, y)Fx / y,对于有符号的二进制补数,如果 y == 0,则为 0
mod(x, y)Fx % y, 如果 y == 0,则为 0
smod(x, y)Fx % y, 对于有符号的二进制补数, 如果 y == 0,则为 0
exp(x, y)Fx的y次方
not(x)Fx的位 “非”(x的每一个位都被否定)
lt(x, y)F如果 x < y,则为1,否则为0
gt(x, y)F如果 x > y,则为1,否则为0
slt(x, y)F如果 x < y,则为1,否则为0,适用于有符号的二进制数
sgt(x, y)F如果 x > y,则为1,否则为0,适用于有符号的二进制补数
eq(x, y)F如果 x == y,则为1,否则为0
iszero(x)F如果 x == 0,则为1,否则为0
and(x, y)Fx 和 y 的按位 “与”
or(x, y)Fx 和 y 的按位 “或”
xor(x, y)Fx 和 y 的按位 “异或”
byte(n, x)Fx的第n个字节,其中最重要的字节是第0个字节
shl(x, y)C将 y 逻辑左移 x 位
shr(x, y)C将 y 逻辑右移 x 位
sar(x, y)C将 y 算术右移 x 位
addmod(x, y, m)F(x + y) % m,采用任意精度算术,如果m == 0则为0
mulmod(x, y, m)F(x * y) % m,采用任意精度算术,如果m == 0则为0
signextend(i, x)F从第 (i*8+7) 位开始进行符号扩展,从最低符号位开始计算
keccak256(p, n)Fkeccak(mem[p…(p+n)))
pc()F代码中的当前位置
pop(x)-F丢弃值 x
mload(p)Fmem[p…(p+32))
mstore(p, v)-Fmem[p…(p+32)) := v
mstore8(p, v)-Fmem[p] := v & 0xff ((只修改了一个字节))
sload(p)Fstorage[p]
sstore(p, v)-Fstorage[p] := v
msize()F内存的大小,即最大的访问内存索引
gas()F仍可以执行的气体值
address()F当前合约/执行环境的地址
balance(a)F地址为A的余额,以wei为单位
selfbalance()I相当于balance(address()),但更便宜
caller()F消息调用者(不包括 delegatecall 调用)。
callvalue()F与当前调用一起发送的wei的数量
calldataload(p)F从位置p开始的调用数据(32字节)
calldatasize()F调用数据的大小,以字节为单位
calldatacopy(t, f, s)-F从位置f的calldata复制s字节到位置t的内存中
codesize()F当前合约/执行环境的代码大小
codecopy(t, f, s)-F从位置f的code中复制s字节到位置t的内存中
extcodesize(a)F地址为a的代码的大小
extcodecopy(a, t, f, s)-F像codecopy(t, f, s)一样,但在地址a处取代码
returndatasize()B最后返回数据的大小
returndatacopy(t, f, s)-B从位置f的returndata复制s字节到位置t的内存中
extcodehash(a)C地址a的代码哈希值
create(v, p, n)F用代码mem[p…(p+n))创建新的合约,发送v数量的wei并返回新地址; 错误时返回0
create2(v, p, n, s)C在keccak256(0xff . this . s . keccak256(mem[p…(p+n)))地址处 创建代码为mem[p…(p+n)]的新合约 并发送v 数量个wei和返回新地址, 其中 0xff 是一个1字节的值, this 是当前合约的地址, 是一个20字节的值, s 是一个256位的大端的值; 错误时返回0
call(g, a, v, in, insize, out, outsize)F调用地址 a 上的合约,以 mem[in..(in+insize)) 作为输入 一并发送 g 数量的 gas 和 v 数量的 wei, 以 mem[out..(out+outsize)) 作为输出空间。 若错误,返回 0 (比如,gas 用光) 若成功,返回 1
callcode(g, a, v, in, insize, out, outsize)F相当于 call 但仅仅使用地址 a 上的代码, 执行时留在当前合约的上下文当中
delegatecall(g, a, in, insize, out, outsize)H相当于 callcode, 但同时保留 callercallvalue
staticcall(g, a, in, insize, out, outsize)B相当于 call(g, a, 0, in, insize, out, outsize) 但不允许状态变量的修改
return(p, s)-F终止执行,返回 mem[p..(p+s)) 上的数据
revert(p, s)-B终止执行,恢复状态变更,返回 mem[p..(p+s)) 上的数据
selfdestruct(a)-F终止执行,销毁当前合约,并且将余额发送到地址 a
invalid()-F以无效指令终止执行
log0(p, s)-F用 mem[p..(p+s)] 上的数据产生日志,但没有 topic
log1(p, s, t1)-F用 mem[p..(p+s)] 上的数据和 topic t1 产生日志
log2(p, s, t1, t2)-F用 mem[p..(p+s)] 上的数据和 topic t1,t2 产生日志
log3(p, s, t1, t2, t3)-F用 mem[p..(p+s)] 上的数据和 topic t1,t2,t3 产生日志
log4(p, s, t1, t2, t3, t4)-F用 mem[p..(p+s)] 上的数据和 topic t1,t2,t3,t4 产生日志
chainid()I执行链的ID(EIP-1344)
basefee()L当前区块的基本费用(EIP-3198和EIP-1559)
origin()F交易发送者
gasprice()F交易的气体价格n
blockhash(b)F区块编号b的哈希值—只针对最近的256个区块,不包括当前区块。
coinbase()F目前的挖矿的受益者
timestamp()F自 epoch 开始的,当前块的时间戳,以秒为单位
number()F当前区块号
difficulty()F当前区块的难度
gaslimit()F当前区块的区块 gas 限制