1
2
3
4
5 package x86asm
6
7 import (
8 "fmt"
9 "strings"
10 )
11
12 type SymLookup func(uint64) (string, uint64)
13
14
15
16
17
18
19
20
21 func GoSyntax(inst Inst, pc uint64, symname SymLookup) string {
22 if symname == nil {
23 symname = func(uint64) (string, uint64) { return "", 0 }
24 }
25 var args []string
26 for i := len(inst.Args) - 1; i >= 0; i-- {
27 a := inst.Args[i]
28 if a == nil {
29 continue
30 }
31 args = append(args, plan9Arg(&inst, pc, symname, a))
32 }
33
34 var rep string
35 var last Prefix
36 for _, p := range inst.Prefix {
37 if p == 0 || p.IsREX() || p.IsVEX() {
38 break
39 }
40
41 switch {
42
43 case p&0xFF00 == PrefixImplicit:
44 continue
45
46
47 case p&0xFF == PrefixREP:
48 rep = "REP; "
49 case p&0xFF == PrefixREPN:
50 rep = "REPNE; "
51 default:
52 last = p
53 }
54 }
55
56 prefix := ""
57 switch last & 0xFF {
58 case 0, 0x66, 0x67:
59
60 default:
61 prefix += last.String() + " "
62 }
63
64 op := inst.Op.String()
65 if plan9Suffix[inst.Op] {
66 s := inst.DataSize
67 if inst.MemBytes != 0 {
68 s = inst.MemBytes * 8
69 }
70 switch s {
71 case 8:
72 op += "B"
73 case 16:
74 op += "W"
75 case 32:
76 op += "L"
77 case 64:
78 op += "Q"
79 }
80 }
81
82 if args != nil {
83 op += " " + strings.Join(args, ", ")
84 }
85
86 return rep + prefix + op
87 }
88
89 func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
90 switch a := arg.(type) {
91 case Reg:
92 return plan9Reg[a]
93 case Rel:
94 if pc == 0 {
95 break
96 }
97
98
99
100
101
102 addr := pc + uint64(inst.Len) + uint64(a)
103 if s, base := symname(addr); s != "" && addr == base {
104 return fmt.Sprintf("%s(SB)", s)
105 }
106 return fmt.Sprintf("%#x", addr)
107
108 case Imm:
109 if s, base := symname(uint64(a)); s != "" {
110 suffix := ""
111 if uint64(a) != base {
112 suffix = fmt.Sprintf("%+d", uint64(a)-base)
113 }
114 return fmt.Sprintf("$%s%s(SB)", s, suffix)
115 }
116 if inst.Mode == 32 {
117 return fmt.Sprintf("$%#x", uint32(a))
118 }
119 if Imm(int32(a)) == a {
120 return fmt.Sprintf("$%#x", int64(a))
121 }
122 return fmt.Sprintf("$%#x", uint64(a))
123 case Mem:
124 if s, disp := memArgToSymbol(a, pc, inst.Len, symname); s != "" {
125 suffix := ""
126 if disp != 0 {
127 suffix = fmt.Sprintf("%+d", disp)
128 }
129 return fmt.Sprintf("%s%s(SB)", s, suffix)
130 }
131 s := ""
132 if a.Segment != 0 {
133 s += fmt.Sprintf("%s:", plan9Reg[a.Segment])
134 }
135 if a.Disp != 0 {
136 s += fmt.Sprintf("%#x", a.Disp)
137 } else {
138 s += "0"
139 }
140 if a.Base != 0 {
141 s += fmt.Sprintf("(%s)", plan9Reg[a.Base])
142 }
143 if a.Index != 0 && a.Scale != 0 {
144 s += fmt.Sprintf("(%s*%d)", plan9Reg[a.Index], a.Scale)
145 }
146 return s
147 }
148 return arg.String()
149 }
150
151 func memArgToSymbol(a Mem, pc uint64, instrLen int, symname SymLookup) (string, int64) {
152 if a.Segment != 0 || a.Disp == 0 || a.Index != 0 || a.Scale != 0 {
153 return "", 0
154 }
155
156 var disp uint64
157 switch a.Base {
158 case IP, EIP, RIP:
159 disp = uint64(a.Disp + int64(pc) + int64(instrLen))
160 case 0:
161 disp = uint64(a.Disp)
162 default:
163 return "", 0
164 }
165
166 s, base := symname(disp)
167 return s, int64(disp) - int64(base)
168 }
169
170 var plan9Suffix = [maxOp + 1]bool{
171 ADC: true,
172 ADD: true,
173 AND: true,
174 BSF: true,
175 BSR: true,
176 BT: true,
177 BTC: true,
178 BTR: true,
179 BTS: true,
180 CMP: true,
181 CMPXCHG: true,
182 CVTSI2SD: true,
183 CVTSI2SS: true,
184 CVTSD2SI: true,
185 CVTSS2SI: true,
186 CVTTSD2SI: true,
187 CVTTSS2SI: true,
188 DEC: true,
189 DIV: true,
190 FLDENV: true,
191 FRSTOR: true,
192 IDIV: true,
193 IMUL: true,
194 IN: true,
195 INC: true,
196 LEA: true,
197 MOV: true,
198 MOVNTI: true,
199 MUL: true,
200 NEG: true,
201 NOP: true,
202 NOT: true,
203 OR: true,
204 OUT: true,
205 POP: true,
206 POPA: true,
207 POPCNT: true,
208 PUSH: true,
209 PUSHA: true,
210 RCL: true,
211 RCR: true,
212 ROL: true,
213 ROR: true,
214 SAR: true,
215 SBB: true,
216 SHL: true,
217 SHLD: true,
218 SHR: true,
219 SHRD: true,
220 SUB: true,
221 TEST: true,
222 XADD: true,
223 XCHG: true,
224 XOR: true,
225 }
226
227 var plan9Reg = [...]string{
228 AL: "AL",
229 CL: "CL",
230 BL: "BL",
231 DL: "DL",
232 AH: "AH",
233 CH: "CH",
234 BH: "BH",
235 DH: "DH",
236 SPB: "SP",
237 BPB: "BP",
238 SIB: "SI",
239 DIB: "DI",
240 R8B: "R8",
241 R9B: "R9",
242 R10B: "R10",
243 R11B: "R11",
244 R12B: "R12",
245 R13B: "R13",
246 R14B: "R14",
247 R15B: "R15",
248 AX: "AX",
249 CX: "CX",
250 BX: "BX",
251 DX: "DX",
252 SP: "SP",
253 BP: "BP",
254 SI: "SI",
255 DI: "DI",
256 R8W: "R8",
257 R9W: "R9",
258 R10W: "R10",
259 R11W: "R11",
260 R12W: "R12",
261 R13W: "R13",
262 R14W: "R14",
263 R15W: "R15",
264 EAX: "AX",
265 ECX: "CX",
266 EDX: "DX",
267 EBX: "BX",
268 ESP: "SP",
269 EBP: "BP",
270 ESI: "SI",
271 EDI: "DI",
272 R8L: "R8",
273 R9L: "R9",
274 R10L: "R10",
275 R11L: "R11",
276 R12L: "R12",
277 R13L: "R13",
278 R14L: "R14",
279 R15L: "R15",
280 RAX: "AX",
281 RCX: "CX",
282 RDX: "DX",
283 RBX: "BX",
284 RSP: "SP",
285 RBP: "BP",
286 RSI: "SI",
287 RDI: "DI",
288 R8: "R8",
289 R9: "R9",
290 R10: "R10",
291 R11: "R11",
292 R12: "R12",
293 R13: "R13",
294 R14: "R14",
295 R15: "R15",
296 IP: "IP",
297 EIP: "IP",
298 RIP: "IP",
299 F0: "F0",
300 F1: "F1",
301 F2: "F2",
302 F3: "F3",
303 F4: "F4",
304 F5: "F5",
305 F6: "F6",
306 F7: "F7",
307 M0: "M0",
308 M1: "M1",
309 M2: "M2",
310 M3: "M3",
311 M4: "M4",
312 M5: "M5",
313 M6: "M6",
314 M7: "M7",
315 X0: "X0",
316 X1: "X1",
317 X2: "X2",
318 X3: "X3",
319 X4: "X4",
320 X5: "X5",
321 X6: "X6",
322 X7: "X7",
323 X8: "X8",
324 X9: "X9",
325 X10: "X10",
326 X11: "X11",
327 X12: "X12",
328 X13: "X13",
329 X14: "X14",
330 X15: "X15",
331 CS: "CS",
332 SS: "SS",
333 DS: "DS",
334 ES: "ES",
335 FS: "FS",
336 GS: "GS",
337 GDTR: "GDTR",
338 IDTR: "IDTR",
339 LDTR: "LDTR",
340 MSW: "MSW",
341 TASK: "TASK",
342 CR0: "CR0",
343 CR1: "CR1",
344 CR2: "CR2",
345 CR3: "CR3",
346 CR4: "CR4",
347 CR5: "CR5",
348 CR6: "CR6",
349 CR7: "CR7",
350 CR8: "CR8",
351 CR9: "CR9",
352 CR10: "CR10",
353 CR11: "CR11",
354 CR12: "CR12",
355 CR13: "CR13",
356 CR14: "CR14",
357 CR15: "CR15",
358 DR0: "DR0",
359 DR1: "DR1",
360 DR2: "DR2",
361 DR3: "DR3",
362 DR4: "DR4",
363 DR5: "DR5",
364 DR6: "DR6",
365 DR7: "DR7",
366 DR8: "DR8",
367 DR9: "DR9",
368 DR10: "DR10",
369 DR11: "DR11",
370 DR12: "DR12",
371 DR13: "DR13",
372 DR14: "DR14",
373 DR15: "DR15",
374 TR0: "TR0",
375 TR1: "TR1",
376 TR2: "TR2",
377 TR3: "TR3",
378 TR4: "TR4",
379 TR5: "TR5",
380 TR6: "TR6",
381 TR7: "TR7",
382 }
383
View as plain text