cubefs

Форк
0
560 строк · 11.7 Кб
1
// Copyright 2014 The Go Authors.  All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4

5
package x86asm
6

7
import (
8
	"fmt"
9
	"strings"
10
)
11

12
// IntelSyntax returns the Intel assembler syntax for the instruction, as defined by Intel's XED tool.
13
func IntelSyntax(inst Inst, pc uint64, symname SymLookup) string {
14
	if symname == nil {
15
		symname = func(uint64) (string, uint64) { return "", 0 }
16
	}
17

18
	var iargs []Arg
19
	for _, a := range inst.Args {
20
		if a == nil {
21
			break
22
		}
23
		iargs = append(iargs, a)
24
	}
25

26
	switch inst.Op {
27
	case INSB, INSD, INSW, OUTSB, OUTSD, OUTSW, LOOPNE, JCXZ, JECXZ, JRCXZ, LOOP, LOOPE, MOV, XLATB:
28
		if inst.Op == MOV && (inst.Opcode>>16)&0xFFFC != 0x0F20 {
29
			break
30
		}
31
		for i, p := range inst.Prefix {
32
			if p&0xFF == PrefixAddrSize {
33
				inst.Prefix[i] &^= PrefixImplicit
34
			}
35
		}
36
	}
37

38
	switch inst.Op {
39
	case MOV:
40
		dst, _ := inst.Args[0].(Reg)
41
		src, _ := inst.Args[1].(Reg)
42
		if ES <= dst && dst <= GS && EAX <= src && src <= R15L {
43
			src -= EAX - AX
44
			iargs[1] = src
45
		}
46
		if ES <= dst && dst <= GS && RAX <= src && src <= R15 {
47
			src -= RAX - AX
48
			iargs[1] = src
49
		}
50

51
		if inst.Opcode>>24&^3 == 0xA0 {
52
			for i, p := range inst.Prefix {
53
				if p&0xFF == PrefixAddrSize {
54
					inst.Prefix[i] |= PrefixImplicit
55
				}
56
			}
57
		}
58
	}
59

60
	switch inst.Op {
61
	case AAM, AAD:
62
		if imm, ok := iargs[0].(Imm); ok {
63
			if inst.DataSize == 32 {
64
				iargs[0] = Imm(uint32(int8(imm)))
65
			} else if inst.DataSize == 16 {
66
				iargs[0] = Imm(uint16(int8(imm)))
67
			}
68
		}
69

70
	case PUSH:
71
		if imm, ok := iargs[0].(Imm); ok {
72
			iargs[0] = Imm(uint32(imm))
73
		}
74
	}
75

76
	for _, p := range inst.Prefix {
77
		if p&PrefixImplicit != 0 {
78
			for j, pj := range inst.Prefix {
79
				if pj&0xFF == p&0xFF {
80
					inst.Prefix[j] |= PrefixImplicit
81
				}
82
			}
83
		}
84
	}
85

86
	if inst.Op != 0 {
87
		for i, p := range inst.Prefix {
88
			switch p &^ PrefixIgnored {
89
			case PrefixData16, PrefixData32, PrefixCS, PrefixDS, PrefixES, PrefixSS:
90
				inst.Prefix[i] |= PrefixImplicit
91
			}
92
			if p.IsREX() {
93
				inst.Prefix[i] |= PrefixImplicit
94
			}
95
			if p.IsVEX() {
96
				if p == PrefixVEX3Bytes {
97
					inst.Prefix[i+2] |= PrefixImplicit
98
				}
99
				inst.Prefix[i] |= PrefixImplicit
100
				inst.Prefix[i+1] |= PrefixImplicit
101
			}
102
		}
103
	}
104

105
	if isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
106
		for i, p := range inst.Prefix {
107
			if p == PrefixPT || p == PrefixPN {
108
				inst.Prefix[i] |= PrefixImplicit
109
			}
110
		}
111
	}
112

113
	switch inst.Op {
114
	case AAA, AAS, CBW, CDQE, CLC, CLD, CLI, CLTS, CMC, CPUID, CQO, CWD, DAA, DAS,
115
		FDECSTP, FINCSTP, FNCLEX, FNINIT, FNOP, FWAIT, HLT,
116
		ICEBP, INSB, INSD, INSW, INT, INTO, INVD, IRET, IRETQ,
117
		LAHF, LEAVE, LRET, MONITOR, MWAIT, NOP, OUTSB, OUTSD, OUTSW,
118
		PAUSE, POPA, POPF, POPFQ, PUSHA, PUSHF, PUSHFQ,
119
		RDMSR, RDPMC, RDTSC, RDTSCP, RET, RSM,
120
		SAHF, STC, STD, STI, SYSENTER, SYSEXIT, SYSRET,
121
		UD2, WBINVD, WRMSR, XEND, XLATB, XTEST:
122

123
		if inst.Op == NOP && inst.Opcode>>24 != 0x90 {
124
			break
125
		}
126
		if inst.Op == RET && inst.Opcode>>24 != 0xC3 {
127
			break
128
		}
129
		if inst.Op == INT && inst.Opcode>>24 != 0xCC {
130
			break
131
		}
132
		if inst.Op == LRET && inst.Opcode>>24 != 0xcb {
133
			break
134
		}
135
		for i, p := range inst.Prefix {
136
			if p&0xFF == PrefixDataSize {
137
				inst.Prefix[i] &^= PrefixImplicit | PrefixIgnored
138
			}
139
		}
140

141
	case 0:
142
		// ok
143
	}
144

145
	switch inst.Op {
146
	case INSB, INSD, INSW, OUTSB, OUTSD, OUTSW, MONITOR, MWAIT, XLATB:
147
		iargs = nil
148

149
	case STOSB, STOSW, STOSD, STOSQ:
150
		iargs = iargs[:1]
151

152
	case LODSB, LODSW, LODSD, LODSQ, SCASB, SCASW, SCASD, SCASQ:
153
		iargs = iargs[1:]
154
	}
155

156
	const (
157
		haveData16 = 1 << iota
158
		haveData32
159
		haveAddr16
160
		haveAddr32
161
		haveXacquire
162
		haveXrelease
163
		haveLock
164
		haveHintTaken
165
		haveHintNotTaken
166
		haveBnd
167
	)
168
	var prefixBits uint32
169
	prefix := ""
170
	for _, p := range inst.Prefix {
171
		if p == 0 {
172
			break
173
		}
174
		if p&0xFF == 0xF3 {
175
			prefixBits &^= haveBnd
176
		}
177
		if p&(PrefixImplicit|PrefixIgnored) != 0 {
178
			continue
179
		}
180
		switch p {
181
		default:
182
			prefix += strings.ToLower(p.String()) + " "
183
		case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
184
			if inst.Op == 0 {
185
				prefix += strings.ToLower(p.String()) + " "
186
			}
187
		case PrefixREPN:
188
			prefix += "repne "
189
		case PrefixLOCK:
190
			prefixBits |= haveLock
191
		case PrefixData16, PrefixDataSize:
192
			prefixBits |= haveData16
193
		case PrefixData32:
194
			prefixBits |= haveData32
195
		case PrefixAddrSize, PrefixAddr16:
196
			prefixBits |= haveAddr16
197
		case PrefixAddr32:
198
			prefixBits |= haveAddr32
199
		case PrefixXACQUIRE:
200
			prefixBits |= haveXacquire
201
		case PrefixXRELEASE:
202
			prefixBits |= haveXrelease
203
		case PrefixPT:
204
			prefixBits |= haveHintTaken
205
		case PrefixPN:
206
			prefixBits |= haveHintNotTaken
207
		case PrefixBND:
208
			prefixBits |= haveBnd
209
		}
210
	}
211
	switch inst.Op {
212
	case JMP:
213
		if inst.Opcode>>24 == 0xEB {
214
			prefixBits &^= haveBnd
215
		}
216
	case RET, LRET:
217
		prefixBits &^= haveData16 | haveData32
218
	}
219

220
	if prefixBits&haveXacquire != 0 {
221
		prefix += "xacquire "
222
	}
223
	if prefixBits&haveXrelease != 0 {
224
		prefix += "xrelease "
225
	}
226
	if prefixBits&haveLock != 0 {
227
		prefix += "lock "
228
	}
229
	if prefixBits&haveBnd != 0 {
230
		prefix += "bnd "
231
	}
232
	if prefixBits&haveHintTaken != 0 {
233
		prefix += "hint-taken "
234
	}
235
	if prefixBits&haveHintNotTaken != 0 {
236
		prefix += "hint-not-taken "
237
	}
238
	if prefixBits&haveAddr16 != 0 {
239
		prefix += "addr16 "
240
	}
241
	if prefixBits&haveAddr32 != 0 {
242
		prefix += "addr32 "
243
	}
244
	if prefixBits&haveData16 != 0 {
245
		prefix += "data16 "
246
	}
247
	if prefixBits&haveData32 != 0 {
248
		prefix += "data32 "
249
	}
250

251
	if inst.Op == 0 {
252
		if prefix == "" {
253
			return "<no instruction>"
254
		}
255
		return prefix[:len(prefix)-1]
256
	}
257

258
	var args []string
259
	for _, a := range iargs {
260
		if a == nil {
261
			break
262
		}
263
		args = append(args, intelArg(&inst, pc, symname, a))
264
	}
265

266
	var op string
267
	switch inst.Op {
268
	case NOP:
269
		if inst.Opcode>>24 == 0x0F {
270
			if inst.DataSize == 16 {
271
				args = append(args, "ax")
272
			} else {
273
				args = append(args, "eax")
274
			}
275
		}
276

277
	case BLENDVPD, BLENDVPS, PBLENDVB:
278
		args = args[:2]
279

280
	case INT:
281
		if inst.Opcode>>24 == 0xCC {
282
			args = nil
283
			op = "int3"
284
		}
285

286
	case LCALL, LJMP:
287
		if len(args) == 2 {
288
			args[0], args[1] = args[1], args[0]
289
		}
290

291
	case FCHS, FABS, FTST, FLDPI, FLDL2E, FLDLG2, F2XM1, FXAM, FLD1, FLDL2T, FSQRT, FRNDINT, FCOS, FSIN:
292
		if len(args) == 0 {
293
			args = append(args, "st0")
294
		}
295

296
	case FPTAN, FSINCOS, FUCOMPP, FCOMPP, FYL2X, FPATAN, FXTRACT, FPREM1, FPREM, FYL2XP1, FSCALE:
297
		if len(args) == 0 {
298
			args = []string{"st0", "st1"}
299
		}
300

301
	case FST, FSTP, FISTTP, FIST, FISTP, FBSTP:
302
		if len(args) == 1 {
303
			args = append(args, "st0")
304
		}
305

306
	case FLD, FXCH, FCOM, FCOMP, FIADD, FIMUL, FICOM, FICOMP, FISUBR, FIDIV, FUCOM, FUCOMP, FILD, FBLD, FADD, FMUL, FSUB, FSUBR, FISUB, FDIV, FDIVR, FIDIVR:
307
		if len(args) == 1 {
308
			args = []string{"st0", args[0]}
309
		}
310

311
	case MASKMOVDQU, MASKMOVQ, XLATB, OUTSB, OUTSW, OUTSD:
312
	FixSegment:
313
		for i := len(inst.Prefix) - 1; i >= 0; i-- {
314
			p := inst.Prefix[i] & 0xFF
315
			switch p {
316
			case PrefixCS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
317
				if inst.Mode != 64 || p == PrefixFS || p == PrefixGS {
318
					args = append(args, strings.ToLower((inst.Prefix[i] & 0xFF).String()))
319
					break FixSegment
320
				}
321
			case PrefixDS:
322
				if inst.Mode != 64 {
323
					break FixSegment
324
				}
325
			}
326
		}
327
	}
328

329
	if op == "" {
330
		op = intelOp[inst.Op]
331
	}
332
	if op == "" {
333
		op = strings.ToLower(inst.Op.String())
334
	}
335
	if args != nil {
336
		op += " " + strings.Join(args, ", ")
337
	}
338
	return prefix + op
339
}
340

341
func intelArg(inst *Inst, pc uint64, symname SymLookup, arg Arg) string {
342
	switch a := arg.(type) {
343
	case Imm:
344
		if s, base := symname(uint64(a)); s != "" {
345
			suffix := ""
346
			if uint64(a) != base {
347
				suffix = fmt.Sprintf("%+d", uint64(a)-base)
348
			}
349
			return fmt.Sprintf("$%s%s", s, suffix)
350
		}
351
		if inst.Mode == 32 {
352
			return fmt.Sprintf("%#x", uint32(a))
353
		}
354
		if Imm(int32(a)) == a {
355
			return fmt.Sprintf("%#x", int64(a))
356
		}
357
		return fmt.Sprintf("%#x", uint64(a))
358
	case Mem:
359
		if a.Base == EIP {
360
			a.Base = RIP
361
		}
362
		prefix := ""
363
		switch inst.MemBytes {
364
		case 1:
365
			prefix = "byte "
366
		case 2:
367
			prefix = "word "
368
		case 4:
369
			prefix = "dword "
370
		case 8:
371
			prefix = "qword "
372
		case 16:
373
			prefix = "xmmword "
374
		case 32:
375
			prefix = "ymmword "
376
		}
377
		switch inst.Op {
378
		case INVLPG:
379
			prefix = "byte "
380
		case STOSB, MOVSB, CMPSB, LODSB, SCASB:
381
			prefix = "byte "
382
		case STOSW, MOVSW, CMPSW, LODSW, SCASW:
383
			prefix = "word "
384
		case STOSD, MOVSD, CMPSD, LODSD, SCASD:
385
			prefix = "dword "
386
		case STOSQ, MOVSQ, CMPSQ, LODSQ, SCASQ:
387
			prefix = "qword "
388
		case LAR:
389
			prefix = "word "
390
		case BOUND:
391
			if inst.Mode == 32 {
392
				prefix = "qword "
393
			} else {
394
				prefix = "dword "
395
			}
396
		case PREFETCHW, PREFETCHNTA, PREFETCHT0, PREFETCHT1, PREFETCHT2, CLFLUSH:
397
			prefix = "zmmword "
398
		}
399
		switch inst.Op {
400
		case MOVSB, MOVSW, MOVSD, MOVSQ, CMPSB, CMPSW, CMPSD, CMPSQ, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ, LODSB, LODSW, LODSD, LODSQ:
401
			switch a.Base {
402
			case DI, EDI, RDI:
403
				if a.Segment == ES {
404
					a.Segment = 0
405
				}
406
			case SI, ESI, RSI:
407
				if a.Segment == DS {
408
					a.Segment = 0
409
				}
410
			}
411
		case LEA:
412
			a.Segment = 0
413
		default:
414
			switch a.Base {
415
			case SP, ESP, RSP, BP, EBP, RBP:
416
				if a.Segment == SS {
417
					a.Segment = 0
418
				}
419
			default:
420
				if a.Segment == DS {
421
					a.Segment = 0
422
				}
423
			}
424
		}
425

426
		if inst.Mode == 64 && a.Segment != FS && a.Segment != GS {
427
			a.Segment = 0
428
		}
429

430
		prefix += "ptr "
431
		if s, disp := memArgToSymbol(a, pc, inst.Len, symname); s != "" {
432
			suffix := ""
433
			if disp != 0 {
434
				suffix = fmt.Sprintf("%+d", disp)
435
			}
436
			return prefix + fmt.Sprintf("[%s%s]", s, suffix)
437
		}
438
		if a.Segment != 0 {
439
			prefix += strings.ToLower(a.Segment.String()) + ":"
440
		}
441
		prefix += "["
442
		if a.Base != 0 {
443
			prefix += intelArg(inst, pc, symname, a.Base)
444
		}
445
		if a.Scale != 0 && a.Index != 0 {
446
			if a.Base != 0 {
447
				prefix += "+"
448
			}
449
			prefix += fmt.Sprintf("%s*%d", intelArg(inst, pc, symname, a.Index), a.Scale)
450
		}
451
		if a.Disp != 0 {
452
			if prefix[len(prefix)-1] == '[' && (a.Disp >= 0 || int64(int32(a.Disp)) != a.Disp) {
453
				prefix += fmt.Sprintf("%#x", uint64(a.Disp))
454
			} else {
455
				prefix += fmt.Sprintf("%+#x", a.Disp)
456
			}
457
		}
458
		prefix += "]"
459
		return prefix
460
	case Rel:
461
		if pc == 0 {
462
			return fmt.Sprintf(".%+#x", int64(a))
463
		} else {
464
			addr := pc + uint64(inst.Len) + uint64(a)
465
			if s, base := symname(addr); s != "" && addr == base {
466
				return fmt.Sprintf("%s", s)
467
			} else {
468
				addr := pc + uint64(inst.Len) + uint64(a)
469
				return fmt.Sprintf("%#x", addr)
470
			}
471
		}
472
	case Reg:
473
		if int(a) < len(intelReg) && intelReg[a] != "" {
474
			switch inst.Op {
475
			case VMOVDQA, VMOVDQU, VMOVNTDQA, VMOVNTDQ:
476
				return strings.Replace(intelReg[a], "xmm", "ymm", -1)
477
			default:
478
				return intelReg[a]
479
			}
480
		}
481
	}
482
	return strings.ToLower(arg.String())
483
}
484

485
var intelOp = map[Op]string{
486
	JAE:       "jnb",
487
	JA:        "jnbe",
488
	JGE:       "jnl",
489
	JNE:       "jnz",
490
	JG:        "jnle",
491
	JE:        "jz",
492
	SETAE:     "setnb",
493
	SETA:      "setnbe",
494
	SETGE:     "setnl",
495
	SETNE:     "setnz",
496
	SETG:      "setnle",
497
	SETE:      "setz",
498
	CMOVAE:    "cmovnb",
499
	CMOVA:     "cmovnbe",
500
	CMOVGE:    "cmovnl",
501
	CMOVNE:    "cmovnz",
502
	CMOVG:     "cmovnle",
503
	CMOVE:     "cmovz",
504
	LCALL:     "call far",
505
	LJMP:      "jmp far",
506
	LRET:      "ret far",
507
	ICEBP:     "int1",
508
	MOVSD_XMM: "movsd",
509
	XLATB:     "xlat",
510
}
511

512
var intelReg = [...]string{
513
	F0:  "st0",
514
	F1:  "st1",
515
	F2:  "st2",
516
	F3:  "st3",
517
	F4:  "st4",
518
	F5:  "st5",
519
	F6:  "st6",
520
	F7:  "st7",
521
	M0:  "mmx0",
522
	M1:  "mmx1",
523
	M2:  "mmx2",
524
	M3:  "mmx3",
525
	M4:  "mmx4",
526
	M5:  "mmx5",
527
	M6:  "mmx6",
528
	M7:  "mmx7",
529
	X0:  "xmm0",
530
	X1:  "xmm1",
531
	X2:  "xmm2",
532
	X3:  "xmm3",
533
	X4:  "xmm4",
534
	X5:  "xmm5",
535
	X6:  "xmm6",
536
	X7:  "xmm7",
537
	X8:  "xmm8",
538
	X9:  "xmm9",
539
	X10: "xmm10",
540
	X11: "xmm11",
541
	X12: "xmm12",
542
	X13: "xmm13",
543
	X14: "xmm14",
544
	X15: "xmm15",
545

546
	// TODO: Maybe the constants are named wrong.
547
	SPB: "spl",
548
	BPB: "bpl",
549
	SIB: "sil",
550
	DIB: "dil",
551

552
	R8L:  "r8d",
553
	R9L:  "r9d",
554
	R10L: "r10d",
555
	R11L: "r11d",
556
	R12L: "r12d",
557
	R13L: "r13d",
558
	R14L: "r14d",
559
	R15L: "r15d",
560
}
561

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.