问题描述:为什么将0x80
存在内存位置0x50
?
指令序列:
0000 PUSH1 80
0002 PUSH1 40
0004 MSTORE
0005 CALLVALUE
栈Stack
:
0: 0x0000000000000000000000000000000000000000000000000000000000000000
内存Memory
:
0x0: 00000000000000000000000000000000 ????????????????
0x10: 00000000000000000000000000000000 ????????????????
0x20: 00000000000000000000000000000000 ????????????????
0x30: 00000000000000000000000000000000 ????????????????
0x40: 00000000000000000000000000000000 ????????????????
0x50: 00000000000000000000000000000080 ????????????????
上面是问题。下面给出解答。
-
栈中的元素
0x0000000000000000000000000000000000000000000000000000000000000000
是因为CALLVALUE
操作码执行后的结果。否则,如果只有前3
条指令,栈应为空。 -
下面模拟指令
0
执行,栈中元素为0x0000000000000000000000000000000000000000000000000000000000000080
。PUSH1
是将1
个字节大小的值放在栈上。栈的每个slot
是一个字(256
比特)。0:0x0000000000000000000000000000000000000000000000000000000000000080
-
继续模拟指令
2
执行,将40
压栈。此时栈的状态如下:
0:0x0000000000000000000000000000000000000000000000000000000000000040
1:0x0000000000000000000000000000000000000000000000000000000000000080 -
接下来执行指令
5
,在本文的上下文中,MSTORE
操作码的功能是将从栈中弹出两个slot
中的数据,并完成M[S[0]]:=S[1]
。其中M
为内存,S
为栈。 -
按照所述,那为何将
0x80
存在了内存位置0x50
? -
因为内存是按字寻址的字节数组。在内存地址
0x40
存放占一个字的数据(显然要做内存扩展)。0x40-0x4f
存放16
字节。0x50-0x5f
存放16
字节。而EVM
是采用大端序,因此0x80
恰好存在0x50
。
00000000000000000000000000000000 (16字节)
00000000000000000000000000000080 (16字节)
在remix的调试界面中, 整个字跨了2行。
相同的疑惑参见stackexchange,btw,该问题得到了ConsenSys的开发者Ben Edgington的解答。Cool。