aboutsummaryrefslogtreecommitdiffstats
path: root/ethchain/asm.go
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-04-16 04:16:38 +0800
committerobscuren <geffobscura@gmail.com>2014-04-16 04:16:38 +0800
commitca13e3b1058f0d680b79dc1d9319d427a09493f8 (patch)
treea121191d4e43ecc41878d268f46739e121fc111b /ethchain/asm.go
parent086acd122b59071255b0c1cfae569748b1d7427a (diff)
downloaddexon-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.go126
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
+}