This repository has been archived by the owner on Feb 27, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathLoad.go
92 lines (70 loc) · 2.12 KB
/
Load.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package asm
import (
"log"
"github.com/akyoto/asm/opcode"
)
// LoadRegister loads from memory into a register.
func (a *Assembler) LoadRegister(registerNameTo string, registerNameFrom string, offset byte, byteCount byte) {
registerTo, exists := registers[registerNameTo]
if !exists {
log.Fatal("Unknown register name: " + registerNameTo)
}
registerFrom, exists := registers[registerNameFrom]
if !exists {
log.Fatal("Unknown register name: " + registerNameFrom)
}
baseCode := byte(0x8b)
switch byteCount {
case 2:
a.WriteBytes(0x66)
case 1:
baseCode = 0x8a
}
// REX prefix
w := byte(0) // Indicates a 64-bit register.
r := byte(0) // Extension to the "reg" field in ModRM.
x := byte(0) // Extension to the SIB index field.
b := byte(0) // Extension to the "rm" field in ModRM or the SIB base (r8 up to r15 use this).
if byteCount == 8 {
w = 1
}
if registerTo.BaseCodeOffset >= 8 {
b = 1
}
if registerFrom.BaseCodeOffset >= 8 {
r = 1
}
// Using one of the new (r8-r15) registers as a destination with an old register source
// requires swapping r & b which is equal to adding 3 to the REX prefix.
if b == 1 && r == 0 {
r = 1
b = 0
}
if w != 0 || r != 0 || b != 0 || x != 0 || registerTo.MustHaveREX {
a.WriteBytes(opcode.REX(w, r, x, b))
}
// Base code
a.WriteBytes(baseCode)
// ModRM
hasOffset := offset != 0
// rbp and r13 always have an offset
if registerNameFrom == "rbp" || registerNameFrom == "r13" {
hasOffset = true
}
if hasOffset {
a.WriteBytes(opcode.ModRM(0b01, registerTo.BaseCodeOffset%8, registerFrom.BaseCodeOffset%8))
} else {
a.WriteBytes(opcode.ModRM(0b00, registerTo.BaseCodeOffset%8, registerFrom.BaseCodeOffset%8))
}
// rsp always need an SIB byte
if registerNameFrom == "rsp" || registerNameFrom == "esp" || registerNameFrom == "sp" || registerNameFrom == "spl" {
a.WriteBytes(opcode.SIB(0b00, 0b100, 0b100))
}
// r12 always need an SIB byte
if registerNameFrom == "r12" || registerNameFrom == "r12d" || registerNameFrom == "r12w" || registerNameFrom == "r12b" {
a.WriteBytes(opcode.SIB(0b00, 0b100, 0b100))
}
if hasOffset {
a.WriteBytes(offset)
}
}