From a5cc2667e4aee8bd29c6250c5cb79df1df0b511f Mon Sep 17 00:00:00 2001 From: Friedrich Ludwig <56637264+isparkyou-github@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:01:02 -0400 Subject: [PATCH] Update isparkyou.md --- isparkyou.md | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) diff --git a/isparkyou.md b/isparkyou.md index 5aecd562..50463ab3 100644 --- a/isparkyou.md +++ b/isparkyou.md @@ -7378,6 +7378,217 @@ class EVM: self.pop() ``` +### 算数指令 +#### ADD +ADD指令从堆栈中弹出两个元素,将它们相加,然后将结果推入堆栈。如果堆栈元素不足两个,那么会抛出异常。这个指令的操作码是0x01,gas消耗为3。 +``` +def add(self): + if len(self.stack) < 2: + raise Exception('Stack underflow') + a = self.stack.pop() + b = self.stack.pop() + res = (a + b) % (2**256) # 加法结果需要模2^256,防止溢出 + self.stack.append(res) +def run(self): + while self.pc < len(self.code): + op = self.next_instruction() + + if PUSH1 <= op <= PUSH32: + size = op - PUSH1 + 1 + self.push(size) + elif op == PUSH0: + self.stack.append(0) + self.pc += size + elif op == POP: + self.pop() + elif op == ADD: # 处理ADD指令 + self.add() +``` +#### MUl +MUL指令和ADD类似,但是它将堆栈的顶部两个元素相乘。操作码是0x02,gas消耗为5。 +``` +def mul(self): + if len(self.stack) < 2: + raise Exception('Stack underflow') + a = self.stack.pop() + b = self.stack.pop() + res = (a * b) % (2**256) # 乘法结果需要模2^256,防止溢出 + self.stack.append(res) +def run(self): + while self.pc < len(self.code): + op = self.next_instruction() + + if PUSH1 <= op <= PUSH32: + size = op - PUSH1 + 1 + self.push(size) + elif op == PUSH0: + self.stack.append(0) + self.pc += size + elif op == POP: + self.pop() + elif op == ADD: + self.add() + elif op == MUL: # 处理MUL指令 + self.mul() +``` +#### SUB +SUB指令从堆栈顶部弹出两个元素,然后计算第二个元素减去第一个元素,最后将结果推入堆栈。这个指令的操作码是0x03,gas消耗为3。 +``` +def sub(self): + if len(self.stack) < 2: + raise Exception('Stack underflow') + a = self.stack.pop() + b = self.stack.pop() + res = (b - a) % (2**256) # 结果需要模2^256,防止溢出 + self.stack.append(res) +def run(self): + while self.pc < len(self.code): + op = self.next_instruction() + + if PUSH1 <= op <= PUSH32: + size = op - PUSH1 + 1 + self.push(size) + elif op == PUSH0: + self.stack.append(0) + self.pc += size + elif op == POP: + self.pop() + elif op == ADD: + self.add() + elif op == MUL: + self.mul() + elif op == SUB: # 处理SUB指令 + self.sub() +``` +#### DIV +DIV指令从堆栈顶部弹出两个元素,然后将第二个元素除以第一个元素,最后将结果推入堆栈。如果第一个元素(除数)为0,则将0推入堆栈。这个指令的操作码是0x04,gas消耗为5。 +``` +def div(self): + if len(self.stack) < 2: + raise Exception('Stack underflow') + a = self.stack.pop() + b = self.stack.pop() + if a == 0: + res = 0 + else: + res = (b // a) % (2**256) + self.stack.append(res) +def run(self): + while self.pc < len(self.code): + op = self.next_instruction() + + if PUSH1 <= op <= PUSH32: + size = op - PUSH1 + 1 + self.push(size) + elif op == PUSH0: + self.stack.append(0) + self.pc += size + elif op == POP: + self.pop() + elif op == ADD: + self.add() + elif op == MUL: + self.mul() + elif op == SUB: + self.sub() + elif op == DIV: # 处理DIV指令 + self.div() +``` +#### SDIV +带符号整数的除法指令。与DIV类似,这个指令会从堆栈中弹出两个元素,然后将第二个元素除以第一个元素,结果带有符号。如果第一个元素(除数)为0,结果为0。它的操作码是0x05,gas消耗为5。要注意,EVM字节码中的负数是用二进制补码(two’s complement)形式,比如-1表示为0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff,它加一等于0。 +``` +def sdiv(self): + if len(self.stack) < 2: + raise Exception('Stack underflow') + a = self.stack.pop() + b = self.stack.pop() + res = b//a % (2**256) if a!=0 else 0 + self.stack.append(res) +``` +#### MOD +取模指令。这个指令会从堆栈中弹出两个元素,然后将第二个元素除以第一个元素的余数推入堆栈。如果第一个元素(除数)为0,结果为0。它的操作码是0x06,gas消耗为5。 +``` +def mod(self): + if len(self.stack) < 2: + raise Exception('Stack underflow') + a = self.stack.pop() + b = self.stack.pop() + res = b % a if a != 0 else 0 + self.stack.append(res) +``` +#### SMOD +带符号的取模指令。这个指令会从堆栈中弹出两个元素,然后将第二个元素除以第一个元素的余数推入堆栈,结果带有第二个元素的符号。如果第一个元素(除数)为0,结果为0。它的操作码是0x07,gas消耗为5。 +``` +def smod(self): + if len(self.stack) < 2: + raise Exception('Stack underflow') + a = self.stack.pop() + b = self.stack.pop() + res = b % a if a != 0 else 0 + self.stack.append(res) +``` +#### ADDMOD +模加法指令。这个指令会从堆栈中弹出三个元素,将前两个元素相加,然后对第三个元素取模,将结果推入堆栈。如果第三个元素(模数)为0,结果为0。它的操作码是0x08,gas消耗为8。 +``` +def addmod(self): + if len(self.stack) < 3: + raise Exception('Stack underflow') + a = self.stack.pop() + b = self.stack.pop() + n = self.stack.pop() + res = (a + b) % n if n != 0 else 0 + self.stack.append(res) +``` +#### MULMOD +模乘法指令。这个指令会从堆栈中弹出三个元素,将前两个元素相乘,然后对第三个元素取模,将结果推入堆栈。如果第三个元素(模数)为0,结果为0。它的操作码是0x09,gas消耗为5。 +``` +def mulmod(self): + if len(self.stack) < 3: + raise Exception('Stack underflow') + a = self.stack.pop() + b = self.stack.pop() + n = self.stack.pop() + res = (a * b) % n if n != 0 else 0 + self.stack.append(res) +``` +#### EXP +指数运算指令。这个指令会从堆栈中弹出两个元素,将第二个元素作为底数,第一个元素作为指数,进行指数运算,然后将结果推入堆栈。它的操作码是0x0A,gas消耗为10。 +``` +def exp(self): + if len(self.stack) < 2: + raise Exception('Stack underflow') + a = self.stack.pop() + b = self.stack.pop() + res = pow(b, a) % (2**256) + self.stack.append(res) +``` +#### SIGNEXTEND +符号位扩展指令,即在保留数字的符号(正负性)及数值的情况下,增加二进制数字位数的操作。举个例子,若计算机使用8位二进制数表示数字“0000 1010”,且此数字需要将字长符号扩充至16位,则扩充后的值为“0000 0000 0000 1010”。此时,数值与符号均保留了下来。SIGNEXTEND指令会从堆栈中弹出两个元素,对第二个元素进行符号扩展,扩展的位数由第一个元素决定,然后将结果推入堆栈。它的操作码是0x0B,gas消耗为5。 +``` +def signextend(self): + if len(self.stack) < 2: + raise Exception('Stack underflow') + b = self.stack.pop() + x = self.stack.pop() + if b < 32: # 如果b>=32,则不需要扩展 + sign_bit = 1 << (8 * b - 1) # b 字节的最高位(符号位)对应的掩码值,将用来检测 x 的符号位是否为1 + x = x & ((1 << (8 * b)) - 1) # 对 x 进行掩码操作,保留 x 的前 b+1 字节的值,其余字节全部置0 + if x & sign_bit: # 检查 x 的符号位是否为1 + x = x | ~((1 << (8 * b)) - 1) # 将 x 的剩余部分全部置1 + self.stack.append(x) +``` + + + + + + + + + + + +