diff options
author | obscuren <geffobscura@gmail.com> | 2014-04-16 04:16:38 +0800 |
---|---|---|
committer | obscuren <geffobscura@gmail.com> | 2014-04-16 04:16:38 +0800 |
commit | ca13e3b1058f0d680b79dc1d9319d427a09493f8 (patch) | |
tree | a121191d4e43ecc41878d268f46739e121fc111b /ethchain/asm.go | |
parent | 086acd122b59071255b0c1cfae569748b1d7427a (diff) | |
download | dexon-ca13e3b1058f0d680b79dc1d9319d427a09493f8.tar.gz dexon-ca13e3b1058f0d680b79dc1d9319d427a09493f8.tar.zst dexon-ca13e3b1058f0d680b79dc1d9319d427a09493f8.zip |
Moved assembler stage processing to it's own file
Diffstat (limited to 'ethchain/asm.go')
-rw-r--r-- | ethchain/asm.go | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/ethchain/asm.go b/ethchain/asm.go new file mode 100644 index 000000000..5f901f8a2 --- /dev/null +++ b/ethchain/asm.go @@ -0,0 +1,126 @@ +package ethchain + +import ( + "fmt" + "github.com/ethereum/eth-go/ethutil" + "math/big" + "regexp" +) + +func CompileInstr(s interface{}) ([]byte, error) { + switch s.(type) { + case string: + str := s.(string) + isOp := IsOpCode(str) + if isOp { + return []byte{OpCodes[str]}, nil + } + + num := new(big.Int) + _, success := num.SetString(str, 0) + // Assume regular bytes during compilation + if !success { + num.SetBytes([]byte(str)) + } else { + // tmp fix for 32 bytes + n := ethutil.BigToBytes(num, 256) + return n, nil + } + + return num.Bytes(), nil + case int: + num := ethutil.BigToBytes(big.NewInt(int64(s.(int))), 256) + return num, nil + case []byte: + return ethutil.BigD(s.([]byte)).Bytes(), nil + } + + return nil, nil +} + +// Script compilation functions +// Compiles strings to machine code +func Assemble(instructions ...interface{}) (script []byte) { + //script = make([]string, len(instructions)) + + for _, val := range instructions { + instr, _ := CompileInstr(val) + + //script[i] = string(instr) + script = append(script, instr...) + } + + return +} + +func Disassemble(script []byte) (asm []string) { + pc := new(big.Int) + for { + if pc.Cmp(big.NewInt(int64(len(script)))) >= 0 { + return + } + + // Get the memory location of pc + val := script[pc.Int64()] + // Get the opcode (it must be an opcode!) + op := OpCode(val) + + asm = append(asm, fmt.Sprintf("%v", op)) + + switch op { + case oPUSH: // Push PC+1 on to the stack + pc.Add(pc, ethutil.Big1) + data := script[pc.Int64() : pc.Int64()+32] + val := ethutil.BigD(data) + + var b []byte + if val.Int64() == 0 { + b = []byte{0} + } else { + b = val.Bytes() + } + + asm = append(asm, fmt.Sprintf("0x%x", b)) + + pc.Add(pc, big.NewInt(31)) + case oPUSH20: + pc.Add(pc, ethutil.Big1) + data := script[pc.Int64() : pc.Int64()+20] + val := ethutil.BigD(data) + var b []byte + if val.Int64() == 0 { + b = []byte{0} + } else { + b = val.Bytes() + } + + asm = append(asm, fmt.Sprintf("0x%x", b)) + + pc.Add(pc, big.NewInt(19)) + } + + pc.Add(pc, ethutil.Big1) + } + + return +} + +func PreProcess(data string) (mainInput, initInput string) { + reg := "\\(\\)\\s*{([\\d\\w\\W\\n\\s]+?)}" + mainReg := regexp.MustCompile("main" + reg) + initReg := regexp.MustCompile("init" + reg) + + main := mainReg.FindStringSubmatch(data) + if len(main) > 0 { + mainInput = main[1] + } else { + mainInput = data + } + + init := initReg.FindStringSubmatch(data) + if len(init) > 0 { + initInput = init[1] + } + + return +} |