WTFOpcodes极简入门5.比较指令


文档摘要

WTF Opcodes极简入门: 5. 比较指令 我最近在重新学以太坊opcodes,也写一个“WTF EVM Opcodes极简入门”,供小白们使用。 推特:@0xAAScience 社区:Discord|微信群|官网 wtf.academy 所有代码和教程开源在github: github.com/WTFAcademy/WTF-Opcodes 这一讲,我们将介绍EVM中用于比较运算的6个指令,包括 (小于), (大于),和 (相等)。并且,我们将在用Python写的极简版EVM中添加对他们的支持。 LT (小于) 指令从堆栈中弹出两个元素,比较第二个元素是否小于第一个元素。如果是,那么将 推入堆栈,否则将 推入堆栈。如果堆栈元素不足两个,那么会抛出异常。

WTF Opcodes极简入门: 5. 比较指令

我最近在重新学以太坊opcodes,也写一个“WTF EVM Opcodes极简入门”,供小白们使用。

推特:@0xAA_Science

社区:Discord微信群官网 wtf.academy

所有代码和教程开源在github: github.com/WTFAcademy/WTF-Opcodes

这一讲,我们将介绍EVM中用于比较运算的6个指令,包括LT(小于),GT(大于),和EQ(相等)。并且,我们将在用Python写的极简版EVM中添加对他们的支持。

LT (小于)

LT指令从堆栈中弹出两个元素,比较第二个元素是否小于第一个元素。如果是,那么将0推入堆栈,否则将1推入堆栈。如果堆栈元素不足两个,那么会抛出异常。这个指令的操作码是0x10,gas消耗为3

我们可以将LT指令的实现添加到我们的极简EVM中:

def lt(self): if len(self.stack) < 2: raise Exception('Stack underflow') a = self.stack.pop() b = self.stack.pop() self.stack.append(int(b < a)) # 注意这里的比较顺序

我们在run()函数中添加对LT指令的处理:

def run(self): while self.pc < len(self.code): op = self.next_instruction() # ... 其他指令的处理 ... elif op == LT: # 处理LT指令 self.lt()

现在,我们可以尝试运行一个包含LT指令的字节码:0x6002600310(PUSH1 2 PUSH1 3 LT)。这个字节码将23推入堆栈,然后比较2是否小于3

code = b"\x60\x02\x60\x03\x10" evm = EVM(code) evm.run() print(evm.stack) # output: [0]

GT (大于)

GT指令和LT指令非常类似,不过它比较的是第二个元素是否大于第一个元素。如果是,那么将0推入堆栈,否则将1推入堆栈。如果堆栈元素不足两个,那么会抛出异常。这个指令的操作码是0x10,gas消耗为3。操作码是0x11,gas消耗为3

我们将GT指令的实现添加到极简EVM:

def gt(self): if len(self.stack) < 2: raise Exception('Stack underflow') a = self.stack.pop() b = self.stack.pop() self.stack.append(int(b > a)) # 注意这里的比较顺序

我们在run()函数中添加对GT指令的处理:

def run(self): while self.pc < len(self.code): op = self.next_instruction() # ... 其他指令的处理 ... elif op == GT: # 处理GT指令 self.gt()

现在,我们可以运行一个包含GT指令的字节码:0x6002600311(PUSH1 2 PUSH1 3 GT)。这个字节码将23推入堆栈,然后比较2是否大于3

code = b"\x60\x02\x60\x03\x11" evm = EVM(code) evm.run() print(evm.stack) # output: [1]

EQ (等于)

EQ指令从堆栈中弹出两个元素,如果两个元素相等,那么将1推入堆栈,否则将0推入堆栈。该指令的操作码是0x14,gas消耗为3

我们将EQ指令的实现添加到极简EVM:

def eq(self): if len(self.stack) < 2: raise Exception('Stack underflow') a = self.stack.pop() b = self.stack.pop() self.stack.append(int(a == b))

我们在run()函数中添加对EQ指令的处理:

elif op == EQ: self.eq()

现在,我们可以运行一个包含EQ指令的字节码:0x6002600314(PUSH1 2 PUSH1 3 EQ)。这个字节码将23推入堆栈,然后比较两者是否相等。

code = b"\x60\x02\x60\x03\x14" evm = EVM(code) evm.run() print(evm.stack) # output: [0]

ISZERO (是否为零)

ISZERO指令从堆栈中弹出一个元素,如果元素为0,那么将1推入堆栈,否则将0推入堆栈。该指令的操作码是0x15,gas消耗为3

我们将ISZERO指令的实现添加到极简EVM:

def iszero(self): if len(self.stack) < 1: raise Exception('Stack underflow') a = self.stack.pop() self.stack.append(int(a == 0))

我们在run()函数中添加对ISZERO指令的处理:

elif op == ISZERO: self.iszero()

现在,我们可以运行一个包含ISZERO指令的字节码:0x600015(PUSH1 0 ISZERO)。这个字节码将0推入堆栈,然后检查其是否为0。

code = b"\x60\x00\x15" evm = EVM(code) evm.run() print(evm.stack) # output: [1]

其他比较指令

  1. SLT (有符号小于): 这个指令会从堆栈中弹出两个元素,然后比较第二个元素是否小于第一个元素,结果以有符号整数形式返回。如果第二个元素小于第一个元素,将0推入堆栈,否则将1推入堆栈。它的操作码是0x12,gas消耗为3

    def slt(self): if len(self.stack) < 2: raise Exception('Stack underflow') a = self.stack.pop() b = self.stack.pop() self.stack.append(int(b < a)) # 极简evm stack中的值已经是以有符号整数存储了,所以和lt一样实现
  2. SGT (有符号大于): 这个指令会从堆栈中弹出两个元素,然后比较第二个元素是否大于第一个元素,结果以有符号整数形式返回。如果第二个元素大于第一个元素,将0推入堆栈,否则将1推入堆栈。它的操作码是0x13,gas消耗为3

    def sgt(self): if len(self.stack) < 2: raise Exception('Stack underflow') a = self.stack.pop() b = self.stack.pop() self.stack.append(int(b > a)) # 极简evm stack中的值已经是以有符号整数存储了,所以和gt一样实现

总结

这一讲,我们介绍了EVM中的6个比较指令,并在极简版EVM中添加了对他们的支持。课后习题: 写出0x6003600414对应的指令形式,并给出运行后的堆栈状态。


发布者: 作者: 转发
评论区 (0)
U