diff --git a/lib/sys/sys_linux_arm.q b/lib/sys/sys_linux_arm.q
new file mode 100644
index 0000000..cfc351e
--- /dev/null
+++ b/lib/sys/sys_linux_arm.q
@@ -0,0 +1,15 @@
+read(fd int, buffer *byte, length int) -> int {
+	return syscall(63, fd, buffer, length)
+}
+
+write(fd int, buffer *byte, length int) -> int {
+	return syscall(64, fd, buffer, length)
+}
+
+mmap(address int, length uint, protection int, flags int) -> *any {
+	return syscall(222, address, length, protection, flags)
+}
+
+munmap(address *any, length uint) -> int {
+	return syscall(215, address, length)
+}
\ No newline at end of file
diff --git a/lib/sys/sys_linux.q b/lib/sys/sys_linux_x86.q
similarity index 100%
rename from lib/sys/sys_linux.q
rename to lib/sys/sys_linux_x86.q
diff --git a/src/arm/Call.go b/src/arm/Call.go
index 5122e02..8c1901f 100644
--- a/src/arm/Call.go
+++ b/src/arm/Call.go
@@ -1,15 +1,8 @@
 package arm
 
-import "encoding/binary"
-
 // Call branches to a PC-relative offset, setting the register X30 to PC+4.
 // The offset starts from the address of this instruction and is encoded as "imm26" times 4.
 // This instruction is also known as BL (branch with link).
-func Call(code []byte, offset uint32) []byte {
-	return binary.LittleEndian.AppendUint32(code, EncodeCall(offset))
-}
-
-// EncodeCall returns the raw encoding of a call with the given offset.
-func EncodeCall(offset uint32) uint32 {
+func Call(offset uint32) uint32 {
 	return uint32(0b100101<<26) | offset
 }
diff --git a/src/arm/Load.go b/src/arm/Load.go
new file mode 100644
index 0000000..e1d09e1
--- /dev/null
+++ b/src/arm/Load.go
@@ -0,0 +1,13 @@
+package arm
+
+import "git.urbach.dev/cli/q/src/cpu"
+
+// LoadRegister loads from memory into a register.
+func LoadRegister(destination cpu.Register, base cpu.Register, offset int16, length byte) uint32 {
+	if offset < 0 {
+		offset &= 0xFF
+		offset |= 1 << 8
+	}
+
+	return 0b11111000010<<21 | uint32(offset)<<12 | uint32(base)<<5 | uint32(destination)
+}
diff --git a/src/arm/LoadAddress.go b/src/arm/LoadAddress.go
new file mode 100644
index 0000000..00284f5
--- /dev/null
+++ b/src/arm/LoadAddress.go
@@ -0,0 +1,10 @@
+package arm
+
+import "git.urbach.dev/cli/q/src/cpu"
+
+// LoadAddress calculates the address with the PC-relative offset and writes the result to the destination register.
+func LoadAddress(destination cpu.Register, offset int) uint32 {
+	hi := uint32(offset) >> 2
+	lo := uint32(offset) & 0b11
+	return lo<<29 | 0b10000<<24 | hi<<5 | uint32(destination)
+}
diff --git a/src/arm/LoadAddress_test.go b/src/arm/LoadAddress_test.go
new file mode 100644
index 0000000..3b3c05f
--- /dev/null
+++ b/src/arm/LoadAddress_test.go
@@ -0,0 +1,26 @@
+package arm_test
+
+import (
+	"testing"
+
+	"git.urbach.dev/cli/q/src/arm"
+	"git.urbach.dev/cli/q/src/cpu"
+	"git.urbach.dev/go/assert"
+)
+
+func TestLoadAddress(t *testing.T) {
+	usagePatterns := []struct {
+		Destination cpu.Register
+		Number      int
+		Code        uint32
+	}{
+		{arm.X0, 56, 0x100001C0},
+		{arm.X1, 80, 0x10000281},
+	}
+
+	for _, pattern := range usagePatterns {
+		t.Logf("adr %s, %d", pattern.Destination, pattern.Number)
+		code := arm.LoadAddress(pattern.Destination, pattern.Number)
+		assert.DeepEqual(t, code, pattern.Code)
+	}
+}
diff --git a/src/arm/Load_test.go b/src/arm/Load_test.go
new file mode 100644
index 0000000..c04f60a
--- /dev/null
+++ b/src/arm/Load_test.go
@@ -0,0 +1,31 @@
+package arm_test
+
+import (
+	"testing"
+
+	"git.urbach.dev/cli/q/src/arm"
+	"git.urbach.dev/cli/q/src/cpu"
+	"git.urbach.dev/go/assert"
+)
+
+func TestLoadRegister(t *testing.T) {
+	usagePatterns := []struct {
+		Destination cpu.Register
+		Base        cpu.Register
+		Offset      int16
+		Length      byte
+		Code        uint32
+	}{
+		{arm.X2, arm.X1, -8, 8, 0xF85F8022},
+		{arm.X2, arm.X1, 0, 8, 0xF8400022},
+		{arm.X2, arm.X1, 8, 8, 0xF8408022},
+		{arm.X2, arm.X1, -256, 8, 0xF8500022},
+		{arm.X2, arm.X1, 255, 8, 0xF84FF022},
+	}
+
+	for _, pattern := range usagePatterns {
+		t.Logf("ldur %s, [%s, %d] %db", pattern.Destination, pattern.Base, pattern.Offset, pattern.Length)
+		code := arm.LoadRegister(pattern.Destination, pattern.Base, pattern.Offset, pattern.Length)
+		assert.DeepEqual(t, code, pattern.Code)
+	}
+}
diff --git a/src/arm/Move.go b/src/arm/Move.go
index f26744f..e61ff8f 100644
--- a/src/arm/Move.go
+++ b/src/arm/Move.go
@@ -1,26 +1,27 @@
 package arm
 
 import (
-	"encoding/binary"
-
 	"git.urbach.dev/cli/q/src/cpu"
 )
 
+// MoveRegisterRegister copies a register to another register.
+func MoveRegisterRegister(destination cpu.Register, source cpu.Register) uint32 {
+	return 0b10101010<<24 | uint32(source)<<16 | 0b11111<<5 | uint32(destination)
+}
+
 // MoveRegisterNumber moves an integer into the given register.
-func MoveRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
-	return MoveZero(code, destination, 0, uint16(number))
+func MoveRegisterNumber(destination cpu.Register, number int) uint32 {
+	return MoveZero(destination, 0, uint16(number))
 }
 
 // MoveKeep moves a 16-bit integer into the given register and keeps all other bits.
-func MoveKeep(code []byte, destination cpu.Register, halfword int, number uint16) []byte {
-	x := mov(0b11, halfword, number, destination)
-	return binary.LittleEndian.AppendUint32(code, x)
+func MoveKeep(destination cpu.Register, halfword int, number uint16) uint32 {
+	return mov(0b11, halfword, number, destination)
 }
 
 // MoveZero moves a 16-bit integer into the given register and clears all other bits to zero.
-func MoveZero(code []byte, destination cpu.Register, halfword int, number uint16) []byte {
-	x := mov(0b10, halfword, number, destination)
-	return binary.LittleEndian.AppendUint32(code, x)
+func MoveZero(destination cpu.Register, halfword int, number uint16) uint32 {
+	return mov(0b10, halfword, number, destination)
 }
 
 // mov encodes a generic move instruction.
diff --git a/src/arm/Move_test.go b/src/arm/Move_test.go
index fb7f7d3..9811e37 100644
--- a/src/arm/Move_test.go
+++ b/src/arm/Move_test.go
@@ -8,19 +8,36 @@ import (
 	"git.urbach.dev/go/assert"
 )
 
+func TestMoveRegisterRegister(t *testing.T) {
+	usagePatterns := []struct {
+		Destination cpu.Register
+		Source      cpu.Register
+		Code        uint32
+	}{
+		{arm.X0, arm.X1, 0xAA0103E0},
+		{arm.X1, arm.X0, 0xAA0003E1},
+	}
+
+	for _, pattern := range usagePatterns {
+		t.Logf("mov %s, %s", pattern.Destination, pattern.Source)
+		code := arm.MoveRegisterRegister(pattern.Destination, pattern.Source)
+		assert.DeepEqual(t, code, pattern.Code)
+	}
+}
+
 func TestMoveKeep(t *testing.T) {
 	usagePatterns := []struct {
 		Register cpu.Register
 		Number   uint16
-		Code     []byte
+		Code     uint32
 	}{
-		{arm.X0, 0, []byte{0x00, 0x00, 0x80, 0xF2}},
-		{arm.X0, 1, []byte{0x20, 0x00, 0x80, 0xF2}},
+		{arm.X0, 0, 0xF2800000},
+		{arm.X0, 1, 0xF2800020},
 	}
 
 	for _, pattern := range usagePatterns {
 		t.Logf("movk %s, %x", pattern.Register, pattern.Number)
-		code := arm.MoveKeep(nil, pattern.Register, 0, pattern.Number)
+		code := arm.MoveKeep(pattern.Register, 0, pattern.Number)
 		assert.DeepEqual(t, code, pattern.Code)
 	}
 }
@@ -29,15 +46,15 @@ func TestMoveZero(t *testing.T) {
 	usagePatterns := []struct {
 		Register cpu.Register
 		Number   uint16
-		Code     []byte
+		Code     uint32
 	}{
-		{arm.X0, 0, []byte{0x00, 0x00, 0x80, 0xD2}},
-		{arm.X0, 1, []byte{0x20, 0x00, 0x80, 0xD2}},
+		{arm.X0, 0, 0xD2800000},
+		{arm.X0, 1, 0xD2800020},
 	}
 
 	for _, pattern := range usagePatterns {
 		t.Logf("movz %s, %x", pattern.Register, pattern.Number)
-		code := arm.MoveZero(nil, pattern.Register, 0, pattern.Number)
+		code := arm.MoveZero(pattern.Register, 0, pattern.Number)
 		assert.DeepEqual(t, code, pattern.Code)
 	}
 }
diff --git a/src/arm/Nop.go b/src/arm/Nop.go
index 8152293..6f518f4 100644
--- a/src/arm/Nop.go
+++ b/src/arm/Nop.go
@@ -1,6 +1,6 @@
 package arm
 
 // Nop does nothing. This can be used for alignment purposes.
-func Nop(code []byte) []byte {
-	return append(code, 0x1F, 0x20, 0x03, 0xD5)
+func Nop() uint32 {
+	return 0xD503201F
 }
diff --git a/src/arm/Return.go b/src/arm/Return.go
index b98c038..898c6e7 100644
--- a/src/arm/Return.go
+++ b/src/arm/Return.go
@@ -1,6 +1,6 @@
 package arm
 
 // Return transfers program control to the caller.
-func Return(code []byte) []byte {
-	return append(code, 0xC0, 0x03, 0x5F, 0xD6)
+func Return() uint32 {
+	return 0xD65F03C0
 }
diff --git a/src/arm/Syscall.go b/src/arm/Syscall.go
index 2792926..e9227d6 100644
--- a/src/arm/Syscall.go
+++ b/src/arm/Syscall.go
@@ -1,6 +1,6 @@
 package arm
 
 // Syscall is the primary way to communicate with the OS kernel.
-func Syscall(code []byte) []byte {
-	return append(code, 0x01, 0x00, 0x00, 0xD4)
+func Syscall() uint32 {
+	return 0xD4000001
 }
diff --git a/src/arm/arm_test.go b/src/arm/arm_test.go
index b4918fc..948f869 100644
--- a/src/arm/arm_test.go
+++ b/src/arm/arm_test.go
@@ -8,9 +8,9 @@ import (
 )
 
 func TestARM(t *testing.T) {
-	assert.DeepEqual(t, arm.Call(nil, 0), []byte{0x00, 0x00, 0x00, 0x94})
-	assert.DeepEqual(t, arm.MoveRegisterNumber(nil, arm.X0, 42), arm.MoveZero(nil, arm.X0, 0, 42))
-	assert.DeepEqual(t, arm.Nop(nil), []byte{0x1F, 0x20, 0x03, 0xD5})
-	assert.DeepEqual(t, arm.Return(nil), []byte{0xC0, 0x03, 0x5F, 0xD6})
-	assert.DeepEqual(t, arm.Syscall(nil), []byte{0x01, 0x00, 0x00, 0xD4})
+	assert.DeepEqual(t, arm.Call(0), 0x94000000)
+	assert.DeepEqual(t, arm.MoveRegisterNumber(arm.X0, 42), arm.MoveZero(arm.X0, 0, 42))
+	assert.DeepEqual(t, arm.Nop(), 0xD503201F)
+	assert.DeepEqual(t, arm.Return(), 0xD65F03C0)
+	assert.DeepEqual(t, arm.Syscall(), 0xD4000001)
 }
diff --git a/src/asm/CanSkipReturn.go b/src/asm/CanSkipReturn.go
index 0ce31cb..56e5096 100644
--- a/src/asm/CanSkipReturn.go
+++ b/src/asm/CanSkipReturn.go
@@ -6,11 +6,19 @@ func (a *Assembler) CanSkipReturn() bool {
 		return false
 	}
 
-	lastMnemonic := a.Instructions[len(a.Instructions)-1].Mnemonic
+	last := a.Instructions[len(a.Instructions)-1]
 
-	if lastMnemonic == RETURN || lastMnemonic == JUMP {
+	if last.Mnemonic == RETURN || last.Mnemonic == JUMP {
 		return true
 	}
 
+	if last.Mnemonic == CALL {
+		label, isLabel := last.Data.(*Label)
+
+		if isLabel && label.String() == "core.exit" {
+			return true
+		}
+	}
+
 	return false
 }
diff --git a/src/asmc/Finalize.go b/src/asmc/Finalize.go
index 2619905..708f207 100644
--- a/src/asmc/Finalize.go
+++ b/src/asmc/Finalize.go
@@ -1,7 +1,6 @@
 package asmc
 
 import (
-	"git.urbach.dev/cli/q/src/arm"
 	"git.urbach.dev/cli/q/src/asm"
 	"git.urbach.dev/cli/q/src/config"
 	"git.urbach.dev/cli/q/src/dll"
@@ -31,10 +30,6 @@ func Finalize(a asm.Assembler, dlls dll.List) ([]byte, []byte) {
 			c.compileARM(x)
 		}
 
-		c.code = arm.MoveRegisterNumber(c.code, arm.X0, 0)
-		c.code = arm.MoveRegisterNumber(c.code, arm.X8, 0x5D)
-		c.code = arm.Syscall(c.code)
-
 	case config.X86:
 		for _, x := range a.Instructions {
 			c.compileX86(x)
diff --git a/src/asmc/compileARM.go b/src/asmc/compileARM.go
index 06c2417..058f1f0 100644
--- a/src/asmc/compileARM.go
+++ b/src/asmc/compileARM.go
@@ -1,7 +1,10 @@
 package asmc
 
 import (
+	"encoding/binary"
 	"fmt"
+	"math"
+	"strings"
 
 	"git.urbach.dev/cli/q/src/arm"
 	"git.urbach.dev/cli/q/src/asm"
@@ -12,11 +15,11 @@ func (c *compiler) compileARM(x asm.Instruction) {
 	case asm.CALL:
 		switch data := x.Data.(type) {
 		case *asm.Label:
-			position := len(c.code)
-			c.code = arm.Call(c.code, 0)
+			position := Address(len(c.code))
+			c.append(arm.Call(0))
 
 			pointer := &pointer{
-				Position: Address(position),
+				Position: position,
 				OpSize:   0,
 				Size:     4,
 			}
@@ -28,8 +31,8 @@ func (c *compiler) compileARM(x asm.Instruction) {
 					panic(fmt.Sprintf("unknown jump label %s", data.Name))
 				}
 
-				distance := (destination - pointer.Position) / 4
-				return arm.EncodeCall(distance)
+				distance := (destination - position) / 4
+				return arm.Call(distance)
 			}
 
 			c.codePointers = append(c.codePointers, pointer)
@@ -37,20 +40,67 @@ func (c *compiler) compileARM(x asm.Instruction) {
 
 	case asm.LABEL:
 		c.codeLabels[x.Data.(*asm.Label).Name] = Address(len(c.code))
+		c.append(0xa9be7bfd)
+		c.append(0x910003fd)
+
+	case asm.LOAD:
+		switch operands := x.Data.(type) {
+		case *asm.MemoryRegister:
+			if operands.Address.OffsetRegister == math.MaxUint8 {
+				c.append(arm.LoadRegister(operands.Register, operands.Address.Base, int16(operands.Address.Offset), operands.Address.Length))
+			} else {
+				// TODO: LoadDynamicRegister
+				panic("not implemented")
+			}
+		}
 
 	case asm.MOVE:
 		switch operands := x.Data.(type) {
+		case *asm.RegisterRegister:
+			c.append(arm.MoveRegisterRegister(operands.Destination, operands.Source))
+
 		case *asm.RegisterNumber:
-			c.code = arm.MoveRegisterNumber(c.code, operands.Register, operands.Number)
+			c.append(arm.MoveRegisterNumber(operands.Register, operands.Number))
+
+		case *asm.RegisterLabel:
+			position := Address(len(c.code))
+			c.append(arm.LoadAddress(operands.Register, 0))
+
+			if strings.HasPrefix(operands.Label, "data ") {
+				c.dataPointers = append(c.dataPointers, &pointer{
+					Position: position,
+					OpSize:   0,
+					Size:     4,
+					Resolve: func() Address {
+						destination, exists := c.dataLabels[operands.Label]
+
+						if !exists {
+							panic("unknown label")
+						}
+
+						destination += c.dataStart - c.codeStart
+						distance := destination - position + 8
+						return arm.LoadAddress(operands.Register, int(distance))
+					},
+				})
+			} else {
+				panic("not implemented")
+			}
 		}
 
 	case asm.RETURN:
-		c.code = arm.Return(c.code)
+		c.append(0xa8c27bfd)
+		c.append(0xd65f03c0)
+		c.append(arm.Return())
 
 	case asm.SYSCALL:
-		c.code = arm.Syscall(c.code)
+		c.append(arm.Syscall())
 
 	default:
-		c.code = arm.Nop(c.code)
+		panic("unknown mnemonic: " + x.Mnemonic.String())
 	}
 }
+
+func (c *compiler) append(code uint32) {
+	c.code = binary.LittleEndian.AppendUint32(c.code, code)
+}
diff --git a/src/asmc/compiler.go b/src/asmc/compiler.go
index b4e30e6..041e590 100644
--- a/src/asmc/compiler.go
+++ b/src/asmc/compiler.go
@@ -12,4 +12,5 @@ type compiler struct {
 	dllPointers  []*pointer
 	dlls         dll.List
 	codeStart    Address
+	dataStart    Address
 }
diff --git a/src/asmc/load.go b/src/asmc/load.go
index 7a3a707..8b28fa8 100644
--- a/src/asmc/load.go
+++ b/src/asmc/load.go
@@ -11,9 +11,9 @@ func (c *compiler) load(x asm.Instruction) {
 	switch operands := x.Data.(type) {
 	case *asm.MemoryRegister:
 		if operands.Address.OffsetRegister == math.MaxUint8 {
-			c.code = x86.LoadRegister(c.code, operands.Register, operands.Address.Offset, operands.Address.Length, operands.Address.Base)
+			c.code = x86.LoadRegister(c.code, operands.Register, operands.Address.Base, operands.Address.Offset, operands.Address.Length)
 		} else {
-			c.code = x86.LoadDynamicRegister(c.code, operands.Register, operands.Address.OffsetRegister, operands.Address.Length, operands.Address.Base)
+			c.code = x86.LoadDynamicRegister(c.code, operands.Register, operands.Address.Base, operands.Address.OffsetRegister, operands.Address.Length)
 		}
 	}
 }
diff --git a/src/asmc/move.go b/src/asmc/move.go
index 71e71f3..056872c 100644
--- a/src/asmc/move.go
+++ b/src/asmc/move.go
@@ -35,7 +35,7 @@ func (c *compiler) move(x asm.Instruction) {
 						panic("unknown label")
 					}
 
-					return destination
+					return config.BaseAddress + c.dataStart + destination + 8
 				},
 			})
 		} else {
diff --git a/src/asmc/resolvePointers.go b/src/asmc/resolvePointers.go
index ea8aef2..6e3ac9d 100644
--- a/src/asmc/resolvePointers.go
+++ b/src/asmc/resolvePointers.go
@@ -77,16 +77,16 @@ restart:
 		}
 	}
 
-	dataStart, _ := fs.Align(c.codeStart+Address(len(c.code)), config.Align)
+	c.dataStart, _ = fs.Align(c.codeStart+Address(len(c.code)), config.Align)
 
 	for _, pointer := range c.dataPointers {
-		address := config.BaseAddress + dataStart + pointer.Resolve() + 8
-		slice := c.code[pointer.Position : pointer.Position+4]
+		address := pointer.Resolve()
+		slice := c.code[pointer.Position : pointer.Position+Address(pointer.Size)]
 		binary.LittleEndian.PutUint32(slice, uint32(address))
 	}
 
 	if config.TargetOS == config.Windows {
-		importsStart, _ := fs.Align(dataStart+Address(len(c.data)), config.Align)
+		importsStart, _ := fs.Align(c.dataStart+Address(len(c.data)), config.Align)
 
 		for _, pointer := range c.dllPointers {
 			destination := importsStart + pointer.Resolve()
diff --git a/src/core/ResolveTypes.go b/src/core/ResolveTypes.go
index e10e41e..306309e 100644
--- a/src/core/ResolveTypes.go
+++ b/src/core/ResolveTypes.go
@@ -6,7 +6,6 @@ import (
 	"git.urbach.dev/cli/q/src/scope"
 	"git.urbach.dev/cli/q/src/token"
 	"git.urbach.dev/cli/q/src/types"
-	"git.urbach.dev/cli/q/src/x86"
 )
 
 // ResolveTypes parses the input and output types.
@@ -34,7 +33,7 @@ func (f *Function) ResolveTypes() error {
 			Name: param.name,
 			Value: eval.Register{
 				Typ:      param.typ,
-				Register: x86.InputRegisters[i],
+				Register: f.CPU.Input[i],
 				Alive:    uses,
 			},
 		})
diff --git a/src/x86/Load.go b/src/x86/Load.go
index dc04a25..f29a08e 100644
--- a/src/x86/Load.go
+++ b/src/x86/Load.go
@@ -3,6 +3,6 @@ package x86
 import "git.urbach.dev/cli/q/src/cpu"
 
 // LoadRegister loads from memory into a register.
-func LoadRegister(code []byte, destination cpu.Register, offset int8, length byte, source cpu.Register) []byte {
-	return memoryAccess(code, 0x8A, 0x8B, source, offset, length, destination)
+func LoadRegister(code []byte, destination cpu.Register, base cpu.Register, offset int8, length byte) []byte {
+	return memoryAccess(code, 0x8A, 0x8B, base, offset, length, destination)
 }
diff --git a/src/x86/LoadDynamic.go b/src/x86/LoadDynamic.go
index 1c5cb30..c06878e 100644
--- a/src/x86/LoadDynamic.go
+++ b/src/x86/LoadDynamic.go
@@ -3,6 +3,6 @@ package x86
 import "git.urbach.dev/cli/q/src/cpu"
 
 // LoadDynamicRegister loads from memory with a register offset into a register.
-func LoadDynamicRegister(code []byte, destination cpu.Register, offset cpu.Register, length byte, source cpu.Register) []byte {
-	return memoryAccessDynamic(code, 0x8A, 0x8B, source, offset, length, destination)
+func LoadDynamicRegister(code []byte, destination cpu.Register, base cpu.Register, offset cpu.Register, length byte) []byte {
+	return memoryAccessDynamic(code, 0x8A, 0x8B, base, offset, length, destination)
 }
diff --git a/src/x86/LoadDynamic_test.go b/src/x86/LoadDynamic_test.go
index 9638e80..4cc3935 100644
--- a/src/x86/LoadDynamic_test.go
+++ b/src/x86/LoadDynamic_test.go
@@ -12,7 +12,7 @@ func TestLoadDynamicRegister(t *testing.T) {
 	usagePatterns := []struct {
 		Destination    cpu.Register
 		Length         byte
-		Source         cpu.Register
+		Base           cpu.Register
 		OffsetRegister cpu.Register
 		Code           []byte
 	}{
@@ -83,8 +83,8 @@ func TestLoadDynamicRegister(t *testing.T) {
 	}
 
 	for _, pattern := range usagePatterns {
-		t.Logf("load %dB %s, [%s+%s]", pattern.Length, pattern.Destination, pattern.Source, pattern.OffsetRegister)
-		code := x86.LoadDynamicRegister(nil, pattern.Destination, pattern.OffsetRegister, pattern.Length, pattern.Source)
+		t.Logf("load %dB %s, [%s+%s]", pattern.Length, pattern.Destination, pattern.Base, pattern.OffsetRegister)
+		code := x86.LoadDynamicRegister(nil, pattern.Destination, pattern.Base, pattern.OffsetRegister, pattern.Length)
 		assert.DeepEqual(t, code, pattern.Code)
 	}
 }
diff --git a/src/x86/Load_test.go b/src/x86/Load_test.go
index b81f6e0..3d5240b 100644
--- a/src/x86/Load_test.go
+++ b/src/x86/Load_test.go
@@ -11,7 +11,7 @@ import (
 func TestLoadRegister(t *testing.T) {
 	usagePatterns := []struct {
 		Destination cpu.Register
-		Source      cpu.Register
+		Base        cpu.Register
 		Offset      int8
 		Length      byte
 		Code        []byte
@@ -150,8 +150,8 @@ func TestLoadRegister(t *testing.T) {
 	}
 
 	for _, pattern := range usagePatterns {
-		t.Logf("load %dB %s, [%s+%d]", pattern.Length, pattern.Destination, pattern.Source, pattern.Offset)
-		code := x86.LoadRegister(nil, pattern.Destination, pattern.Offset, pattern.Length, pattern.Source)
+		t.Logf("load %dB %s, [%s+%d]", pattern.Length, pattern.Destination, pattern.Base, pattern.Offset)
+		code := x86.LoadRegister(nil, pattern.Destination, pattern.Base, pattern.Offset, pattern.Length)
 		assert.DeepEqual(t, code, pattern.Code)
 	}
 }
diff --git a/src/x86/Move.go b/src/x86/Move.go
index efe8756..7e3b103 100644
--- a/src/x86/Move.go
+++ b/src/x86/Move.go
@@ -54,7 +54,7 @@ func MoveRegisterNumber32(code []byte, destination cpu.Register, number int) []b
 	return binary.LittleEndian.AppendUint32(code, uint32(number))
 }
 
-// MoveRegisterRegister moves a register value into another register.
+// MoveRegisterRegister copies a register to another register.
 func MoveRegisterRegister(code []byte, destination cpu.Register, source cpu.Register) []byte {
 	return encode(code, AddressDirect, source, destination, 8, 0x89)
 }