Implemented instruction lists
This commit is contained in:
23
src/asm/Base.go
Normal file
23
src/asm/Base.go
Normal file
@ -0,0 +1,23 @@
|
||||
package asm
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/asm/x64"
|
||||
)
|
||||
|
||||
// Base represents the data that is common among all instructions.
|
||||
type Base struct {
|
||||
Mnemonic Mnemonic
|
||||
}
|
||||
|
||||
func (x *Base) Write(w io.ByteWriter) {
|
||||
switch x.Mnemonic {
|
||||
case SYSCALL:
|
||||
x64.Syscall(w)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Base) String() string {
|
||||
return x.Mnemonic.String()
|
||||
}
|
8
src/asm/Instruction.go
Normal file
8
src/asm/Instruction.go
Normal file
@ -0,0 +1,8 @@
|
||||
package asm
|
||||
|
||||
import "io"
|
||||
|
||||
type Instruction interface {
|
||||
Write(io.ByteWriter)
|
||||
String() string
|
||||
}
|
47
src/asm/InstructionList.go
Normal file
47
src/asm/InstructionList.go
Normal file
@ -0,0 +1,47 @@
|
||||
package asm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/register"
|
||||
)
|
||||
|
||||
type InstructionList struct {
|
||||
Instructions []Instruction
|
||||
}
|
||||
|
||||
// Finalize generates the final assembly code.
|
||||
func (list *InstructionList) Finalize() *Result {
|
||||
final := Result{}
|
||||
|
||||
for _, instr := range list.Instructions {
|
||||
instr.Write(&final.Code)
|
||||
fmt.Println(instr.String())
|
||||
}
|
||||
|
||||
return &final
|
||||
}
|
||||
|
||||
func (list *InstructionList) MoveRegisterNumber(reg register.Register, number uint64) {
|
||||
list.addRegisterNumber(MOV, reg, number)
|
||||
}
|
||||
|
||||
func (list *InstructionList) Syscall() {
|
||||
list.add(SYSCALL)
|
||||
}
|
||||
|
||||
// add adds an instruction without any operands.
|
||||
func (list *InstructionList) add(mnemonic Mnemonic) {
|
||||
list.Instructions = append(list.Instructions, &Base{Mnemonic: mnemonic})
|
||||
}
|
||||
|
||||
// addRegisterNumber adds an instruction using a register and a number.
|
||||
func (list *InstructionList) addRegisterNumber(mnemonic Mnemonic, reg register.Register, number uint64) {
|
||||
list.Instructions = append(list.Instructions, &RegisterNumber{
|
||||
Base: Base{
|
||||
Mnemonic: mnemonic,
|
||||
},
|
||||
Register: reg,
|
||||
Number: number,
|
||||
})
|
||||
}
|
21
src/asm/Mnemonic.go
Normal file
21
src/asm/Mnemonic.go
Normal file
@ -0,0 +1,21 @@
|
||||
package asm
|
||||
|
||||
type Mnemonic uint8
|
||||
|
||||
const (
|
||||
NONE Mnemonic = iota
|
||||
MOV
|
||||
SYSCALL
|
||||
)
|
||||
|
||||
func (m Mnemonic) String() string {
|
||||
switch m {
|
||||
case MOV:
|
||||
return "mov"
|
||||
|
||||
case SYSCALL:
|
||||
return "syscall"
|
||||
}
|
||||
|
||||
return "NONE"
|
||||
}
|
26
src/asm/RegisterNumber.go
Normal file
26
src/asm/RegisterNumber.go
Normal file
@ -0,0 +1,26 @@
|
||||
package asm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/asm/x64"
|
||||
"git.akyoto.dev/cli/q/src/register"
|
||||
)
|
||||
|
||||
type RegisterNumber struct {
|
||||
Base
|
||||
Register register.Register
|
||||
Number uint64
|
||||
}
|
||||
|
||||
func (x *RegisterNumber) Write(w io.ByteWriter) {
|
||||
switch x.Mnemonic {
|
||||
case MOV:
|
||||
x64.MoveRegNum32(w, uint8(x.Register), uint32(x.Number))
|
||||
}
|
||||
}
|
||||
|
||||
func (x *RegisterNumber) String() string {
|
||||
return fmt.Sprintf("%s %s, %x", x.Mnemonic, x.Register, x.Number)
|
||||
}
|
@ -2,7 +2,7 @@ package asm
|
||||
|
||||
import "bytes"
|
||||
|
||||
type Assembler struct {
|
||||
type Result struct {
|
||||
Code bytes.Buffer
|
||||
Data bytes.Buffer
|
||||
}
|
@ -2,7 +2,7 @@ package x64
|
||||
|
||||
import "io"
|
||||
|
||||
// AppendUint32 appends a 32 bit number in Little Endian to the given writer.
|
||||
// AppendUint32 appends a 32 bit integer in Little Endian to the given writer.
|
||||
func AppendUint32(w io.ByteWriter, number uint32) {
|
||||
w.WriteByte(byte(number))
|
||||
w.WriteByte(byte(number >> 8))
|
||||
|
@ -4,7 +4,8 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
func MoveRegNum32(w io.ByteWriter, register byte, number uint32) {
|
||||
// MoveRegNum32 moves a 32 bit integer into the given register.
|
||||
func MoveRegNum32(w io.ByteWriter, register uint8, number uint32) {
|
||||
w.WriteByte(0xb8 + register)
|
||||
AppendUint32(w, number)
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Syscall is the primary way to communicate with the OS kernel.
|
||||
func Syscall(w io.ByteWriter) {
|
||||
w.WriteByte(0x0f)
|
||||
w.WriteByte(0x05)
|
||||
|
Reference in New Issue
Block a user