Skip to content

Commit

Permalink
Update isparkyou.md
Browse files Browse the repository at this point in the history
  • Loading branch information
isparkyou-github authored Oct 17, 2024
1 parent 6835187 commit a5cc266
Showing 1 changed file with 211 additions and 0 deletions.
211 changes: 211 additions & 0 deletions isparkyou.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
```















Expand Down

0 comments on commit a5cc266

Please sign in to comment.