Skip to content

twitchyliquid64/golang-asm

Repository files navigation

golang-asm

A mirror of the assembler from the Go compiler, with import paths re-written for the assembler to be functional as a standalone library.

License as per the Go project.

Status

Works, but expect to dig into the assembler godoc's to work out what to set different parameters of obj.Prog to get it to generate specific instructions.

Example

Demonstrates assembly of a NOP & an ADD instruction on x86-64.

package main

import (
	"fmt"

	asm "github.com/twitchyliquid64/golang-asm"
	"github.com/twitchyliquid64/golang-asm/obj"
	"github.com/twitchyliquid64/golang-asm/obj/x86"
)

func noop(builder *asm.Builder) *obj.Prog {
	prog := builder.NewProg()
	prog.As = x86.ANOPL
	prog.From.Type = obj.TYPE_REG
	prog.From.Reg = x86.REG_AX
	return prog
}

func addImmediateByte(builder *asm.Builder, in int32) *obj.Prog {
	prog := builder.NewProg()
	prog.As = x86.AADDB
	prog.To.Type = obj.TYPE_REG
	prog.To.Reg = x86.REG_AL
	prog.From.Type = obj.TYPE_CONST
	prog.From.Offset = int64(in)
	return prog
}

func movImmediateByte(builder *asm.Builder, reg int16, in int32) *obj.Prog {
	prog := builder.NewProg()
	prog.As = x86.AMOVB
	prog.To.Type = obj.TYPE_REG
	prog.To.Reg = reg
	prog.From.Type = obj.TYPE_CONST
	prog.From.Offset = int64(in)
	return prog
}

func main() {
	b, _ := asm.NewBuilder("amd64", 64)
	b.AddInstruction(noop(b))
	b.AddInstruction(movImmediateByte(b, x86.REG_AL, 16))
	b.AddInstruction(addImmediateByte(b, 16))
	fmt.Printf("Bin: %x\n", b.Assemble())
}

Working out the parameters of obj.Prog

This took me some time to work out, so I'll write a bit here.

Use these references

Instruction constants have a naming scheme

Instructions are defined as constants in the package for the relavant architecture, and have an 'A' prefix and a size suffix.

For example, the MOV instruction for 64 bits of data is AMOVQ (well, at least in amd64).

Search the go source for usage of a given instruction

For example, if I wanted to work out how to emit the MOV instruction for 64bits, I would search the go source on github for AMOVQ or x86.AMOVQ. Normally, you see find a few examples where the compiler backend fills in a obj.Prog structure, and you follow it's lead.

About

The assembler from the Go compiler, in library form.

Resources

License

Stars

Watchers

Forks

Packages

No packages published