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 ...
随机推荐
- SqlServer 查看死锁的进程
版权声明:本文为 走错路的程序员 原创文章,欢迎转载. https://blog.csdn.net/phker/article/details/78612974搞sqlsever 好多年, 从来没锁过 ...
- AnyVal与AnyRef
AnyRef 是所有引用类型的基类.除了值类型,所有类型都继承自AnyRef . AnyVal AnyVal 所有值类型的基类, 它描述的是值,而不是代表一个对象. 它包括 9 个 AnyVal ...
- oracle的start with connect by prior
oracle的start with connect by prior是根据条件递归查询"树",分为四种使用情况: 第一种:start with 子节点ID='...' connec ...
- nginx跳转访问
server { listen 8888; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; ...
- 如何在表单中使用Ajax
1.HTML就是一个简单表单验证,有登录按钮,点击登录会发送Ajax, 这里就是简单如果用户名为:zhouzhiruo,密码为:123456,就是登录成功,否则登录失败 应该在发送请求之前对input ...
- OpenCV 填充(ROI)+模糊操作
1.ROI 操作 src = cv.imread('./1.jpg') cv.imshow('src',src) dst = src[40:240,100:300] gray = cv.cvtColo ...
- Kotlin入门(17)等式判断的情况
话说等式可是编程语言最基本的表达式之一,不管哪种高级语言,无一例外都采用双等号“==”判断两个变量是否相等:就算是复杂的对象,在Java中也可通过equals函数判断两个实例是否相等.按理说这些能够满 ...
- (网页)angularjs中的interval定时执行功能(转)
转载博客园魔豆: 一个例子,用来显示当前实时时间,1秒钟刷新一次: <!DOCTYPE html> <html ng-app="myApp"> <he ...
- (后端)sql server 按时间段查询
百度的资料,保存下来: 在写按时间段查询的sql语句的时候 一般我们会这么写查询条件: where date>='2010-01-01' and date<='2010-10-1'. 但是 ...
- Unity3D开发之3D按钮的声音播放
这里我们首先就简易的制作一个非常简单的3D按钮![ 图中就一个cube 加个3DText,然后我们就编写代码 [RequireComponent(typeof(CompoundButton))]//特 ...