├── .gitignore ├── README.md ├── emu2.3 ├── main.go ├── px86 └── test.sh ├── emu3.2 ├── main.go ├── px86 └── test.sh ├── emu3.4 ├── emulator │ └── emulator.go ├── emulator_function │ └── emulator_function.go ├── instruction │ └── instruction.go ├── main ├── main.go └── modrm │ └── modrm.go └── emu3.7 ├── emulator └── emulator.go ├── emulator_function └── emulator_function.go ├── instruction └── instruction.go ├── main ├── main.go └── modrm └── modrm.go /.gitignore: -------------------------------------------------------------------------------- 1 | /tolset_p86* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # x86 Emulator by Golang 2 | 3 | Reference: [自作エミュレータで学ぶx86アーキテクチャ コンピュータが動く仕組みを徹底理解!](https://www.amazon.co.jp/dp/B0148FQNVC/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1) 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /emu2.3/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | type Register int 9 | 10 | type instruction_func_t func(*Emulator) 11 | 12 | type Emulator struct { 13 | registers [REGISTERS_COUNT]uint32 14 | eflags uint32 15 | memory [MEMORY_SIZE]byte 16 | eip uint32 17 | } 18 | 19 | const MEMORY_SIZE = 1024 * 1024 20 | 21 | const ( 22 | EAX Register = iota 23 | ECX 24 | EDX 25 | EBX 26 | ESP 27 | ESI 28 | EDI 29 | REGISTERS_COUNT 30 | ) 31 | 32 | var registers_name = [8]string{"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"} 33 | var instructions = [256]instruction_func_t{} 34 | 35 | func create_emu(eip uint32, esp uint32) (emu *Emulator) { 36 | 37 | emu = &Emulator{} 38 | emu.eip = eip 39 | emu.registers[ESP] = esp 40 | 41 | return emu 42 | } 43 | 44 | 45 | func dump_registers(emu *Emulator) { 46 | 47 | for i, v := range emu.registers { 48 | fmt.Printf("%s = %08x\n", registers_name[i], v) 49 | } 50 | fmt.Printf("EIP = %08x\n", emu.eip) 51 | 52 | } 53 | 54 | func get_code8(emu *Emulator, index int) uint32{ 55 | return uint32(emu.memory[int(emu.eip) + index]) 56 | } 57 | 58 | func get_sign_code8(emu *Emulator, index int) int32{ 59 | return int32(emu.memory[int(emu.eip) + index]) 60 | } 61 | 62 | func get_code32(emu *Emulator, index int) (ret uint32) { 63 | var i uint 64 | for i = 0; i < 4; i++ { 65 | ret |= get_code8(emu, index + int(i)) << (i * 8); 66 | } 67 | return ret; 68 | } 69 | 70 | func mov_r32_imm32(emu *Emulator) { 71 | reg := get_code8(emu, 0) - 0xb8; 72 | value := get_code32(emu, 1); 73 | emu.registers[reg] = value; 74 | emu.eip += 5 75 | } 76 | 77 | func short_jump(emu *Emulator) { 78 | diff := int8(get_sign_code8(emu, 1)) 79 | emu.eip += uint32(diff + 2) 80 | } 81 | 82 | 83 | func init_instructions() { 84 | for i := 0; i < 8; i++ { 85 | instructions[0xb8 + i] = mov_r32_imm32; 86 | } 87 | instructions[0xeb] = short_jump 88 | } 89 | 90 | func main() { 91 | 92 | if len(os.Args) != 2 { 93 | fmt.Println("usage: ./px86 filename") 94 | return 95 | } 96 | 97 | emu := create_emu(uint32(0x0000), uint32(0x7c00)) 98 | 99 | 100 | 101 | f, err := os.Open(os.Args[1]) 102 | if err != nil { 103 | fmt.Printf("%sファイルが開けません\n", os.Args[1]) 104 | } 105 | defer f.Close() 106 | 107 | buf := make([]byte, 0x200) 108 | n, _ := f.Read(buf) 109 | for i := 0; i < n; i++ { 110 | emu.memory[i] = buf[i] 111 | } 112 | 113 | init_instructions() 114 | 115 | for i := emu.eip; i < MEMORY_SIZE; i++ { 116 | code := uint8(get_code8(emu, 0)) 117 | fmt.Printf("EIP = %X, Code = %02X\n", emu.eip, code) 118 | 119 | if instructions[code] == nil { 120 | fmt.Printf("\n\nNot Implemented: %x\n", code) 121 | break 122 | } 123 | 124 | instructions[code](emu) 125 | 126 | if emu.eip == 0x00 { 127 | fmt.Printf("\n\nend of program.\n\n") 128 | break 129 | } 130 | } 131 | dump_registers(emu) 132 | } 133 | -------------------------------------------------------------------------------- /emu2.3/px86: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/owlinux1000/x86emulator/3c9b41424c9b340ec44076ef83786ba236f8f8a7/emu2.3/px86 -------------------------------------------------------------------------------- /emu2.3/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | go build -o px86 main.go 3 | ./px86 ../tolset_p86/pasm-helloworld/helloworld.bin 4 | 5 | -------------------------------------------------------------------------------- /emu3.2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | type Register int 9 | 10 | type instruction_func_t func(*Emulator) 11 | 12 | type Emulator struct { 13 | registers [REGISTERS_COUNT]uint32 14 | eflags uint32 15 | memory [MEMORY_SIZE]byte 16 | eip uint32 17 | } 18 | 19 | const MEMORY_SIZE = 1024 * 1024 20 | 21 | const ( 22 | EAX Register = iota 23 | ECX 24 | EDX 25 | EBX 26 | ESP 27 | ESI 28 | EDI 29 | REGISTERS_COUNT 30 | ) 31 | 32 | var registers_name = [8]string{"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"} 33 | var instructions = [256]instruction_func_t{} 34 | 35 | func create_emu(eip uint32, esp uint32) (emu *Emulator) { 36 | 37 | emu = &Emulator{} 38 | emu.eip = eip 39 | emu.registers[ESP] = esp 40 | 41 | return emu 42 | } 43 | 44 | 45 | func dump_registers(emu *Emulator) { 46 | 47 | for i, v := range emu.registers { 48 | fmt.Printf("%s = %08x\n", registers_name[i], v) 49 | } 50 | fmt.Printf("EIP = %08x\n", emu.eip) 51 | 52 | } 53 | 54 | func get_code8(emu *Emulator, index int) uint32{ 55 | return uint32(emu.memory[int(emu.eip) + index]) 56 | } 57 | 58 | func get_sign_code8(emu *Emulator, index int) int32{ 59 | return int32(emu.memory[int(emu.eip) + index]) 60 | } 61 | 62 | func get_code32(emu *Emulator, index int) (ret uint32) { 63 | var i uint 64 | for i = 0; i < 4; i++ { 65 | ret |= get_code8(emu, index + int(i)) << (i * 8); 66 | } 67 | return ret; 68 | } 69 | 70 | func get_sign_code32(emu *Emulator, index int) int32 { 71 | return int32(get_code32(emu, index)) 72 | } 73 | 74 | func mov_r32_imm32(emu *Emulator) { 75 | reg := get_code8(emu, 0) - 0xb8; 76 | value := get_code32(emu, 1); 77 | emu.registers[reg] = value; 78 | emu.eip += 5 79 | } 80 | 81 | func short_jump(emu *Emulator) { 82 | diff := int8(get_sign_code8(emu, 1)) 83 | emu.eip += uint32(diff + 2) 84 | } 85 | 86 | func near_jump(emu *Emulator) { 87 | diff := get_sign_code32(emu, 1) 88 | emu.eip += uint32(diff + 5) 89 | } 90 | 91 | func init_instructions() { 92 | // 0xb8 + regsiter number() 93 | for i := 0; i < 8; i++ { 94 | instructions[0xb8 + i] = mov_r32_imm32; 95 | } 96 | instructions[0xe9] = near_jump 97 | instructions[0xeb] = short_jump 98 | 99 | } 100 | 101 | func main() { 102 | 103 | if len(os.Args) != 2 { 104 | fmt.Println("usage: ./px86 filename") 105 | return 106 | } 107 | 108 | emu := create_emu(uint32(0x7c00), uint32(0x7c00)) 109 | 110 | f, err := os.Open(os.Args[1]) 111 | if err != nil { 112 | fmt.Printf("%sファイルが開けません\n", os.Args[1]) 113 | } 114 | 115 | buf := make([]byte, 0x200) 116 | n, _ := f.Read(buf) 117 | for i := 0; i < n; i++ { 118 | emu.memory[i+0x7c00] = buf[i] 119 | } 120 | f.Close() 121 | 122 | init_instructions() 123 | 124 | for i := emu.eip; i < MEMORY_SIZE; i++ { 125 | code := uint8(get_code8(emu, 0)) 126 | fmt.Printf("EIP = %X, Code = %02X\n", emu.eip, code) 127 | 128 | if instructions[code] == nil { 129 | fmt.Printf("\n\nNot Implemented: %x\n", code) 130 | break 131 | } 132 | 133 | instructions[code](emu) 134 | 135 | if emu.eip == 0x00 { 136 | fmt.Printf("\n\nend of program.\n\n") 137 | break 138 | } 139 | } 140 | dump_registers(emu) 141 | } 142 | -------------------------------------------------------------------------------- /emu3.2/px86: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/owlinux1000/x86emulator/3c9b41424c9b340ec44076ef83786ba236f8f8a7/emu3.2/px86 -------------------------------------------------------------------------------- /emu3.2/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | go build -o px86 main.go 3 | ./px86 ../tolset_p86/exec-helloworld/helloworld.bin 4 | -------------------------------------------------------------------------------- /emu3.4/emulator/emulator.go: -------------------------------------------------------------------------------- 1 | package emulator 2 | 3 | const MEMORY_SIZE = 1024 * 1024 4 | type Register int 5 | const ( 6 | EAX Register = iota 7 | ECX 8 | EDX 9 | EBX 10 | ESP 11 | EBP 12 | ESI 13 | EDI 14 | REGISTERS_COUNT 15 | ) 16 | 17 | type Emulator struct { 18 | Registers [REGISTERS_COUNT]uint32 19 | Eflags uint32 20 | Memory [MEMORY_SIZE]byte 21 | Eip uint32 22 | } 23 | -------------------------------------------------------------------------------- /emu3.4/emulator_function/emulator_function.go: -------------------------------------------------------------------------------- 1 | package emulator_function 2 | 3 | import ( 4 | . "../emulator" 5 | ) 6 | 7 | func Get_code8(emu *Emulator, index int) uint32{ 8 | return uint32(emu.Memory[int(emu.Eip) + index]) 9 | } 10 | 11 | func Get_sign_code8(emu *Emulator, index int) int32{ 12 | return int32(emu.Memory[int(emu.Eip) + index]) 13 | } 14 | 15 | func Get_code32(emu *Emulator, index int) (ret uint32) { 16 | var i uint 17 | for i = 0; i < 4; i++ { 18 | ret |= Get_code8(emu, index + int(i)) << (i * 8); 19 | } 20 | return ret; 21 | } 22 | 23 | func Get_sign_code32(emu *Emulator, index int) int32 { 24 | return int32(Get_code32(emu, index)) 25 | } 26 | 27 | func Get_register32(emu *Emulator, index int) uint32 { 28 | return emu.Registers[index] 29 | } 30 | 31 | func Set_register32(emu *Emulator, index uint32, value uint32) { 32 | emu.Registers[index] = value 33 | } 34 | 35 | func Set_memory8(emu *Emulator, address uint32, value uint32) { 36 | emu.Memory[address] = byte(value & 0xff) 37 | } 38 | 39 | func Set_memory32(emu *Emulator, address uint32, value uint32) { 40 | for i := 0; i < 4; i++ { 41 | Set_memory8(emu, address + uint32(i), value >> (uint(i) * 8)) 42 | } 43 | } 44 | 45 | func Get_memory8(emu *Emulator, address uint32) uint32 { 46 | return uint32(emu.Memory[address]) 47 | } 48 | 49 | func Get_memory32(emu *Emulator, address uint32) (ret uint32){ 50 | 51 | for i := 0; i < 4; i++ { 52 | ret |= Get_memory8(emu, address + uint32(i)) << (8 * uint32(i)) 53 | } 54 | return ret 55 | } 56 | -------------------------------------------------------------------------------- /emu3.4/instruction/instruction.go: -------------------------------------------------------------------------------- 1 | package instruction 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | . "../emulator" 7 | . "../emulator_function" 8 | . "../modrm" 9 | ) 10 | 11 | 12 | type Instruction_func_t func(*Emulator) 13 | var Instructions = [256]Instruction_func_t{} 14 | 15 | func Mov_r32_imm32(emu *Emulator) { 16 | reg := Get_code8(emu, 0) - 0xb8; 17 | value := Get_code32(emu, 1); 18 | emu.Registers[reg] = value; 19 | emu.Eip += 5 20 | } 21 | 22 | func Mov_r32_rm32(emu *Emulator) { 23 | emu.Eip += 1 24 | var modrm ModRM 25 | Parse_modrm(emu, &modrm) 26 | rm32 := Get_rm32(emu, &modrm) 27 | Set_r32(emu, &modrm, rm32) 28 | } 29 | 30 | func Mov_rm32_r32(emu *Emulator) { 31 | emu.Eip += 1 32 | var modrm ModRM 33 | Parse_modrm(emu, &modrm) 34 | r32 := Get_r32(emu, &modrm) 35 | Set_rm32(emu, &modrm, r32) 36 | } 37 | 38 | func Mov_rm32_imm32(emu *Emulator) { 39 | emu.Eip += 1 40 | var modrm ModRM 41 | Parse_modrm(emu, &modrm) 42 | value := Get_code32(emu, 0) 43 | emu.Eip += 4 44 | Set_rm32(emu, &modrm, value) 45 | } 46 | 47 | func Sub_rm32_imm8(emu *Emulator, modrm *ModRM) { 48 | rm32 := int32(Get_rm32(emu, modrm)) 49 | imm8 := int32(Get_sign_code8(emu, 0)) 50 | emu.Eip += 1 51 | Set_rm32(emu, modrm, uint32(rm32 - imm8)) 52 | } 53 | 54 | func Code_83(emu *Emulator) { 55 | emu.Eip += 1 56 | var modrm ModRM 57 | Parse_modrm(emu, &modrm) 58 | 59 | switch modrm.Opecode { 60 | case 5: 61 | Sub_rm32_imm8(emu, &modrm) 62 | default: 63 | fmt.Printf("not implemented: 83 /%d\n", modrm.Opecode) 64 | os.Exit(1) 65 | } 66 | } 67 | 68 | func Inc_rm32(emu *Emulator, modrm *ModRM) { 69 | value := Get_rm32(emu, modrm) 70 | Set_rm32(emu, modrm, value + 1) 71 | } 72 | 73 | func Code_ff(emu *Emulator) { 74 | emu.Eip += 1 75 | var modrm ModRM 76 | Parse_modrm(emu, &modrm) 77 | 78 | switch modrm.Opecode { 79 | case 0: 80 | Inc_rm32(emu, &modrm); 81 | default: 82 | fmt.Printf("not implemented: FF /%d\n", modrm.Opecode) 83 | os.Exit(1) 84 | } 85 | } 86 | 87 | func Add_rm32_r32(emu *Emulator) { 88 | emu.Eip += 1 89 | var modrm ModRM 90 | Parse_modrm(emu, &modrm) 91 | r32 := Get_r32(emu, &modrm) 92 | rm32 := Get_rm32(emu, &modrm) 93 | Set_rm32(emu, &modrm, rm32 + r32) 94 | } 95 | 96 | func Short_jump(emu *Emulator) { 97 | diff := int8(Get_sign_code8(emu, 1)) 98 | emu.Eip += uint32(diff + 2) 99 | } 100 | 101 | func Near_jump(emu *Emulator) { 102 | diff := Get_sign_code32(emu, 1) 103 | emu.Eip += uint32(diff + 5) 104 | } 105 | 106 | 107 | func Init_instructions() { 108 | 109 | Instructions[0x01] = Add_rm32_r32 110 | Instructions[0x83] = Code_83 111 | Instructions[0x89] = Mov_rm32_r32 112 | Instructions[0x8b] = Mov_r32_rm32 113 | 114 | // 0xb8 + regsiter number 115 | for i := 0; i < 8; i++ { 116 | Instructions[0xb8 + i] = Mov_r32_imm32 117 | } 118 | 119 | Instructions[0xc7] = Mov_rm32_imm32 120 | Instructions[0xe9] = Near_jump 121 | Instructions[0xeb] = Short_jump 122 | Instructions[0xff] = Code_ff 123 | } 124 | -------------------------------------------------------------------------------- /emu3.4/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/owlinux1000/x86emulator/3c9b41424c9b340ec44076ef83786ba236f8f8a7/emu3.4/main -------------------------------------------------------------------------------- /emu3.4/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | . "./emulator" 7 | . "./instruction" 8 | . "./emulator_function" 9 | ) 10 | 11 | var registers_name = [8]string{"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"} 12 | 13 | func read_binary(emu *Emulator, filename string) { 14 | 15 | f, err := os.Open(filename) 16 | 17 | if err != nil { 18 | fmt.Printf("%sファイルが開けません\n", os.Args[1]) 19 | os.Exit(1) 20 | } 21 | 22 | buf := make([]byte, 0x200) 23 | n, _ := f.Read(buf) 24 | 25 | for i := 0; i < n; i++ { 26 | emu.Memory[i+0x7c00] = buf[i] 27 | } 28 | f.Close() 29 | } 30 | 31 | func create_emu(eip uint32, esp uint32) (emu *Emulator) { 32 | 33 | emu = &Emulator{} 34 | emu.Eip = eip 35 | emu.Registers[ESP] = esp 36 | 37 | return emu 38 | } 39 | 40 | func dump_registers(emu *Emulator) { 41 | 42 | for i, v := range emu.Registers { 43 | fmt.Printf("%s = %08x\n", registers_name[i], v) 44 | } 45 | fmt.Printf("EIP = %08x\n", emu.Eip) 46 | 47 | } 48 | 49 | func main() { 50 | 51 | if len(os.Args) != 2 { 52 | fmt.Println("usage: ./px86 filename") 53 | return 54 | } 55 | 56 | emu := create_emu(uint32(0x7c00), uint32(0x7c00)) 57 | 58 | read_binary(emu, os.Args[1]) 59 | 60 | Init_instructions() 61 | 62 | for i := emu.Eip; i < MEMORY_SIZE; i++ { 63 | code := uint8(Get_code8(emu, 0)) 64 | fmt.Printf("EIP = %X, Code = %02X\n", emu.Eip, code) 65 | 66 | if Instructions[code] == nil { 67 | fmt.Printf("\n\nNot Implemented: %x\n", code) 68 | break 69 | } 70 | 71 | Instructions[code](emu) 72 | 73 | if emu.Eip == 0x00 { 74 | fmt.Printf("\n\nend of program.\n\n") 75 | break 76 | } 77 | 78 | } 79 | dump_registers(emu) 80 | } 81 | -------------------------------------------------------------------------------- /emu3.4/modrm/modrm.go: -------------------------------------------------------------------------------- 1 | package modrm 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | . "../emulator" 7 | . "../emulator_function" 8 | ) 9 | 10 | type ModRM struct { 11 | Mod uint8 12 | Rm uint8 13 | Opecode uint8 14 | Reg_index uint8 15 | Sib uint8 16 | Disp8 int8 17 | Disp32 uint32 18 | }; 19 | 20 | func Parse_modrm(emu *Emulator, modrm *ModRM) { 21 | 22 | var code uint8 23 | 24 | if emu == nil || modrm == nil { 25 | 26 | } 27 | 28 | code = uint8(Get_code8(emu, 0)) 29 | 30 | modrm.Mod = ((code & 0xc0) >> 6) 31 | modrm.Opecode = ((code & 0x38) >> 3) 32 | modrm.Reg_index = modrm.Opecode 33 | modrm.Rm = code & 0x7 34 | 35 | emu.Eip += 1 36 | 37 | if modrm.Mod != 3 && modrm.Rm == 4 { 38 | modrm.Sib = uint8(Get_code8(emu, 0)) 39 | emu.Eip += 1 40 | } 41 | 42 | if (modrm.Mod == 0 && modrm.Rm == 5) || modrm.Mod == 2 { 43 | modrm.Disp32 = uint32(Get_sign_code32(emu, 0)) 44 | modrm.Disp8 = int8(modrm.Disp8) 45 | emu.Eip += 4 46 | } else if modrm.Mod == 1 { 47 | modrm.Disp8 = int8(Get_sign_code8(emu, 0)) 48 | modrm.Disp32 = uint32(modrm.Disp8) 49 | emu.Eip += 1 50 | } 51 | } 52 | 53 | func Calc_memory_address(emu *Emulator, modrm *ModRM) (result uint32) { 54 | 55 | if modrm.Mod == 0 { 56 | if modrm.Rm == 4 { 57 | fmt.Println("not implemented ModRM mod = 0, rm = 4") 58 | os.Exit(0) 59 | } else if modrm.Rm == 5 { 60 | result = modrm.Disp32 61 | } else { 62 | result = uint32(Get_register32(emu, int(modrm.Rm))) 63 | } 64 | } else if modrm.Mod == 1 { 65 | if modrm.Rm == 4 { 66 | fmt.Println("not implemented ModRM mod = 2, rm = 4") 67 | os.Exit(0) 68 | } else { 69 | result = uint32(Get_register32(emu, int(modrm.Rm))) + modrm.Disp32 70 | } 71 | } else { 72 | fmt.Println("not implemented ModRM mod = 3") 73 | os.Exit(0) 74 | } 75 | return result 76 | } 77 | 78 | func Set_rm32(emu *Emulator, modrm *ModRM, value uint32) { 79 | if modrm.Mod == 3 { 80 | Set_register32(emu, uint32(modrm.Rm), value) 81 | } else { 82 | address := Calc_memory_address(emu, modrm) 83 | Set_memory32(emu, address, value) 84 | } 85 | } 86 | 87 | func Get_rm32(emu *Emulator, modrm *ModRM) (result uint32) { 88 | if modrm.Mod == 3 { 89 | result = Get_register32(emu, int(modrm.Rm)) 90 | } else { 91 | address := Calc_memory_address(emu, modrm) 92 | result = Get_memory32(emu, address) 93 | } 94 | return result 95 | } 96 | 97 | func Set_r32(emu *Emulator, modrm *ModRM, value uint32) { 98 | Set_register32(emu, uint32(modrm.Reg_index), value) 99 | } 100 | 101 | func Get_r32(emu *Emulator, modrm *ModRM) uint32 { 102 | return Get_register32(emu, int(modrm.Reg_index)) 103 | } 104 | -------------------------------------------------------------------------------- /emu3.7/emulator/emulator.go: -------------------------------------------------------------------------------- 1 | package emulator 2 | 3 | const MEMORY_SIZE = 1024 * 1024 4 | type Register int 5 | const ( 6 | EAX Register = iota 7 | ECX 8 | EDX 9 | EBX 10 | ESP 11 | EBP 12 | ESI 13 | EDI 14 | REGISTERS_COUNT 15 | ) 16 | 17 | type Emulator struct { 18 | Registers [REGISTERS_COUNT]uint32 19 | Eflags uint32 20 | Memory [MEMORY_SIZE]byte 21 | Eip uint32 22 | } 23 | -------------------------------------------------------------------------------- /emu3.7/emulator_function/emulator_function.go: -------------------------------------------------------------------------------- 1 | package emulator_function 2 | 3 | import ( 4 | . "../emulator" 5 | ) 6 | 7 | func Get_code8(emu *Emulator, index int) uint32{ 8 | return uint32(emu.Memory[int(emu.Eip) + index]) 9 | } 10 | 11 | func Get_sign_code8(emu *Emulator, index int) int32{ 12 | return int32(emu.Memory[int(emu.Eip) + index]) 13 | } 14 | 15 | func Get_code32(emu *Emulator, index int) (ret uint32) { 16 | var i uint 17 | for i = 0; i < 4; i++ { 18 | ret |= Get_code8(emu, index + int(i)) << (i * 8); 19 | } 20 | return ret; 21 | } 22 | 23 | func Get_sign_code32(emu *Emulator, index int) int32 { 24 | return int32(Get_code32(emu, index)) 25 | } 26 | 27 | func Get_register32(emu *Emulator, index int) uint32 { 28 | return emu.Registers[index] 29 | } 30 | 31 | func Set_register32(emu *Emulator, index uint32, value uint32) { 32 | emu.Registers[index] = value 33 | } 34 | 35 | func Set_memory8(emu *Emulator, address uint32, value uint32) { 36 | emu.Memory[address] = byte(value & 0xff) 37 | } 38 | 39 | func Set_memory32(emu *Emulator, address uint32, value uint32) { 40 | for i := 0; i < 4; i++ { 41 | Set_memory8(emu, address + uint32(i), value >> (uint(i) * 8)) 42 | } 43 | } 44 | 45 | func Get_memory8(emu *Emulator, address uint32) uint32 { 46 | return uint32(emu.Memory[address]) 47 | } 48 | 49 | func Get_memory32(emu *Emulator, address uint32) (ret uint32){ 50 | 51 | for i := 0; i < 4; i++ { 52 | ret |= Get_memory8(emu, address + uint32(i)) << (8 * uint32(i)) 53 | } 54 | return ret 55 | } 56 | 57 | 58 | func Push32(emu *Emulator, value uint32) { 59 | 60 | address := Get_register32(emu, int(ESP)) - 4 61 | Set_register32(emu, uint32(ESP), address) 62 | Set_memory32(emu, address, value) 63 | } 64 | 65 | func Pop32(emu *Emulator) (ret uint32) { 66 | 67 | address := Get_register32(emu, int(ESP)) 68 | ret = Get_memory32(emu, address) 69 | Set_register32(emu, uint32(ESP), address + 4) 70 | return ret 71 | 72 | } 73 | -------------------------------------------------------------------------------- /emu3.7/instruction/instruction.go: -------------------------------------------------------------------------------- 1 | package instruction 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | . "../emulator" 7 | . "../emulator_function" 8 | . "../modrm" 9 | ) 10 | 11 | type Instruction_func_t func(*Emulator) 12 | var Instructions = [256]Instruction_func_t{} 13 | 14 | func Mov_r32_imm32(emu *Emulator) { 15 | reg := Get_code8(emu, 0) - 0xb8; 16 | value := Get_code32(emu, 1); 17 | emu.Registers[reg] = value; 18 | emu.Eip += 5 19 | } 20 | 21 | func Mov_r32_rm32(emu *Emulator) { 22 | emu.Eip += 1 23 | var modrm ModRM 24 | Parse_modrm(emu, &modrm) 25 | rm32 := Get_rm32(emu, &modrm) 26 | Set_r32(emu, &modrm, rm32) 27 | } 28 | 29 | func Mov_rm32_r32(emu *Emulator) { 30 | emu.Eip += 1 31 | var modrm ModRM 32 | Parse_modrm(emu, &modrm) 33 | r32 := Get_r32(emu, &modrm) 34 | Set_rm32(emu, &modrm, r32) 35 | } 36 | 37 | func Push_r32(emu *Emulator) { 38 | reg := Get_code8(emu, 0) - 0x50 39 | Push32(emu, Get_register32(emu, int(reg))) 40 | emu.Eip += 1 41 | } 42 | 43 | func Push_imm32(emu *Emulator) { 44 | value := Get_code32(emu, 1) 45 | Push32(emu, value) 46 | emu.Eip += 5 47 | } 48 | 49 | func Push_imm8(emu *Emulator) { 50 | value := Get_code8(emu, 1) 51 | Push32(emu, value) 52 | emu.Eip += 2 53 | } 54 | 55 | func Pop_r32(emu *Emulator) { 56 | reg := Get_code8(emu, 0) - 0x58 57 | Set_register32(emu, reg, Pop32(emu)) 58 | emu.Eip += 1 59 | } 60 | 61 | func Mov_rm32_imm32(emu *Emulator) { 62 | emu.Eip += 1 63 | var modrm ModRM 64 | Parse_modrm(emu, &modrm) 65 | value := Get_code32(emu, 0) 66 | emu.Eip += 4 67 | Set_rm32(emu, &modrm, value) 68 | } 69 | 70 | func Sub_rm32_imm8(emu *Emulator, modrm *ModRM) { 71 | rm32 := int32(Get_rm32(emu, modrm)) 72 | imm8 := int32(Get_sign_code8(emu, 0)) 73 | emu.Eip += 1 74 | Set_rm32(emu, modrm, uint32(rm32 - imm8)) 75 | } 76 | 77 | func Code_83(emu *Emulator) { 78 | emu.Eip += 1 79 | var modrm ModRM 80 | Parse_modrm(emu, &modrm) 81 | 82 | switch modrm.Opecode { 83 | case 5: 84 | Sub_rm32_imm8(emu, &modrm) 85 | default: 86 | fmt.Printf("not implemented: 83 /%d\n", modrm.Opecode) 87 | os.Exit(1) 88 | } 89 | } 90 | 91 | func Inc_rm32(emu *Emulator, modrm *ModRM) { 92 | value := Get_rm32(emu, modrm) 93 | Set_rm32(emu, modrm, value + 1) 94 | } 95 | 96 | func Code_ff(emu *Emulator) { 97 | emu.Eip += 1 98 | var modrm ModRM 99 | Parse_modrm(emu, &modrm) 100 | 101 | switch modrm.Opecode { 102 | case 0: 103 | Inc_rm32(emu, &modrm); 104 | default: 105 | fmt.Printf("not implemented: FF /%d\n", modrm.Opecode) 106 | os.Exit(1) 107 | } 108 | } 109 | 110 | func Add_rm32_r32(emu *Emulator) { 111 | emu.Eip += 1 112 | var modrm ModRM 113 | Parse_modrm(emu, &modrm) 114 | r32 := Get_r32(emu, &modrm) 115 | rm32 := Get_rm32(emu, &modrm) 116 | Set_rm32(emu, &modrm, rm32 + r32) 117 | } 118 | 119 | func Call_rel32(emu *Emulator) { 120 | diff := Get_sign_code32(emu, 1) 121 | Push32(emu, emu.Eip + 5) 122 | emu.Eip += uint32(diff + 5) 123 | } 124 | 125 | func Ret(emu *Emulator) { 126 | emu.Eip = Pop32(emu) 127 | } 128 | 129 | func Leave(emu *Emulator) { 130 | ebp := Get_register32(emu, int(EBP)) 131 | Set_register32(emu, uint32(ESP), ebp) 132 | Set_register32(emu, uint32(EBP), Pop32(emu)) 133 | emu.Eip += 1 134 | } 135 | 136 | func Short_jump(emu *Emulator) { 137 | diff := int8(Get_sign_code8(emu, 1)) 138 | emu.Eip += uint32(diff + 2) 139 | } 140 | 141 | func Near_jump(emu *Emulator) { 142 | diff := Get_sign_code32(emu, 1) 143 | emu.Eip += uint32(diff + 5) 144 | } 145 | 146 | func Init_instructions() { 147 | 148 | Instructions[0x01] = Add_rm32_r32 149 | 150 | for i := 0; i < 8; i++ { 151 | Instructions[0x50 + i] = Push_r32 152 | } 153 | for i := 0; i < 8; i++ { 154 | Instructions[0x58 + i] = Pop_r32 155 | } 156 | 157 | Instructions[0x68] = Push_imm32 158 | Instructions[0x6a] = Push_imm8 159 | 160 | Instructions[0x83] = Code_83 161 | Instructions[0x89] = Mov_rm32_r32 162 | Instructions[0x8b] = Mov_r32_rm32 163 | 164 | // 0xb8 + regsiter number 165 | for i := 0; i < 8; i++ { 166 | Instructions[0xb8 + i] = Mov_r32_imm32 167 | } 168 | 169 | Instructions[0xc3] = Ret 170 | Instructions[0xc7] = Mov_rm32_imm32 171 | Instructions[0xc9] = Leave 172 | 173 | Instructions[0xe8] = Call_rel32 174 | Instructions[0xe9] = Near_jump 175 | Instructions[0xeb] = Short_jump 176 | 177 | Instructions[0xff] = Code_ff 178 | } 179 | -------------------------------------------------------------------------------- /emu3.7/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/owlinux1000/x86emulator/3c9b41424c9b340ec44076ef83786ba236f8f8a7/emu3.7/main -------------------------------------------------------------------------------- /emu3.7/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | . "./emulator" 7 | . "./instruction" 8 | . "./emulator_function" 9 | ) 10 | 11 | var registers_name = [8]string{"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"} 12 | 13 | func read_binary(emu *Emulator, filename string) { 14 | 15 | f, err := os.Open(filename) 16 | 17 | if err != nil { 18 | fmt.Printf("%sファイルが開けません\n", os.Args[1]) 19 | os.Exit(1) 20 | } 21 | 22 | buf := make([]byte, 0x200) 23 | n, _ := f.Read(buf) 24 | 25 | for i := 0; i < n; i++ { 26 | emu.Memory[i+0x7c00] = buf[i] 27 | } 28 | f.Close() 29 | } 30 | 31 | func create_emu(eip uint32, esp uint32) (emu *Emulator) { 32 | 33 | emu = &Emulator{} 34 | emu.Eip = eip 35 | emu.Registers[ESP] = esp 36 | 37 | return emu 38 | } 39 | 40 | func dump_registers(emu *Emulator) { 41 | 42 | for i, v := range emu.Registers { 43 | fmt.Printf("%s = %08x\n", registers_name[i], v) 44 | } 45 | 46 | fmt.Printf("EIP = %08x\n", emu.Eip) 47 | } 48 | 49 | func main() { 50 | 51 | if len(os.Args) != 2 { 52 | fmt.Println("usage: ./px86 filename") 53 | return 54 | } 55 | 56 | emu := create_emu(uint32(0x7c00), uint32(0x7c00)) 57 | 58 | read_binary(emu, os.Args[1]) 59 | 60 | Init_instructions() 61 | 62 | for i := emu.Eip; i < MEMORY_SIZE; i++ { 63 | 64 | code := uint8(Get_code8(emu, 0)) 65 | fmt.Printf("EIP = %X, Code = %02X\n", emu.Eip, code) 66 | 67 | if Instructions[code] == nil { 68 | fmt.Printf("\n\nNot Implemented: %x\n", code) 69 | break 70 | } 71 | 72 | Instructions[code](emu) 73 | 74 | if emu.Eip == 0x00 { 75 | fmt.Printf("\n\nend of program.\n\n") 76 | break 77 | } 78 | } 79 | dump_registers(emu) 80 | } 81 | -------------------------------------------------------------------------------- /emu3.7/modrm/modrm.go: -------------------------------------------------------------------------------- 1 | package modrm 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | . "../emulator" 7 | . "../emulator_function" 8 | ) 9 | 10 | type ModRM struct { 11 | Mod uint8 12 | Rm uint8 13 | Opecode uint8 14 | Reg_index uint8 15 | Sib uint8 16 | Disp8 int8 17 | Disp32 uint32 18 | }; 19 | 20 | func Parse_modrm(emu *Emulator, modrm *ModRM) { 21 | 22 | var code uint8 23 | 24 | if emu == nil || modrm == nil { 25 | 26 | } 27 | 28 | code = uint8(Get_code8(emu, 0)) 29 | 30 | modrm.Mod = ((code & 0xc0) >> 6) 31 | modrm.Opecode = ((code & 0x38) >> 3) 32 | modrm.Reg_index = modrm.Opecode 33 | modrm.Rm = code & 0x7 34 | 35 | emu.Eip += 1 36 | 37 | if modrm.Mod != 3 && modrm.Rm == 4 { 38 | modrm.Sib = uint8(Get_code8(emu, 0)) 39 | emu.Eip += 1 40 | } 41 | 42 | if (modrm.Mod == 0 && modrm.Rm == 5) || modrm.Mod == 2 { 43 | modrm.Disp32 = uint32(Get_sign_code32(emu, 0)) 44 | modrm.Disp8 = int8(modrm.Disp8) 45 | emu.Eip += 4 46 | } else if modrm.Mod == 1 { 47 | modrm.Disp8 = int8(Get_sign_code8(emu, 0)) 48 | modrm.Disp32 = uint32(modrm.Disp8) 49 | emu.Eip += 1 50 | } 51 | } 52 | 53 | func Calc_memory_address(emu *Emulator, modrm *ModRM) (result uint32) { 54 | 55 | if modrm.Mod == 0 { 56 | if modrm.Rm == 4 { 57 | fmt.Println("not implemented ModRM mod = 0, rm = 4") 58 | os.Exit(0) 59 | } else if modrm.Rm == 5 { 60 | result = modrm.Disp32 61 | } else { 62 | result = uint32(Get_register32(emu, int(modrm.Rm))) 63 | } 64 | } else if modrm.Mod == 1 { 65 | if modrm.Rm == 4 { 66 | fmt.Println("not implemented ModRM mod = 2, rm = 4") 67 | os.Exit(0) 68 | } else { 69 | result = uint32(Get_register32(emu, int(modrm.Rm))) + modrm.Disp32 70 | } 71 | } else { 72 | fmt.Println("not implemented ModRM mod = 3") 73 | os.Exit(0) 74 | } 75 | return result 76 | } 77 | 78 | func Set_rm32(emu *Emulator, modrm *ModRM, value uint32) { 79 | if modrm.Mod == 3 { 80 | Set_register32(emu, uint32(modrm.Rm), value) 81 | } else { 82 | address := Calc_memory_address(emu, modrm) 83 | Set_memory32(emu, address, value) 84 | } 85 | } 86 | 87 | func Get_rm32(emu *Emulator, modrm *ModRM) (result uint32) { 88 | if modrm.Mod == 3 { 89 | result = Get_register32(emu, int(modrm.Rm)) 90 | } else { 91 | address := Calc_memory_address(emu, modrm) 92 | result = Get_memory32(emu, address) 93 | } 94 | return result 95 | } 96 | 97 | func Set_r32(emu *Emulator, modrm *ModRM, value uint32) { 98 | Set_register32(emu, uint32(modrm.Reg_index), value) 99 | } 100 | 101 | func Get_r32(emu *Emulator, modrm *ModRM) uint32 { 102 | return Get_register32(emu, int(modrm.Reg_index)) 103 | } 104 | --------------------------------------------------------------------------------