summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xREADME.md8
-rwxr-xr-xassemble.go7
-rwxr-xr-xelf.go51
-rwxr-xr-xqdma.go152
-rwxr-xr-xsymbol.go5
5 files changed, 130 insertions, 93 deletions
diff --git a/README.md b/README.md
index e3335f3..d171d24 100755
--- a/README.md
+++ b/README.md
@@ -7,6 +7,14 @@ QDMA is a simple MIPS assembler written in Go for
emulator. QDMA implements a partial version of the Executable and Linkable
Format (ELF), [See Partial ELF for more information](#Partial-ELF).
+## Options
+
+- `-o output` set an output file name
+
+- `-b` Set byte order to big endian (default is native)
+
+- `-l` Set byte order to little endian (default is native)
+
## TODO
- ~Assemble Instructions into Binary~
diff --git a/assemble.go b/assemble.go
index 923fb33..9554080 100755
--- a/assemble.go
+++ b/assemble.go
@@ -2,7 +2,6 @@ package main
import (
"bufio"
- "encoding/binary"
"fmt"
"os"
"regexp"
@@ -91,10 +90,10 @@ func Encode(inst []string, pc int32) ([]byte, error) {
for _, s := range inst {
switch s {
case "syscall":
- binary.NativeEndian.PutUint32(bytes, 12)
+ byteOrder.PutUint32(bytes, 12)
return bytes, nil
case "nop":
- binary.NativeEndian.PutUint32(bytes, 0)
+ byteOrder.PutUint32(bytes, 0)
return bytes, nil
}
}
@@ -177,7 +176,7 @@ func Encode(inst []string, pc int32) ([]byte, error) {
(RegNums[inst[1]] << 16) | (0xFFFF & uint32(imm))
}
fmt.Println(inst)
- binary.NativeEndian.PutUint32(bytes, ret)
+ byteOrder.PutUint32(bytes, ret)
return bytes, nil
}
diff --git a/elf.go b/elf.go
index ea90180..7030c96 100755
--- a/elf.go
+++ b/elf.go
@@ -60,11 +60,18 @@ func EHInit(e_entry uint32, e_phnum uint16) ElfHeader {
var e ElfHeader
e.e_ident = [EI_NIDENT]byte{0x7f, 0x45, 0x4c, 0x46, // ELF magic number
0x01, // 32-bit format
- 0x01, // Little Endian
+ 0x00, // Endian
0x01, // ELF Version
0x00, // Target OS
0x00, // Target ABI
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // Padding
+
+ if byteOrder == binary.BigEndian {
+ e.e_ident[5] = 0x02
+ } else {
+ e.e_ident[5] = 0x01
+ }
+
e.e_type = ET_EXEC
e.e_machine = MIPS
e.e_version = 0x01
@@ -95,31 +102,31 @@ func (e *ElfHeader) ToBytes() []byte {
bytes[i] = b
i++
}
- binary.NativeEndian.PutUint16(bytes[EI_NIDENT:], e.e_type)
- binary.NativeEndian.PutUint16(bytes[18:], e.e_machine)
- binary.NativeEndian.PutUint32(bytes[20:], e.e_version)
- binary.NativeEndian.PutUint32(bytes[24:], e.e_entry)
- binary.NativeEndian.PutUint32(bytes[28:], e.e_phoff)
- binary.NativeEndian.PutUint32(bytes[32:], e.e_shoff)
- binary.NativeEndian.PutUint32(bytes[36:], e.e_flags)
- binary.NativeEndian.PutUint16(bytes[40:], e.e_ehsize)
- binary.NativeEndian.PutUint16(bytes[42:], e.e_phentsize)
- binary.NativeEndian.PutUint16(bytes[44:], e.e_phnum)
- binary.NativeEndian.PutUint16(bytes[46:], e.e_shentsize)
- binary.NativeEndian.PutUint16(bytes[48:], e.e_shnum)
- binary.NativeEndian.PutUint16(bytes[50:], e.e_shstrndx)
+ byteOrder.PutUint16(bytes[EI_NIDENT:], e.e_type)
+ byteOrder.PutUint16(bytes[18:], e.e_machine)
+ byteOrder.PutUint32(bytes[20:], e.e_version)
+ byteOrder.PutUint32(bytes[24:], e.e_entry)
+ byteOrder.PutUint32(bytes[28:], e.e_phoff)
+ byteOrder.PutUint32(bytes[32:], e.e_shoff)
+ byteOrder.PutUint32(bytes[36:], e.e_flags)
+ byteOrder.PutUint16(bytes[40:], e.e_ehsize)
+ byteOrder.PutUint16(bytes[42:], e.e_phentsize)
+ byteOrder.PutUint16(bytes[44:], e.e_phnum)
+ byteOrder.PutUint16(bytes[46:], e.e_shentsize)
+ byteOrder.PutUint16(bytes[48:], e.e_shnum)
+ byteOrder.PutUint16(bytes[50:], e.e_shstrndx)
return bytes
}
func (p *ProgramHeader) ToBytes() []byte {
bytes := make([]byte, PHENSIZE)
- binary.NativeEndian.PutUint32(bytes[0:], p.ptype)
- binary.NativeEndian.PutUint32(bytes[4:], p.offset)
- binary.NativeEndian.PutUint32(bytes[8:], p.vaddr)
- binary.NativeEndian.PutUint32(bytes[12:], p.paddr)
- binary.NativeEndian.PutUint32(bytes[16:], p.filesz)
- binary.NativeEndian.PutUint32(bytes[20:], p.memsz)
- binary.NativeEndian.PutUint32(bytes[24:], p.flags)
- binary.NativeEndian.PutUint32(bytes[28:], p.align)
+ byteOrder.PutUint32(bytes[0:], p.ptype)
+ byteOrder.PutUint32(bytes[4:], p.offset)
+ byteOrder.PutUint32(bytes[8:], p.vaddr)
+ byteOrder.PutUint32(bytes[12:], p.paddr)
+ byteOrder.PutUint32(bytes[16:], p.filesz)
+ byteOrder.PutUint32(bytes[20:], p.memsz)
+ byteOrder.PutUint32(bytes[24:], p.flags)
+ byteOrder.PutUint32(bytes[28:], p.align)
return bytes
}
diff --git a/qdma.go b/qdma.go
index 3b08aba..316c901 100755
--- a/qdma.go
+++ b/qdma.go
@@ -1,84 +1,108 @@
package main
import (
+ "encoding/binary"
"os"
- "strings"
)
-func main() {
- for _, arg := range os.Args[1:] {
- tempData, err := os.CreateTemp("", "data*")
- Check(err)
- dName := tempData.Name()
- defer os.Remove(dName)
+type PathPair struct {
+ input string
+ output string
+}
- tempRoData, err := os.CreateTemp("", "rodata*")
- Check(err)
- rName := tempRoData.Name()
- defer os.Remove(rName)
+var byteOrder binary.ByteOrder = binary.NativeEndian
- tempText, err := os.CreateTemp("", "text*")
- Check(err)
- tName := tempText.Name()
- defer os.Remove(tName)
-
- // First pass to find the address of all labels and encode the data
- LabelFind(arg, tempData, tempRoData)
-
- var names [3]string
- var PHeaders [4]ProgramHeader
- i := 0
- n := 0
-
- if SectionPos[TEXT] > 0 {
- PHeaders[i] = ProgramHeader{PT_LOAD, 0, 0, 0,
- uint32(SectionPos[TEXT]), uint32(SectionPos[TEXT]), PF_READ +
- PF_EXEC, 0}
- names[i] = tName
- i++
- n++
- // Second pass to assemble the instructions.
- Assemble(arg, tempText)
+func main() {
+ var inputFiles []PathPair
+ for i, arg := range os.Args[1:] {
+ switch arg {
+ case "-b":
+ byteOrder = binary.BigEndian
+ case "-l":
+ byteOrder = binary.LittleEndian
+ case "-o":
+ inputFiles = append(inputFiles, PathPair{os.Args[i+3], os.Args[i+2]})
}
+ }
- if SectionPos[DATA] > 0 {
- PHeaders[i] = ProgramHeader{PT_LOAD, 0, 0, 0,
- uint32(SectionPos[DATA]), uint32(SectionPos[DATA]), PF_READ +
- PF_WRITE, 0}
- names[i] = dName
- i++
- n++
- }
+ for _, p := range inputFiles {
+ AssembleFile(p)
+ }
+}
- if SectionPos[RODATA] > 0 {
- PHeaders[i] = ProgramHeader{PT_LOAD, 0, 0, 0,
- uint32(SectionPos[RODATA]), uint32(SectionPos[RODATA]), PF_READ, 0}
- names[i] = rName
- i++
- n++
- }
+func AssembleFile(path PathPair) {
+ tempData, err := os.CreateTemp("", "data*")
+ Check(err)
+ dName := tempData.Name()
+ defer os.Remove(dName)
- if SectionPos[BSS] > 0 {
- PHeaders[i] = ProgramHeader{PT_LOAD, 0, 0, 0, 0,
- uint32(SectionPos[BSS]), PF_READ + PF_WRITE, 0}
- i++
- }
+ tempRoData, err := os.CreateTemp("", "rodata*")
+ Check(err)
+ rName := tempRoData.Name()
+ defer os.Remove(rName)
- var fOffset, mOffset uint32 = 0, 0
- for j, p := range PHeaders[:i] {
- PHeaders[j].offset = uint32(i*PHENSIZE) + fOffset + EHSIZE
- fOffset += p.filesz
- PHeaders[j].vaddr = mOffset
- mOffset += p.memsz
- }
+ tempText, err := os.CreateTemp("", "text*")
+ Check(err)
+ tName := tempText.Name()
+ defer os.Remove(tName)
+
+ // First pass to find the address of all labels and encode the data
+ LabelFind(path.input, tempData, tempRoData)
+
+ var names [3]string
+ var PHeaders [4]ProgramHeader
+ i := 0
+ n := 0
+
+ if SectionPos[TEXT] > 0 {
+ PHeaders[i] = ProgramHeader{PT_LOAD, 0, 0, 0,
+ uint32(SectionPos[TEXT]), uint32(SectionPos[TEXT]), PF_READ +
+ PF_EXEC, 0}
+ names[i] = tName
+ i++
+ n++
+ // Second pass to assemble the instructions.
+ Assemble(path.input, tempText)
+ }
+
+ if SectionPos[DATA] > 0 {
+ PHeaders[i] = ProgramHeader{PT_LOAD, 0, 0, 0,
+ uint32(SectionPos[DATA]), uint32(SectionPos[DATA]), PF_READ +
+ PF_WRITE, 0}
+ names[i] = dName
+ i++
+ n++
+ }
+
+ if SectionPos[RODATA] > 0 {
+ PHeaders[i] = ProgramHeader{PT_LOAD, 0, 0, 0,
+ uint32(SectionPos[RODATA]), uint32(SectionPos[RODATA]), PF_READ, 0}
+ names[i] = rName
+ i++
+ n++
+ }
- EHeader := EHInit(0, uint16(i))
- WriteBinary(arg, EHeader, PHeaders[:i], names[:n])
+ if SectionPos[BSS] > 0 {
+ PHeaders[i] = ProgramHeader{PT_LOAD, 0, 0, 0, 0,
+ uint32(SectionPos[BSS]), PF_READ + PF_WRITE, 0}
+ i++
}
+
+ var fOffset, mOffset uint32 = 0, 0
+ for j, p := range PHeaders[:i] {
+ PHeaders[j].offset = uint32(i*PHENSIZE) + fOffset + EHSIZE
+ fOffset += p.filesz
+ PHeaders[j].vaddr = mOffset
+ mOffset += p.memsz
+ }
+
+ EHeader := EHInit(0, uint16(i))
+ WriteBinary(path, EHeader, PHeaders[:i], names[:n])
+
}
-func WriteBinary(path string, e ElfHeader, ps []ProgramHeader, ns []string) {
- out, err := os.Create(strings.ReplaceAll(path, ".asm", ".bin"))
+func WriteBinary(path PathPair, e ElfHeader, ps []ProgramHeader, ns []string) {
+ out, err := os.Create(path.output)
Check(err)
defer out.Close()
_, err = out.Write(e.ToBytes())
diff --git a/symbol.go b/symbol.go
index 98c5f07..0e8e485 100755
--- a/symbol.go
+++ b/symbol.go
@@ -2,7 +2,6 @@ package main
import (
"bufio"
- "encoding/binary"
"os"
"regexp"
"strconv"
@@ -170,9 +169,9 @@ func EncodeData(line []string) ([]byte, error) {
case 1:
bytes[0] = uint8(data)
case 2:
- binary.NativeEndian.PutUint16(bytes, uint16(data))
+ byteOrder.PutUint16(bytes, uint16(data))
case 4:
- binary.NativeEndian.PutUint32(bytes, uint32(data))
+ byteOrder.PutUint32(bytes, uint32(data))
}
} else if isString {
if nullTerm {