solidity 汇编语言问题——内存数据mload时为什么从第32位开始
问题:内存数据mload时为什么从第32位开始
代码出处:https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
pragma solidity ^0.4.;
library ECVerify {
// Duplicate Solidity's ecrecover, but catching the CALL return value
function safer_ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal returns (bool, address) {
// We do our own memory management here. Solidity uses memory offset
// 0x40 to store the current end of memory. We write past it (as
// writes are memory extensions), but don't update the offset so
// Solidity will reuse it. The memory used here is only needed for
// this context. // FIXME: inline assembly can't access return values
bool ret;
address addr; assembly {
let size := mload(0x40)
mstore(size, hash)
mstore(add(size, ), v)
mstore(add(size, ), r)
mstore(add(size, ), s) // NOTE: we can reuse the request memory because we deal with
// the return code
ret := call(, , , size, , size, )
addr := mload(size)
} return (ret, addr);
} function ecrecovery(bytes32 hash, bytes sig) public returns (bool, address) {
bytes32 r;
bytes32 s;
uint8 v; if (sig.length != )
return (false, ); // The signature format is a compact form of:
// {bytes32 r}{bytes32 s}{uint8 v}
// Compact means, uint8 is not padded to 32 bytes.
assembly {
r := mload(add(sig, ))//????????????
s := mload(add(sig, )) // Here we are loading the last 32 bytes. We exploit the fact that
// 'mload' will pad with zeroes if we overread.
// There is no 'mload8' to do this, but that would be nicer.
v := byte(, mload(add(sig, ))) // Alternative solution:
// 'byte' is not working due to the Solidity parser, so lets
// use the second best option, 'and'
// v := and(mload(add(sig, 65)), 255)
} // albeit non-transactional signatures are not specified by the YP, one would expect it
// to match the YP range of [27, 28]
//
// geth uses [0, 1] and some clients have followed. This might change, see:
// https://github.com/ethereum/go-ethereum/issues/2053
if (v < )
v += ; if (v != && v != )
return (false, ); return safer_ecrecover(hash, v, r, s);
} function ecverify(bytes32 hash, bytes sig, address signer) public returns (bool,address) {
bool ret;
address addr;
(ret, addr) = ecrecovery(hash, sig);
return (ret == true && addr == signer,addr);
}
} contract ECVerifyTest {
function test_v0() public returns (bool,address) {
bytes32 hash = 0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad;
bytes memory sig = "\xac\xa7\xda\x99\x7a\xd1\x77\xf0\x40\x24\x0c\xdc\xcf\x69\x05\xb7\x1a\xb1\x6b\x74\x43\x43\x88\xc3\xa7\x2f\x34\xfd\x25\xd6\x43\x93\x46\xb2\xba\xc2\x74\xff\x29\xb4\x8b\x3e\xa6\xe2\xd0\x4c\x13\x36\xea\xce\xaf\xda\x3c\x53\xab\x48\x3f\xc3\xff\x12\xfa\xc3\xeb\xf2\x00";
return ECVerify.ecverify(hash, sig, 0x0E5cB767Cce09A7F3CA594Df118aa519BE5e2b5A);
} function test_v1() public returns (bool,address) {
bytes32 hash = 0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad;
bytes memory sig = "\xde\xba\xaa\x0c\xdd\xb3\x21\xb2\xdc\xaa\xf8\x46\xd3\x96\x05\xde\x7b\x97\xe7\x7b\xa6\x10\x65\x87\x85\x5b\x91\x06\xcb\x10\x42\x15\x61\xa2\x2d\x94\xfa\x8b\x8a\x68\x7f\xf9\xc9\x11\xc8\x44\xd1\xc0\x16\xd1\xa6\x85\xa9\x16\x68\x58\xf9\xc7\xc1\xbc\x85\x12\x8a\xca\x01";
return ECVerify.ecverify(hash, sig, 0x8743523D96A1B2CbE0c6909653a56da18ed484Af);
}
}
每当使用出现了使用到汇编语言时,我就一直很奇怪一个问题,就是r := mload(add(sig, 32))这里为什么要加32,后面通过测试发现,前32个字节存储的是数据的长度
测试过程:
1)先得到原代码取得的(v, r, s) :
pragma solidity ^0.4.;
library ECVerify {
function ecrecovery(bytes32 hash, bytes sig) public returns (uint8, bytes32, bytes32) {
bytes32 r;
bytes32 s;
uint8 v; if (sig.length != )
return (v, r, s); // The signature format is a compact form of:
// {bytes32 r}{bytes32 s}{uint8 v}
// Compact means, uint8 is not padded to 32 bytes.
assembly {
r := mload(add(sig, ))
s := mload(add(sig, )) // Here we are loading the last 32 bytes. We exploit the fact that
// 'mload' will pad with zeroes if we overread.
// There is no 'mload8' to do this, but that would be nicer.
v := byte(, mload(add(sig, ))) // Alternative solution:
// 'byte' is not working due to the Solidity parser, so lets
// use the second best option, 'and'
// v := and(mload(add(sig, 65)), 255)
} // albeit non-transactional signatures are not specified by the YP, one would expect it
// to match the YP range of [27, 28]
//
// geth uses [0, 1] and some clients have followed. This might change, see:
// https://github.com/ethereum/go-ethereum/issues/2053
if (v < )
v += ; if (v != && v != )
return (v, r, s); return (v, r, s);
} } contract ECVerifyTest {
function test_v0() public returns (uint8,bytes32, bytes32) {
bytes32 hash = 0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad;
bytes memory sig = "\xac\xa7\xda\x99\x7a\xd1\x77\xf0\x40\x24\x0c\xdc\xcf\x69\x05\xb7\x1a\xb1\x6b\x74\x43\x43\x88\xc3\xa7\x2f\x34\xfd\x25\xd6\x43\x93\x46\xb2\xba\xc2\x74\xff\x29\xb4\x8b\x3e\xa6\xe2\xd0\x4c\x13\x36\xea\xce\xaf\xda\x3c\x53\xab\x48\x3f\xc3\xff\x12\xfa\xc3\xeb\xf2\x00";
return ECVerify.ecrecovery(hash, sig);
} function test_v1() public returns(uint8,bytes32, bytes32) {
bytes32 hash = 0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad;
bytes memory sig = "\xde\xba\xaa\x0c\xdd\xb3\x21\xb2\xdc\xaa\xf8\x46\xd3\x96\x05\xde\x7b\x97\xe7\x7b\xa6\x10\x65\x87\x85\x5b\x91\x06\xcb\x10\x42\x15\x61\xa2\x2d\x94\xfa\x8b\x8a\x68\x7f\xf9\xc9\x11\xc8\x44\xd1\xc0\x16\xd1\xa6\x85\xa9\x16\x68\x58\xf9\xc7\xc1\xbc\x85\x12\x8a\xca\x01";
return ECVerify.ecrecovery(hash, sig);
}
}
返回:


2)然后调用0位置的数据:
pragma solidity ^0.4.;
library ECVerify { function ecrecovery(bytes32 hash, bytes sig) public returns (uint8, bytes32, bytes32) {
bytes32 r;
bytes32 s;
uint8 v; if (sig.length != )
return (v, r, s); // The signature format is a compact form of:
// {bytes32 r}{bytes32 s}{uint8 v}
// Compact means, uint8 is not padded to 32 bytes.
assembly {
r := mload(add(sig, ))
s := mload(add(sig, )) // Here we are loading the last 32 bytes. We exploit the fact that
// 'mload' will pad with zeroes if we overread.
// There is no 'mload8' to do this, but that would be nicer.
v := byte(, mload(add(sig, ))) // Alternative solution:
// 'byte' is not working due to the Solidity parser, so lets
// use the second best option, 'and'
// v := and(mload(add(sig, 65)), 255)
} return (v, r, s);
} } contract ECVerifyTest {
function test_v0() public returns (uint8,bytes32, bytes32) {
bytes32 hash = 0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad;
bytes memory sig = "\xac\xa7\xda\x99\x7a\xd1\x77\xf0\x40\x24\x0c\xdc\xcf\x69\x05\xb7\x1a\xb1\x6b\x74\x43\x43\x88\xc3\xa7\x2f\x34\xfd\x25\xd6\x43\x93\x46\xb2\xba\xc2\x74\xff\x29\xb4\x8b\x3e\xa6\xe2\xd0\x4c\x13\x36\xea\xce\xaf\xda\x3c\x53\xab\x48\x3f\xc3\xff\x12\xfa\xc3\xeb\xf2\x00";
return ECVerify.ecrecovery(hash, sig);
} function test_v1() public returns(uint8,bytes32, bytes32) {
bytes32 hash = 0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad;
bytes memory sig = "\xde\xba\xaa\x0c\xdd\xb3\x21\xb2\xdc\xaa\xf8\x46\xd3\x96\x05\xde\x7b\x97\xe7\x7b\xa6\x10\x65\x87\x85\x5b\x91\x06\xcb\x10\x42\x15\x61\xa2\x2d\x94\xfa\x8b\x8a\x68\x7f\xf9\xc9\x11\xc8\x44\xd1\xc0\x16\xd1\xa6\x85\xa9\x16\x68\x58\xf9\xc7\xc1\xbc\x85\x12\x8a\xca\x01";
return ECVerify.ecrecovery(hash, sig);
}
}
返回结果:

0x41 = 65,所以能够得出结论,前32字节存储的是参数的长度
solidity 汇编语言问题——内存数据mload时为什么从第32位开始的更多相关文章
- [oracle] Oracle存储过程里操作BLOB的字节数据的办法,例如写入32位整数
作者: zyl910 一.缘由 BLOB是指二进制大对象,也就是英文Binary Large Object的缩写. 在很多时候,我们是通过其他编程语言(如Java)访问BLOB的字节数据,进行字节级的 ...
- 安装64位office时提示已安装32位的office
运行 regedit,进入到HKEY_CLASSES_ROOT\Installer\Products下,删除0000510开头的项,没有00005我把00002....的删了也可以
- 安装office2016 64位时提示64位与32位的office程序不兼容,在系统是64位的情况下,由于应用的需要,必须装64位的office,怎么办
解决办法如下: 如果是,那就看看32位的能不能安装了,要是能,就重新安装一次,把所有组件全部安装,然后,在进行卸载,一般可以卸载成功 如果卸载不成功,这个时候再使用微软的专用卸载工具,——要认清,一定 ...
- Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式
Linux就这个范儿 第15章 七种武器 linux 同步IO: sync.fsync与fdatasync Linux中的内存大页面huge page/large page David Cut ...
- CCS内存数据转成图片
在嵌入式DSP图像处理开发过程中,经常需要将DSP内存中的图像数据保存下来,作为数据集.CCS5.4或者CCS3.3都只支持保存内存原始数据而不支持将内存数据直接存储为一张图片,为了能将CCS保存的. ...
- ASM:《X86汇编语言-从实模式到保护模式》第10章:32位x86处理器的编程架构
★PART1:32位的x86处理器执行方式和架构 1. 寄存器的拓展(IA-32) 从80386开始,处理器内的寄存器从16位拓展到32位,命名其实就是在前面加上e(Extend)就好了,8个通用寄存 ...
- 32位模式下C/C++程序可用最大内存
关于32位程序申请大内存问题(1.6G). 我在win7 64系统上面测试Visual studio 10 int* Test=new int[1024*1024*200]; int* Test2=n ...
- 32位x86处理器编程导入——《x86汇编语言:从实模式到保护模式》读书笔记08
在说正题之前,我们先看2个概念. 1.指令集架构(ISA) ISA 的全称是 instruction set architecture,中文就是指令集架构,是指对程序员实际"可见" ...
- 32位Windows7 利用多余的不能识别的电脑内存 RAMDISK5.5教程
32位Windows7 利用多余的不能识别的电脑内存 RAMDISK5.5教程 环境:Windows7 32位 Ultimate 内存8GB 只能识别2.95GB内存 ramdisk5.5只适用于Wi ...
随机推荐
- Strust2框架笔记01_XML配置_action编写
目录 1.Struts2概述 1.1 什么是Struts2 1.2 Web层框架基于前端控制器模型设计 2. Struts2入门案例 2.1 Struts2的开发环境 2.2 解压开发包 2.3 创建 ...
- 【Java深入研究】6、CGLib动态代理机制详解
一.首先说一下JDK中的动态代理: JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的 但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该 ...
- 使用git push命令如何忽略不想提交的文件夹或者文件
如下场景是在window下的操作. 在使用node的时候有个node_modules文件夹很大,一般情况下不想提交,忽略的办法如: 方法一(来自评论区):直接在仓库根目录:执行命令echo 'node ...
- scala简单入门_wordCount
scala的语法写起来是非常的舒服的,相比java来说,简便许多.而Java在scala面前就显的略微有些笨重了. 接下来我们看一下scala版的wordcount import scala.io.S ...
- HTML5 template元素
前言 转自http://www.zhangxinxu.com/wordpress/2014/07/hello-html5-template-tag/ 在单页面应用,我们对页面的无刷新有了更高的要求,H ...
- codechef QCHEF(不删除莫队)
题意 题目链接 给出长度为\(n\)的序列,每次询问区间\([l, r]\),要求最大化 \(max |x − y| : L_i ≤ x, y ≤ R_i and A_x = A_y\) Sol 标算 ...
- 洛谷P2572 [SCOI2010]序列操作(ODT)
题解 题意 题目链接 Sol ODT板子题..... // luogu-judger-enable-o2 #include<bits/stdc++.h> #define LL long l ...
- 【读书笔记】iOS-应用内购买
Store Kit框架是一个应用内支付引擎.通过这个框架,付费应用可以实现用户付费购买内容的功能(比如为了获取额外的内容) 如果你发现Store Kit框架很难用,而且应用内付款不需要服务器端的支持, ...
- recovery 恢复出厂设置失败Data wipe failed
最近客户反馈,编译32位的android系统,在recovery中执行恢复出厂设置的时候失败了,失败的打印提升信息如下. Formatting /data... [ 2.191404] E:get_f ...
- 利用奇异值分解(SVD)进行图像压缩-python实现
首先要声明,图片的算法有很多,如JPEG算法,SVD对图片的压缩可能并不是最佳选择,这里主要说明SVD可以降维 相对于PAC(主成分分析),SVD(奇异值分解)对数据的列和行都进行了降维,左奇异矩阵可 ...