intel.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  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. package x86asm
  5. import (
  6. "fmt"
  7. "strings"
  8. )
  9. // IntelSyntax returns the Intel assembler syntax for the instruction, as defined by Intel's XED tool.
  10. func IntelSyntax(inst Inst, pc uint64, symname SymLookup) string {
  11. if symname == nil {
  12. symname = func(uint64) (string, uint64) { return "", 0 }
  13. }
  14. var iargs []Arg
  15. for _, a := range inst.Args {
  16. if a == nil {
  17. break
  18. }
  19. iargs = append(iargs, a)
  20. }
  21. switch inst.Op {
  22. case INSB, INSD, INSW, OUTSB, OUTSD, OUTSW, LOOPNE, JCXZ, JECXZ, JRCXZ, LOOP, LOOPE, MOV, XLATB:
  23. if inst.Op == MOV && (inst.Opcode>>16)&0xFFFC != 0x0F20 {
  24. break
  25. }
  26. for i, p := range inst.Prefix {
  27. if p&0xFF == PrefixAddrSize {
  28. inst.Prefix[i] &^= PrefixImplicit
  29. }
  30. }
  31. }
  32. switch inst.Op {
  33. case MOV:
  34. dst, _ := inst.Args[0].(Reg)
  35. src, _ := inst.Args[1].(Reg)
  36. if ES <= dst && dst <= GS && EAX <= src && src <= R15L {
  37. src -= EAX - AX
  38. iargs[1] = src
  39. }
  40. if ES <= dst && dst <= GS && RAX <= src && src <= R15 {
  41. src -= RAX - AX
  42. iargs[1] = src
  43. }
  44. if inst.Opcode>>24&^3 == 0xA0 {
  45. for i, p := range inst.Prefix {
  46. if p&0xFF == PrefixAddrSize {
  47. inst.Prefix[i] |= PrefixImplicit
  48. }
  49. }
  50. }
  51. }
  52. switch inst.Op {
  53. case AAM, AAD:
  54. if imm, ok := iargs[0].(Imm); ok {
  55. if inst.DataSize == 32 {
  56. iargs[0] = Imm(uint32(int8(imm)))
  57. } else if inst.DataSize == 16 {
  58. iargs[0] = Imm(uint16(int8(imm)))
  59. }
  60. }
  61. case PUSH:
  62. if imm, ok := iargs[0].(Imm); ok {
  63. iargs[0] = Imm(uint32(imm))
  64. }
  65. }
  66. for _, p := range inst.Prefix {
  67. if p&PrefixImplicit != 0 {
  68. for j, pj := range inst.Prefix {
  69. if pj&0xFF == p&0xFF {
  70. inst.Prefix[j] |= PrefixImplicit
  71. }
  72. }
  73. }
  74. }
  75. if inst.Op != 0 {
  76. for i, p := range inst.Prefix {
  77. switch p &^ PrefixIgnored {
  78. case PrefixData16, PrefixData32, PrefixCS, PrefixDS, PrefixES, PrefixSS:
  79. inst.Prefix[i] |= PrefixImplicit
  80. }
  81. if p.IsREX() {
  82. inst.Prefix[i] |= PrefixImplicit
  83. }
  84. if p.IsVEX() {
  85. if p == PrefixVEX3Bytes {
  86. inst.Prefix[i+2] |= PrefixImplicit
  87. }
  88. inst.Prefix[i] |= PrefixImplicit
  89. inst.Prefix[i+1] |= PrefixImplicit
  90. }
  91. }
  92. }
  93. if isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
  94. for i, p := range inst.Prefix {
  95. if p == PrefixPT || p == PrefixPN {
  96. inst.Prefix[i] |= PrefixImplicit
  97. }
  98. }
  99. }
  100. switch inst.Op {
  101. case AAA, AAS, CBW, CDQE, CLC, CLD, CLI, CLTS, CMC, CPUID, CQO, CWD, DAA, DAS,
  102. FDECSTP, FINCSTP, FNCLEX, FNINIT, FNOP, FWAIT, HLT,
  103. ICEBP, INSB, INSD, INSW, INT, INTO, INVD, IRET, IRETQ,
  104. LAHF, LEAVE, LRET, MONITOR, MWAIT, NOP, OUTSB, OUTSD, OUTSW,
  105. PAUSE, POPA, POPF, POPFQ, PUSHA, PUSHF, PUSHFQ,
  106. RDMSR, RDPMC, RDTSC, RDTSCP, RET, RSM,
  107. SAHF, STC, STD, STI, SYSENTER, SYSEXIT, SYSRET,
  108. UD2, WBINVD, WRMSR, XEND, XLATB, XTEST:
  109. if inst.Op == NOP && inst.Opcode>>24 != 0x90 {
  110. break
  111. }
  112. if inst.Op == RET && inst.Opcode>>24 != 0xC3 {
  113. break
  114. }
  115. if inst.Op == INT && inst.Opcode>>24 != 0xCC {
  116. break
  117. }
  118. if inst.Op == LRET && inst.Opcode>>24 != 0xcb {
  119. break
  120. }
  121. for i, p := range inst.Prefix {
  122. if p&0xFF == PrefixDataSize {
  123. inst.Prefix[i] &^= PrefixImplicit | PrefixIgnored
  124. }
  125. }
  126. case 0:
  127. // ok
  128. }
  129. switch inst.Op {
  130. case INSB, INSD, INSW, OUTSB, OUTSD, OUTSW, MONITOR, MWAIT, XLATB:
  131. iargs = nil
  132. case STOSB, STOSW, STOSD, STOSQ:
  133. iargs = iargs[:1]
  134. case LODSB, LODSW, LODSD, LODSQ, SCASB, SCASW, SCASD, SCASQ:
  135. iargs = iargs[1:]
  136. }
  137. const (
  138. haveData16 = 1 << iota
  139. haveData32
  140. haveAddr16
  141. haveAddr32
  142. haveXacquire
  143. haveXrelease
  144. haveLock
  145. haveHintTaken
  146. haveHintNotTaken
  147. haveBnd
  148. )
  149. var prefixBits uint32
  150. prefix := ""
  151. for _, p := range inst.Prefix {
  152. if p == 0 {
  153. break
  154. }
  155. if p&0xFF == 0xF3 {
  156. prefixBits &^= haveBnd
  157. }
  158. if p&(PrefixImplicit|PrefixIgnored) != 0 {
  159. continue
  160. }
  161. switch p {
  162. default:
  163. prefix += strings.ToLower(p.String()) + " "
  164. case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
  165. if inst.Op == 0 {
  166. prefix += strings.ToLower(p.String()) + " "
  167. }
  168. case PrefixREPN:
  169. prefix += "repne "
  170. case PrefixLOCK:
  171. prefixBits |= haveLock
  172. case PrefixData16, PrefixDataSize:
  173. prefixBits |= haveData16
  174. case PrefixData32:
  175. prefixBits |= haveData32
  176. case PrefixAddrSize, PrefixAddr16:
  177. prefixBits |= haveAddr16
  178. case PrefixAddr32:
  179. prefixBits |= haveAddr32
  180. case PrefixXACQUIRE:
  181. prefixBits |= haveXacquire
  182. case PrefixXRELEASE:
  183. prefixBits |= haveXrelease
  184. case PrefixPT:
  185. prefixBits |= haveHintTaken
  186. case PrefixPN:
  187. prefixBits |= haveHintNotTaken
  188. case PrefixBND:
  189. prefixBits |= haveBnd
  190. }
  191. }
  192. switch inst.Op {
  193. case JMP:
  194. if inst.Opcode>>24 == 0xEB {
  195. prefixBits &^= haveBnd
  196. }
  197. case RET, LRET:
  198. prefixBits &^= haveData16 | haveData32
  199. }
  200. if prefixBits&haveXacquire != 0 {
  201. prefix += "xacquire "
  202. }
  203. if prefixBits&haveXrelease != 0 {
  204. prefix += "xrelease "
  205. }
  206. if prefixBits&haveLock != 0 {
  207. prefix += "lock "
  208. }
  209. if prefixBits&haveBnd != 0 {
  210. prefix += "bnd "
  211. }
  212. if prefixBits&haveHintTaken != 0 {
  213. prefix += "hint-taken "
  214. }
  215. if prefixBits&haveHintNotTaken != 0 {
  216. prefix += "hint-not-taken "
  217. }
  218. if prefixBits&haveAddr16 != 0 {
  219. prefix += "addr16 "
  220. }
  221. if prefixBits&haveAddr32 != 0 {
  222. prefix += "addr32 "
  223. }
  224. if prefixBits&haveData16 != 0 {
  225. prefix += "data16 "
  226. }
  227. if prefixBits&haveData32 != 0 {
  228. prefix += "data32 "
  229. }
  230. if inst.Op == 0 {
  231. if prefix == "" {
  232. return "<no instruction>"
  233. }
  234. return prefix[:len(prefix)-1]
  235. }
  236. var args []string
  237. for _, a := range iargs {
  238. if a == nil {
  239. break
  240. }
  241. args = append(args, intelArg(&inst, pc, symname, a))
  242. }
  243. var op string
  244. switch inst.Op {
  245. case NOP:
  246. if inst.Opcode>>24 == 0x0F {
  247. if inst.DataSize == 16 {
  248. args = append(args, "ax")
  249. } else {
  250. args = append(args, "eax")
  251. }
  252. }
  253. case BLENDVPD, BLENDVPS, PBLENDVB:
  254. args = args[:2]
  255. case INT:
  256. if inst.Opcode>>24 == 0xCC {
  257. args = nil
  258. op = "int3"
  259. }
  260. case LCALL, LJMP:
  261. if len(args) == 2 {
  262. args[0], args[1] = args[1], args[0]
  263. }
  264. case FCHS, FABS, FTST, FLDPI, FLDL2E, FLDLG2, F2XM1, FXAM, FLD1, FLDL2T, FSQRT, FRNDINT, FCOS, FSIN:
  265. if len(args) == 0 {
  266. args = append(args, "st0")
  267. }
  268. case FPTAN, FSINCOS, FUCOMPP, FCOMPP, FYL2X, FPATAN, FXTRACT, FPREM1, FPREM, FYL2XP1, FSCALE:
  269. if len(args) == 0 {
  270. args = []string{"st0", "st1"}
  271. }
  272. case FST, FSTP, FISTTP, FIST, FISTP, FBSTP:
  273. if len(args) == 1 {
  274. args = append(args, "st0")
  275. }
  276. case FLD, FXCH, FCOM, FCOMP, FIADD, FIMUL, FICOM, FICOMP, FISUBR, FIDIV, FUCOM, FUCOMP, FILD, FBLD, FADD, FMUL, FSUB, FSUBR, FISUB, FDIV, FDIVR, FIDIVR:
  277. if len(args) == 1 {
  278. args = []string{"st0", args[0]}
  279. }
  280. case MASKMOVDQU, MASKMOVQ, XLATB, OUTSB, OUTSW, OUTSD:
  281. FixSegment:
  282. for i := len(inst.Prefix) - 1; i >= 0; i-- {
  283. p := inst.Prefix[i] & 0xFF
  284. switch p {
  285. case PrefixCS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
  286. if inst.Mode != 64 || p == PrefixFS || p == PrefixGS {
  287. args = append(args, strings.ToLower((inst.Prefix[i] & 0xFF).String()))
  288. break FixSegment
  289. }
  290. case PrefixDS:
  291. if inst.Mode != 64 {
  292. break FixSegment
  293. }
  294. }
  295. }
  296. }
  297. if op == "" {
  298. op = intelOp[inst.Op]
  299. }
  300. if op == "" {
  301. op = strings.ToLower(inst.Op.String())
  302. }
  303. if args != nil {
  304. op += " " + strings.Join(args, ", ")
  305. }
  306. return prefix + op
  307. }
  308. func intelArg(inst *Inst, pc uint64, symname SymLookup, arg Arg) string {
  309. switch a := arg.(type) {
  310. case Imm:
  311. if (inst.Op == MOV || inst.Op == PUSH) && inst.DataSize == 32 { // See comment in plan9x.go.
  312. if s, base := symname(uint64(a)); s != "" {
  313. suffix := ""
  314. if uint64(a) != base {
  315. suffix = fmt.Sprintf("%+d", uint64(a)-base)
  316. }
  317. return fmt.Sprintf("$%s%s", s, suffix)
  318. }
  319. }
  320. if inst.Mode == 32 {
  321. return fmt.Sprintf("%#x", uint32(a))
  322. }
  323. if Imm(int32(a)) == a {
  324. return fmt.Sprintf("%#x", int64(a))
  325. }
  326. return fmt.Sprintf("%#x", uint64(a))
  327. case Mem:
  328. if a.Base == EIP {
  329. a.Base = RIP
  330. }
  331. prefix := ""
  332. switch inst.MemBytes {
  333. case 1:
  334. prefix = "byte "
  335. case 2:
  336. prefix = "word "
  337. case 4:
  338. prefix = "dword "
  339. case 8:
  340. prefix = "qword "
  341. case 16:
  342. prefix = "xmmword "
  343. case 32:
  344. prefix = "ymmword "
  345. }
  346. switch inst.Op {
  347. case INVLPG:
  348. prefix = "byte "
  349. case STOSB, MOVSB, CMPSB, LODSB, SCASB:
  350. prefix = "byte "
  351. case STOSW, MOVSW, CMPSW, LODSW, SCASW:
  352. prefix = "word "
  353. case STOSD, MOVSD, CMPSD, LODSD, SCASD:
  354. prefix = "dword "
  355. case STOSQ, MOVSQ, CMPSQ, LODSQ, SCASQ:
  356. prefix = "qword "
  357. case LAR:
  358. prefix = "word "
  359. case BOUND:
  360. if inst.Mode == 32 {
  361. prefix = "qword "
  362. } else {
  363. prefix = "dword "
  364. }
  365. case PREFETCHW, PREFETCHNTA, PREFETCHT0, PREFETCHT1, PREFETCHT2, CLFLUSH:
  366. prefix = "zmmword "
  367. }
  368. switch inst.Op {
  369. case MOVSB, MOVSW, MOVSD, MOVSQ, CMPSB, CMPSW, CMPSD, CMPSQ, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ, LODSB, LODSW, LODSD, LODSQ:
  370. switch a.Base {
  371. case DI, EDI, RDI:
  372. if a.Segment == ES {
  373. a.Segment = 0
  374. }
  375. case SI, ESI, RSI:
  376. if a.Segment == DS {
  377. a.Segment = 0
  378. }
  379. }
  380. case LEA:
  381. a.Segment = 0
  382. default:
  383. switch a.Base {
  384. case SP, ESP, RSP, BP, EBP, RBP:
  385. if a.Segment == SS {
  386. a.Segment = 0
  387. }
  388. default:
  389. if a.Segment == DS {
  390. a.Segment = 0
  391. }
  392. }
  393. }
  394. if inst.Mode == 64 && a.Segment != FS && a.Segment != GS {
  395. a.Segment = 0
  396. }
  397. prefix += "ptr "
  398. if s, disp := memArgToSymbol(a, pc, inst.Len, symname); s != "" {
  399. suffix := ""
  400. if disp != 0 {
  401. suffix = fmt.Sprintf("%+d", disp)
  402. }
  403. return prefix + fmt.Sprintf("[%s%s]", s, suffix)
  404. }
  405. if a.Segment != 0 {
  406. prefix += strings.ToLower(a.Segment.String()) + ":"
  407. }
  408. prefix += "["
  409. if a.Base != 0 {
  410. prefix += intelArg(inst, pc, symname, a.Base)
  411. }
  412. if a.Scale != 0 && a.Index != 0 {
  413. if a.Base != 0 {
  414. prefix += "+"
  415. }
  416. prefix += fmt.Sprintf("%s*%d", intelArg(inst, pc, symname, a.Index), a.Scale)
  417. }
  418. if a.Disp != 0 {
  419. if prefix[len(prefix)-1] == '[' && (a.Disp >= 0 || int64(int32(a.Disp)) != a.Disp) {
  420. prefix += fmt.Sprintf("%#x", uint64(a.Disp))
  421. } else {
  422. prefix += fmt.Sprintf("%+#x", a.Disp)
  423. }
  424. }
  425. prefix += "]"
  426. return prefix
  427. case Rel:
  428. if pc == 0 {
  429. return fmt.Sprintf(".%+#x", int64(a))
  430. } else {
  431. addr := pc + uint64(inst.Len) + uint64(a)
  432. if s, base := symname(addr); s != "" && addr == base {
  433. return fmt.Sprintf("%s", s)
  434. } else {
  435. addr := pc + uint64(inst.Len) + uint64(a)
  436. return fmt.Sprintf("%#x", addr)
  437. }
  438. }
  439. case Reg:
  440. if int(a) < len(intelReg) && intelReg[a] != "" {
  441. switch inst.Op {
  442. case VMOVDQA, VMOVDQU, VMOVNTDQA, VMOVNTDQ:
  443. return strings.Replace(intelReg[a], "xmm", "ymm", -1)
  444. default:
  445. return intelReg[a]
  446. }
  447. }
  448. }
  449. return strings.ToLower(arg.String())
  450. }
  451. var intelOp = map[Op]string{
  452. JAE: "jnb",
  453. JA: "jnbe",
  454. JGE: "jnl",
  455. JNE: "jnz",
  456. JG: "jnle",
  457. JE: "jz",
  458. SETAE: "setnb",
  459. SETA: "setnbe",
  460. SETGE: "setnl",
  461. SETNE: "setnz",
  462. SETG: "setnle",
  463. SETE: "setz",
  464. CMOVAE: "cmovnb",
  465. CMOVA: "cmovnbe",
  466. CMOVGE: "cmovnl",
  467. CMOVNE: "cmovnz",
  468. CMOVG: "cmovnle",
  469. CMOVE: "cmovz",
  470. LCALL: "call far",
  471. LJMP: "jmp far",
  472. LRET: "ret far",
  473. ICEBP: "int1",
  474. MOVSD_XMM: "movsd",
  475. XLATB: "xlat",
  476. }
  477. var intelReg = [...]string{
  478. F0: "st0",
  479. F1: "st1",
  480. F2: "st2",
  481. F3: "st3",
  482. F4: "st4",
  483. F5: "st5",
  484. F6: "st6",
  485. F7: "st7",
  486. M0: "mmx0",
  487. M1: "mmx1",
  488. M2: "mmx2",
  489. M3: "mmx3",
  490. M4: "mmx4",
  491. M5: "mmx5",
  492. M6: "mmx6",
  493. M7: "mmx7",
  494. X0: "xmm0",
  495. X1: "xmm1",
  496. X2: "xmm2",
  497. X3: "xmm3",
  498. X4: "xmm4",
  499. X5: "xmm5",
  500. X6: "xmm6",
  501. X7: "xmm7",
  502. X8: "xmm8",
  503. X9: "xmm9",
  504. X10: "xmm10",
  505. X11: "xmm11",
  506. X12: "xmm12",
  507. X13: "xmm13",
  508. X14: "xmm14",
  509. X15: "xmm15",
  510. // TODO: Maybe the constants are named wrong.
  511. SPB: "spl",
  512. BPB: "bpl",
  513. SIB: "sil",
  514. DIB: "dil",
  515. R8L: "r8d",
  516. R9L: "r9d",
  517. R10L: "r10d",
  518. R11L: "r11d",
  519. R12L: "r12d",
  520. R13L: "r13d",
  521. R14L: "r14d",
  522. R15L: "r15d",
  523. }