-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathx86inst.py
More file actions
executable file
·965 lines (867 loc) · 42.5 KB
/
x86inst.py
File metadata and controls
executable file
·965 lines (867 loc) · 42.5 KB
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
# Copyright 2004-2010 Grant T. Olson.
# See license.txt for terms.
"""
x86inst.py
----------
This contains the core functionality to handle x86 instructions. We need to
build definition tables, so that instructions can be converted to/from
mneumonics durring assembly/disassembly phases.
At some point we'll need to deal with forward references and symbols, but
not today.
"""
import logging
import struct
from pickle import decode_long, encode_long
from x86tokenizer import (tokenizeInstDef,tokenizeInst,
REGISTER,OPCODE,COMMA,OPERAND,
LBRACKET, RBRACKET,NUMBER,SYMBOL)
class OpcodeTooShort(Exception):pass
class OpcodeNeedsModRM(Exception):pass # for /d info and SIB calculation
class x86instError(Exception):pass
opcodeFlags = ['/0','/1','/2','/3','/4','/5','/6','/7',
'/r',
'cb','cw','cd','cp',
'ib','iw','id',
'+rb','+rw','+rd',
'+i'
]
instModRM = ['r/m8','r/m16','r/m32','r8','r16','r32']
immediate = ['imm8','imm16','imm32']
displacement = ['rel8','rel16','rel32']
rb =['AL','CL','DL','BL','AH','CH','DH','BH']
rw = ['AX','CX','DX','BX','SP','BP','SI','DI']
rd = ['EAX','ECX','EDX','EBX','ESP','EBP','ESI','EDI']
regOpcode = {
'r8':['AL','CL','DL','BL','AH','CH','DH','BH'],
'r16':['AX','CX','DX','BX','SP','BP','SI','DI'],
'r32':['EAX','ECX','EDX','EBX','ESP','EBP','ESI','EDI'],
'mm':['MM0','MM1','MM2','MM3','MM4','MM5','MM6','MM7'],
'xmm':['XMM0','XMM1','XMM2','XMM3','XMM4','XMM5','XMM6','XMM7'],
'/digit':[0,1,2,3,4,5,6,7],
'REG':[0,1,2,3,4,5,6,7],
}
mode1 = ['[EAX]','[ECX]','[EDX]','[EBX]','[--][--]','disp32','[ESI]','[EDI]']
mode2 = ['[EAX+disp8]','[ECX+disp8]','[EDX+disp8]','[EBX+disp8]',
'[--][--]+disp8','[EBP+disp8]','[ESI+disp8]','[EDI+disp8]']
mode3 = ['[EAX+disp32]','[ECX+disp32]','[EDX+disp32]','[EBX+disp32]',
'[--][--]+disp32','[EBP+disp8]','[ESI+disp8]','[EDI+disp8]']
#
# These could be 16, but that doesn't make since for windows
# They are overridden with opcode prefixes
#
DefaultOperandSize = 32
class OpcodeDict(dict):
"""
Holds instructions by opcode for lookup.
If you get an OpcodeTooShort exception, you need to keep on grabbing bytes
until you get a good opcode.
"""
def __getitem__(self,key):
retVal = dict.__getitem__(self,key)
if retVal == None:
raise OpcodeTooShort()
return retVal
def __setitem__(self,key,value):
if self.has_key(key):
dict.__getitem__(self,key).append(value)
else:
dict.__setitem__(self,key,[value])
# Sentinel for multi-byte opcodes
if len(key) > 1:
for i in range(1,len(key)):
tmpKey = key[:i]
dict.__setitem__(self,tmpKey,None)
def GetOp(self,opcode,modRM=None):
lst = self.__getitem__(opcode)
if modRM is not None:
mrm = ModRM(modRM)
digit = "/%s" % mrm.RegOp
lst = [item for item in lst if digit in item.OpcodeFlags]
if DefaultOperandSize == 16:
lst = [item for item in lst if item.InstructionString.find('r32') == -1]
lst = [item for item in lst if item.InstructionString.find('r/m32') == -1]
lst = [item for item in lst if item.InstructionString.find('imm32') == -1]
lst = [item for item in lst if item.InstructionString.find('rel32') == -1]
lst = [item for item in lst if item.InstructionString.find('m32') == -1]
lst = [item for item in lst if 'rd' not in item.OpcodeFlags]
elif DefaultOperandSize == 32:
lst = [item for item in lst if item.InstructionString.find('r16') == -1]
lst = [item for item in lst if item.InstructionString.find('r/m16') == -1]
lst = [item for item in lst if item.InstructionString.find('imm16') == -1]
lst = [item for item in lst if item.InstructionString.find('rel16') == -1]
lst = [item for item in lst if item.InstructionString.find('m16') == -1]
lst = [item for item in lst if 'rw' not in item.OpcodeFlags]
else:
raise RuntimeError("Invalid DefaultOperandSize")
if len(lst) == 0:
raise RuntimeError("Invalid/Unimplemented Opcode [%s]" % opcode)
elif len(lst) > 1:
# try to figure out what we need
op = lst[0]
for flag in op.OpcodeFlags:
if flag in ('/0','/1','/2','/3','/4','/5','/6','/7'):
raise OpcodeNeedsModRM("Opcode %s" % op.Opcode)
for x in lst:
logging.error(x.Description)
raise RuntimeError("Shouldn't get here")
else:
return lst[0]
class MnemonicDict(dict):
def __setitem__(self,key,val):
if self.has_key(key):
raise RuntimeError("Duplicate mnemonic def %s" % `key`)
dict.__setitem__(self,key,val)
opcodeDict = OpcodeDict()
mnemonicDict = MnemonicDict()
def longToBytes(long, bytes=4):
retVal = [ord(x) for x in encode_long(long)]
while len(retVal) < bytes:
if abs(long) == long:
retVal.append(0)
else:
retVal.append(0xFF)
if len(retVal) > bytes:
good,bad = retVal[:bytes],retVal[bytes:]
for x in bad:
if x:
raise x86instError("Failed converting long '%s' to bytes '%s'" % \
(long, retVal))
retVal = good
return tuple(retVal)
def longToString(long, bytes=4):
return ''.join([chr(c) for c in longToBytes(long,bytes)])
def longToBytesRepr(long,bytes=4):
retVal = ""
for x in longToBytes(long,bytes):
retVal += "%02X " % x
return retVal
class ModRM:
def __init__(self,byte=None):
self.Mode = 0x0
self.RegOp = 0x0
self.RM = 0x0
if byte:
self.LoadFromByte(byte)
def LoadFromByte(self,byte):
self.RegOp = byte & 0x38
self.RegOp = self.RegOp >> 3
self.RM = byte & 0x7
self.Mode = byte & 192
self.Mode = self.Mode >> 6
def SaveToByte(self):
return (self.Mode << 6) + (self.RegOp << 3) + self.RM
def HasSIB(self):
if self.Mode in (0,1,2) and self.RM == 4:
return True
else:
return False
def RegOpString(self,typ):
return regOpcode[typ][self.RegOp]
def RMString(self,typ=None):
retVal = ""
if self.Mode == 0:
retVal = mode1[self.RM]
elif self.Mode == 1:
retVal = mode2[self.RM]
elif self.Mode == 2:
retVal = mode3[self.RM]
elif self.Mode == 3:
if typ == 'r/m8':
retVal = regOpcode['r8'][self.RM]
elif typ == 'r/m16':
retVal = regOpcode['r16'][self.RM]
elif typ == 'r/m32':
retVal = regOpcode['r32'][self.RM]
else:
raise RuntimeError("Invalid r/m type")
else:
raise RuntimeError("Invalid Mode")
return retVal
def GetDisplacementSize(self):
"We only know this at runtime with real values"
if self.Mode == 0 and self.RM == 5:
return 4
elif self.Mode == 1:
return 1
elif self.Mode == 2:
return 4
else:
return 0
class instruction:
def __init__(self,opstr,inststr,desc):
self.OpcodeString = opstr
self.InstructionString = inststr
self.Description = desc
self.Opcode = []
self.OpcodeSize = 0
self.OpcodeFlags = []
self.InstructionDef = tokenizeInstDef(self.InstructionString)
self.HasImmediate = False
self.ImmediateSize = 0 # no of bytes
self.HasModRM = False
self.ModRM = None
self.HasPrefixes = False
self.Prefixes = None
self.HasDisplacement = False
self.DisplacementSize = 0
self.setOpcodeAndFlags()
self.setHasFlags()
if '+rb' in self.OpcodeFlags:
self.loadRBWD('+rb','r8')
elif '+rw' in self.OpcodeFlags:
self.loadRBWD('+rw','r16')
elif '+rd' in self.OpcodeFlags:
self.loadRBWD('+rd','r32')
else:
opcodeDict[self.Opcode] = self
mnemonicDict[self.InstructionDef] = self
def loadRBWD(self,plus,reg):
for i in range(8):
OS = self.OpcodeString
IS = self.InstructionString
ID = self.Description
OS = OS.replace(plus,plus[1:])
OS = OS.replace("%X" % self.Opcode[0], '%X' % (self.Opcode[0] + i))
IS = IS.replace(reg, regOpcode[reg][i])
instruction(OS,IS,ID)
def setOpcodeAndFlags(self):
parts = self.OpcodeString.split()
for part in parts:
if len(part) == 2 and part[0] in "ABCDEF0123456789" \
and part[1] in "ABCDEF0123456789":
# suppose I could use a regex above
self.Opcode.append(eval("0x%s" % part))
else:
self.OpcodeFlags.append(part)
self.Opcode = tuple(self.Opcode)
self.OpcodeSize = len(self.Opcode)
def setHasFlags(self):
for i in instModRM:
if i in self.InstructionString:
if "+rb" in self.OpcodeFlags: break
if "+rw" in self.OpcodeFlags: break
if "+rd" in self.OpcodeFlags: break
self.HasModRM = True
break
for i in immediate:
if i in self.InstructionString:
#hack fix, how do we do this right?
#if i.startswith('m') and 'imm' in self.InstructionString:
# continue
self.HasImmediate = True
if i.endswith('8') or i == 'mo':
self.ImmediateSize = 1
elif i.endswith('16'):
self.ImmediateSize = 2
elif i.endswith('32'):
self.ImmediateSize = 4
else:
raise RuntimeError("Invalid Immediate Value")
break
for i in displacement:
if i in self.InstructionString:
self.HasDisplacement = True
if i.endswith('8'):
self.DisplacementSize = 1
elif i.endswith('16'):
self.DisplacementSize = 2
elif i.endswith('32'):
self.DisplacementSize = 4
else:
raise RuntimeError("Invalid Displacement Value")
break
#%TODO: figure out logic for SIB, and prefixes
def GetInstance(self):
return instructionInstance(self)
def __str__(self):
retVal = ""
retVal += self.OpcodeString + "\n"
retVal += self.InstructionString + "\n"
retVal += self.Description + "\n"
retVal += "OP: %s, OP flag: %s\n" % (self.Opcode,self.OpcodeFlags)
return retVal
i = instruction
RELATIVE,DIRECT = range(1,3)
class instructionInstance:
"""
An instructionInstance is an instruction + the data for an instance's
prefixes and suffixes
"""
def __init__(self,inst):
self.Address = 0x0
self.Instruction = inst
self.Prefixes = []
self.ModRM = None
self.SIB = None
self.Displacement = None
self.DisplacementSymbol = None
self.Immediate = None
self.ImmediateSymbol = None
def GetSymbolPatchins(self,modrm=None):
"locations of symbols if they exist"
retVal = []
size = len(self.Instruction.Opcode)
if self.Instruction.HasModRM:
size += 1
if self.ModRM:
mrm = self.ModRM
elif modrm == None:
raise OpcodeNeedsModRM()
else:
mrm = ModRM(modrm)
if mrm.HasSIB():
size += 1
if mrm.GetDisplacementSize():
if self.DisplacementSymbol:
retVal.append( (self.DisplacementSymbol,self.Address + size, RELATIVE) )
size += mrm.GetDisplacementSize()
if self.Instruction.HasDisplacement:
if self.DisplacementSymbol:
retVal.append( (self.DisplacementSymbol,self.Address + size, RELATIVE) )
size += self.Instruction.DisplacementSize
if self.Instruction.HasImmediate:
if self.ImmediateSymbol:
retVal.append( (self.ImmediateSymbol, self.Address + size, DIRECT))
size += self.Instruction.ImmediateSize
return retVal
def GetSuffixSize(self,modrm=None):
"Size for everything after Opcode"
size = 0
if self.Instruction.HasModRM:
size += 1
if self.ModRM:
mrm = self.ModRM
elif modrm == None:
raise OpcodeNeedsModRM()
else:
mrm = ModRM(modrm)
if mrm.HasSIB():
size += 1
if mrm.GetDisplacementSize():
size += mrm.GetDisplacementSize()
if self.Instruction.HasDisplacement:
size += self.Instruction.DisplacementSize
if self.Instruction.HasImmediate:
size += self.Instruction.ImmediateSize
return size
def GetInstructionSize(self):
return len(self.Instruction.Opcode) + self.GetSuffixSize()
def NextInstructionLoc(self):
return self.GetInstructionSize() + self.Address
def LoadData(self, data):
first,rest = '',data
if self.Instruction.HasModRM:
first,rest = rest[0],rest[1:]
self.ModRM = ModRM(struct.unpack("<b",first)[0])
if self.ModRM.HasSIB():
first,rest = rest[0],rest[1:]
self.SIB = struct.unpack("<b",first)[0]
if self.Instruction.HasDisplacement:
if self.Instruction.DisplacementSize == 1:
first,rest = rest[0],rest[1:]
self.Displacement = struct.unpack("<b",first)[0]
elif self.Instruction.DisplacementSize == 2:
first,rest = rest[:2],rest[2:]
self.Displacement = struct.unpack("<s",first)[0]
elif self.Instruction.DisplacementSize == 4:
first,rest = rest[:4],rest[4:]
self.Displacement = struct.unpack('<l',first)[0]
else:
raise RuntimeError("Invalid Displacement size")
if self.Instruction.HasModRM:
dispSize = self.ModRM.GetDisplacementSize()
if dispSize == 0:
pass
elif dispSize == 1:
first,rest = rest[0],rest[1:]
self.Displacement = struct.unpack("<b",first)[0]
elif dispSize == 4:
first,rest = rest[:4],rest[4:]
self.Displacement = struct.unpack('<l',first)[0]
else:
raise RuntimeError("Invalid Displacement size")
if self.Instruction.HasImmediate:
if self.Instruction.ImmediateSize == 1:
first,rest = rest[0],rest[1:]
self.Immediate = struct.unpack("<b",first)[0]
elif self.Instruction.ImmediateSize == 2:
first,rest = rest[:2],rest[2:]
self.Immediate = struct.unpack("<s",first)[0]
elif self.Instruction.ImmediateSize == 4:
first,rest = rest[:4],rest[4:]
self.Immediate = struct.unpack('<l',first)[0]
else:
raise RuntimeError("Invalid Immdediate size [%s]" % \
self.InstructionImmediateSize)
if rest:
raise RuntimeError("Couldn't unpack all data")
def DataText(self,data,size,skip=False):
retVal = ''
if skip:
return retVal
if size >= 1:
retVal += "%02X " % (data % 0xFF)
return retVal
def LoadConcreteValues(self, toks):
if type(toks) == type(""):
toks = tokenizeInst(toks)
logging.info("%s => %s" % (self.Instruction.InstructionString, toks))
tmpModRM = ModRM()
firstDef, restDef = (self.Instruction.InstructionDef[0],self.Instruction.InstructionDef[1:])
firstTok, restTok = toks[0],toks[1:]
while 1:
logging.info("TOK COMPARES: %s => %s" % (firstDef, firstTok))
if firstDef[0] in (OPCODE, COMMA, REGISTER):
#TODO: Can we handle this special case better?
# The special case is a m8/16/32 value that is constant
# and doesn't have an RM.
if firstDef[0] == REGISTER and firstDef[1][0] == '[' and \
firstTok[0] == LBRACKET:
firstTok, restTok = restTok[0],restTok[1:]
if firstTok[1] == firstDef[1][1:-1]:
firstTok, restTok = restTok[0],restTok[1:]
else:
raise x86instError("TOKEN MISMATCH '%s' '%s'" % \
(firstDef,firstTok))
elif firstDef[0] != firstTok[0]:
raise x86instError("These should be equal '%s' '%s'" % \
(firstDef, firstTok))
elif firstDef[0] == NUMBER:
if firstTok[0] != NUMBER or firstTok[1] != firstDef[1]:
raise x86instError("INVALID NUMBER '%s'" % repr(firstTok))
elif firstDef[0] == OPERAND:
if firstDef[1] in ('r/m32','r/m16','r/m8'):
#figure out r/m val
if firstTok[0] == REGISTER:
#figure out r val
registerName = firstTok[1]
registerType = firstDef[1][0] + firstDef[1][3:]
registerVal = regOpcode[registerType].index(registerName)
if registerVal < 0:
raise x86instError("Couldn't resolve register '%s'" % registerName)
else:
tmpModRM.Mode = 3
tmpModRM.RM = registerVal
elif firstTok[0] == LBRACKET:
firstTok, restTok = restTok[0],restTok[1:]
if firstTok[0] in (NUMBER,SYMBOL):
tmpModRM.Mode = 0
tmpModRM.RM = 6
if firstTok[0] == NUMBER:
self.Displacement = eval(firstTok[1])
else:
self.Displacement = 0x0
self.DisplacementSymbol = firstTok[1]
firstTok, restTok = restTok[0],restTok[1:]
elif firstTok[0] == REGISTER:
regTok = firstTok
firstTok, restTok = restTok[0],restTok[1:]
if firstTok[0] in (NUMBER,SYMBOL): #displacement
if firstTok[0] == NUMBER:
num = eval(firstTok[1])
if num >= -127 and num <= 128:
tmpModRM.Mode = 1
else:
tmpModRM.Mode = 2
else:
tmpModRM.Mode = 2
tmpModRM.RM = ['EAX','ECX','EDX','EBX',
'[--][--]','EBP','ESI',
'EDI'].index(regTok[1])
if firstTok[0] == NUMBER:
self.Displacement = eval(firstTok[1])
else:
self.Displacement = 0x0
self.DisplacementSymbol = firstTok[1]
firstTok, restTok = restTok[0],restTok[1:]
else: # no displacement
tmpModRM.Mode = 0
tmpModRM.RM = ['EAX','ECX','EDX','EBX',
'[--][--]','disp32','ESI',
'EDI'].index(regTok[1])
else:
raise x86instError("Invalid r/m token '%s'" % firstTok[0])
elif firstDef[1] in ('r32','r16','r8'):
#figure out r val
registerName = firstTok[1]
registerVal = regOpcode[firstDef[1]].index(registerName)
if registerVal < 0:
raise x86instError("Couldn't resolve register '%s'" % registerName)
else:
tmpModRM.RegOp = registerVal
elif firstDef[1] in ('imm32','imm16','imm8'):
if firstTok[0] == NUMBER:
self.Immediate = eval(firstTok[1])
else:
self.Immediate = 0x0
self.ImmediateSymbol = firstTok[1]
elif firstDef[1] in ('rel32','rel16','rel8'):
# Do we need to do the math here (convert absolute val to relative?)
if firstTok[0] == NUMBER:
self.Displacement = eval(firstTok[1])
else:
self.Displacement = 0x0
self.DisplacementSymbol = firstTok[1]
else:
#there will really be more cases here.
raise x86instError("Invalid Operand type '%s'" % firstDef[1])
else:
raise x86instError("Invalid token" , firstDef)
if not restDef:
break
firstDef, restDef = restDef[0],restDef[1:]
firstTok, restTok = restTok[0],restTok[1:]
for flag in self.Instruction.OpcodeFlags:
if flag in ['/0','/1','/2','/3','/4','/5','/6','/7']:
tmpModRM.RegOp = eval(flag[1])
self.ModRM = tmpModRM
def OpDataAsString(self):
"""
Return the OPCODE as a string.
"""
retVal = ''
for i in self.Instruction.Opcode:
retVal += chr(i)
if self.Instruction.HasModRM:
retVal += chr(self.ModRM.SaveToByte())
if self.ModRM.HasSIB():
retVal += chr(self.SIB)
disp = self.ModRM.GetDisplacementSize()
if disp == 1:
retVal += ''.join(longToString(self.Displacement,1))
elif disp == 4:
logging.error("DISPLACEMENT %s" % self.Displacement)
retVal += ''.join(longToString(self.Displacement,4))
if self.Instruction.HasDisplacement:
retVal += ''.join(longToString(self.Displacement,self.Instruction.DisplacementSize))
if self.Instruction.HasImmediate:
retVal += ''.join(longToString(self.Immediate,self.Instruction.ImmediateSize))
if len(retVal) != self.GetInstructionSize():
raise x86instError("Invalid Instruction Size '%s' '%s'" % (self.Instruction.InstructionString, \
retVal))
return retVal
def OpText(self):
size = 0
retVal = ''
retVal += " %08X: " % self.Address
ds = self.OpDataAsString()
for c in ds:
retVal += "%02X " % ord(c)
retVal += " " * (8-len(ds))
opcodeStr, operandStr = "",""
for typ,val in self.Instruction.InstructionDef:
if typ == OPCODE:
opcodeStr += val + " "
elif typ == COMMA:
operandStr += val
elif typ == REGISTER:
operandStr += val
elif typ == OPERAND:
#TODO: Cleanup here, remove strings in if statements
if val in immediate:
if self.ImmediateSymbol:
operandStr += self.ImmediateSymbol
else:
operandStr += "0x%X" % self.Immediate
elif val in displacement:
if self.DisplacementSymbol:
operandStr += self.DisplacementSymbol
else:
operandStr += "0x%X" % (self.Displacement +
self.NextInstructionLoc())
elif val in ('r8','r16','r32','mm','xmm','/digit','REG'):
operandStr += self.ModRM.RegOpString(val)
elif val in ('r/m8','r/m16','r/m32'):
if not self.ModRM:
raise x86instError("No RM found when we need one '%s'" % \
self.Instruction.InstructionString)
rmString = self.ModRM.RMString(val)
if rmString.find('disp8') >= 0:
rmString = rmString.replace('disp8',"0x%X" % \
self.Displacement)
if rmString.find('disp32') >= 0:
rmString = rmString.replace('disp32', "0x%X" % \
self.Displacement)
operandStr += rmString
elif val in ('m','m8','m16','m32'):
tmpVal = self.ModRM.RMString(val)
tmpVal = tmpVal.replace("+disp8", "%+X" % self.Displacement)
tmpVal = tmpVal.replace("+disp32", "%+X" % self.Displacement)
operandStr += tmpVal
else:
# should check for other types
operandStr += val
else:
raise RuntimeError("Invalid op type[%s %s]" % (typ,val))
retVal += "%-10s%-10s" % (opcodeStr, operandStr)
return retVal
i("04 ib", "ADD AL,imm8", "Add imm8 to AL")
i("05 iw", "ADD AX,imm16", "Add imm16 to AX")
i("05 id", "ADD EAX,imm32", "Add imm32 to EAX")
i("80 /0 ib", "ADD r/m8,imm8", "Add imm6 to r/m8")
i("81 /0 iw", "ADD r/m16,imm16", "Add imm16 to r/m16")
i("81 /0 id", "ADD r/m32,imm32", "Add imm32 to r/m32")
i("83 /0 ib", "ADD r/m16, imm8", "Add sign extended imm8 to r/m16")
i("83 /0 iw", "ADD r/m32,imm8", "Add sign extended imm8 to r/m32")
i("00 /r", "ADD r/m8,r8", "Add r8 to r/m8")
i("01 /r", "ADD r/m16,r16", "Add r16 to r/m16")
i("01 /r", "ADD r/m32,r32", "Add r32 to r/m32")
i("02 /r", "ADD r8,r/m8", "Add r/m8 to r/8")
i("03 /r", "ADD r16,r/m16", "Add r/m16 to r16")
i("03 /r", "ADD r32,r/m32", "Add r/m32 to r32")
i("E8 cw", "CALL rel16", "Call near, relative, displacement relative to next instruction")
i("E8 cd", "CALL rel32", "Call near, relative, displacement relative to next instruction")
i("FF /2", "CALL r/m16", "Call near, absolute indirect, address given in r/m16")
i("FF /2", "CALL r/m32", "Call near, absolute indirect, address given in r/m32")
i("9A cd", "CALL ptr16:16", "Call far, absolute, address given in operand")
i("9A cp", "CALL ptr32:32", "Call far, absolute, address given in operand")
i("FF /3", "CALL m16:16", "Call far, absolute indirect, address given in m16:16")
i("FF /3", "CALL m32:32", "Call far, absolute indirect, address given in m32:32")
i("3C ib", "CMP AL,imm8", "Compare imm8 with AL.")
i("3D iw", "CMP AX,imm16", "Compare imm16 with AX.")
i("3D id", "CMP EAX,imm32", "Compare imm32 with EAX.")
i("80 /7 ib", "CMP r/m8,imm8", "Compare imm8 with r/m8.")
i("81 /7 iw", "CMP r/m16,imm16", "Compare imm16 with r/m16.")
i("81 /7 id", "CMP r/m32,imm32", "Compare imm32 with r/m32.")
i("83 /7 ib", "CMP r/m16,imm8", "Compare imm8 with r/m16.")
i("83 /7 ib", "CMP r/m32,imm8", "Compare imm8 with r/m32.")
i("38 /r", "CMP r/m8,r8", "Compare r8 with r/m8.")
i("39 /r", "CMP r/m16,r16", "Compare r16 with r/m16.")
i("39 /r", "CMP r/m32,r32", "Compare r32 with r/m32.")
i("3A /r", "CMP r8,r/m8", "Compare r/m8 with r8.")
i("3B /r", "CMP r16,r/m16", "Compare r/m16 with r16.")
i("3B /r", "CMP r32,r/m32", "Compare r/m32 with r32.")
i("FE /1", "DEC r/m8", "Decrement r/m8 by 1.")
i("FF /1", "DEC r/m16", "Decrement r/m16 by 1.")
i("FF /1", "DEC r/m32", "Decrement r/m32 by 1.")
i("48+rw", "DEC r16", "Decrement r16 by 1.")
i("48+rd", "DEC r32", "Decrement r32 by 1.")
i("FE /0", "INC r/m8", "Increment r/m byte by 1.")
i("FF /0", "INC r/m16", "Increment r/m word by 1.")
i("FF /0", "INC r/m32", "Increment r/m doubleword by 1.")
i("40+ rw", "INC r16", "Increment word register by 1.")
i("40+ rd", "INC r32", "Increment doubleword register by 1.")
i("CC", "INT 3", "Interrupt 3 - trap to debugger.")
i("CD ib", "INT imm8", "Interrupt vector number specified by immediate byte.")
i("CE", "INTO", "Interrupt 4 - if overflow flag is 1.")
i("77 cb", "JA rel8", "Jump short if above (CF=0 and ZF=0).")
i("73 cb", "JAE rel8", "Jump short if above or equal (CF=0).")
i("72 cb", "JB rel8", "Jump short if below (CF=1).")
i("76 cb", "JBE rel8", "Jump short if below or equal (CF=1 or ZF=1).")
i("72 cb", "JC rel8", "Jump short if carry (CF=1).")
i("E3 cb", "JCXZ rel8", "Jump short if CX register is 0.")
i("E3 cb", "JECXZ rel8", "Jump short if ECX register is 0.")
i("74 cb", "JE rel8", "Jump short if equal (ZF=1).")
i("7F cb", "JG rel8", "Jump short if greater (ZF=0 and SF=OF).")
i("7D cb", "JGE rel8", "Jump short if greater or equal (SF=OF).")
i("7C cb", "JL rel8", "Jump short if less (SF<>OF).")
i("7E cb", "JLE rel8", "Jump short if less or equal (ZF=1 or SF<>OF).")
i("76 cb", "JNA rel8", "Jump short if not above (CF=1 or ZF=1).")
i("72 cb", "JNAE rel8", "Jump short if not above or equal (CF=1).")
i("73 cb", "JNB rel8", "Jump short if not below (CF=0).")
i("77 cb", "JNBE rel8", "Jump short if not below or equal (CF=0 and ZF=0).")
i("73 cb", "JNC rel8", "Jump short if not carry (CF=0).")
i("75 cb", "JNE rel8", "Jump short if not equal (ZF=0).")
i("7E cb", "JNG rel8", "Jump short if not greater (ZF=1 or SF<>OF).")
i("7C cb", "JNGE rel8", "Jump short if not greater or equal (SF<>OF).")
i("7D cb", "JNL rel8", "Jump short if not less (SF=OF).")
i("7F cb", "JNLE rel8", "Jump short if not less or equal (ZF=0 and SF=OF).")
i("71 cb", "JNO rel8", "Jump short if not overflow (OF=0).")
i("7B cb", "JNP rel8", "Jump short if not parity (PF=0).")
i("79 cb", "JNS rel8", "Jump short if not sign (SF=0).")
i("75 cb", "JNZ rel8", "Jump short if not zero (ZF=0).")
i("70 cb", "JO rel8", "Jump short if overflow (OF=1).")
i("7A cb", "JP rel8", "Jump short if parity (PF=1).")
i("7A cb", "JPE rel8", "Jump short if parity even (PF=1).")
i("7B cb", "JPO rel8", "Jump short if parity odd (PF=0).")
i("78 cb", "JS rel8", "Jump short if sign (SF=1).")
i("74 cb", "JZ rel8", "Jump short if zero (ZF = 1).")
i("0F 87 cw", "JA rel16", "Jump near if above (CF=0 and ZF=0).")
i("0F 87 cd", "JA rel32", "Jump near if above (CF=0 and ZF=0).")
i("0F 83 cw", "JAE rel16", "Jump near if above or equal (CF=0).")
i("0F 83 cd", "JAE rel32", "Jump near if above or equal (CF=0).")
i("0F 82 cw", "JB rel16", "Jump near if below (CF=1).")
i("0F 82 cd", "JB rel32", "Jump near if below (CF=1).")
i("0F 86 cw", "JBE rel16", "Jump near if below or equal (CF=1 or ZF=1).")
i("0F 86 cd", "JBE rel32", "Jump near if below or equal (CF=1 or ZF=1).")
i("0F 82 cw", "JC rel16", "Jump near if carry (CF=1).")
i("0F 82 cd", "JC rel32", "Jump near if carry (CF=1).")
i("0F 84 cw", "JE rel16", "Jump near if equal (ZF=1).")
i("0F 84 cd", "JE rel32", "Jump near if equal (ZF=1).")
i("0F 84 cw", "JZ rel16", "Jump near if 0 (ZF=1).")
i("0F 84 cd", "JZ rel32", "Jump near if 0 (ZF=1).")
i("0F 8F cw", "JG rel16", "Jump near if greater (ZF=0 and SF=OF).")
i("0F 8F cd", "JG rel32", "Jump near if greater (ZF=0 and SF=OF).")
i("0F 8D cw", "JGE rel16", "Jump near if greater or equal (SF=OF).")
i("0F 8D cd", "JGE rel32", "Jump near if greater or equal (SF=OF).")
i("0F 8C cw", "JL rel16", "Jump near if less (SF<>OF).")
i("0F 8C cd", "JL rel32", "Jump near if less (SF<>OF).")
i("0F 8E cw", "JLE rel16", "Jump near if less or equal (ZF=1 or SF<>OF).")
i("0F 8E cd", "JLE rel32", "Jump near if less or equal (ZF=1 or SF<>OF).")
i("0F 86 cw", "JNA rel16", "Jump near if not above (CF=1 or ZF=1).")
i("0F 86 cd", "JNA rel32", "Jump near if not above (CF=1 or ZF=1).")
i("0F 82 cw", "JNAE rel16", "Jump near if not above or equal (CF=1).")
i("0F 82 cd", "JNAE rel32", "Jump near if not above or equal (CF=1).")
i("0F 83 cw", "JNB rel16", "Jump near if not below (CF=0).")
i("0F 83 cd", "JNB rel32", "Jump near if not below (CF=0).")
i("0F 87 cw", "JNBE rel16", "Jump near if not below or equal (CF=0 and ZF=0)")
i("0F 87 cd", "JNBE rel32", "Jump near if not below or equal (CF=0 and ZF=0)")
i("0F 83 cw", "JNC rel16", "Jump near if not carry (CF=0).")
i("0F 83 cd", "JNC rel32", "Jump near if not carry (CF=0).")
i("0F 85 cw", "JNE rel16", "Jump near if not equal (ZF=0).")
i("0F 85 cd", "JNE rel32", "Jump near if not equal (ZF=0).")
i("0F 8E cw", "JNG rel16", "Jump near if not greater (ZF=1 or SF<>OF).")
i("0F 8E cd", "JNG rel32", "Jump near if not greater (ZF=1 or SF<>OF).")
i("0F 8C cw", "JNGE rel16", "Jump near if not greater or equal (SF<>OF).")
i("0F 8C cd", "JNGE rel32", "Jump near if not greater or equal (SF<>OF).")
i("0F 8D cw", "JNL rel16", "Jump near if not less (SF=OF).")
i("0F 8D cd", "JNL rel32", "Jump near if not less (SF=OF).")
i("0F 8F cw", "JNLE rel16", "Jump near if not less or equal (ZF=0 and SF=OF).")
i("0F 8F cd", "JNLE rel32", "Jump near if not less or equal (ZF=0 and SF=OF).")
i("0F 81 cw", "JNO rel16", "Jump near if not overflow (OF=0).")
i("0F 81 cd", "JNO rel32", "Jump near if not overflow (OF=0).")
i("0F 8B cw", "JNP rel16", "Jump near if not parity (PF=0).")
i("0F 8B cd", "JNP rel32", "Jump near if not parity (PF=0).")
i("0F 89 cw", "JNS rel16", "Jump near if not sign (SF=0).")
i("0F 89 cd", "JNS rel32", "Jump near if not sign (SF=0).")
i("0F 85 cw", "JNZ rel16", "Jump near if not zero (ZF=0).")
i("0F 85 cd", "JNZ rel32", "Jump near if not zero (ZF=0).")
i("0F 80 cw", "JO rel16", "Jump near if overflow (OF=1).")
i("0F 80 cd", "JO rel32", "Jump near if overflow (OF=1).")
i("0F 8A cw", "JP rel16", "Jump near if parity (PF=1).")
i("0F 8A cd", "JP rel32", "Jump near if parity (PF=1).")
i("0F 8A cw", "JPE rel16", "Jump near if parity even (PF=1).")
i("0F 8A cd", "JPE rel32", "Jump near if parity even (PF=1).")
i("0F 8B cw", "JPO rel16", "Jump near if parity odd (PF=0).")
i("0F 8B cd", "JPO rel32", "Jump near if parity odd (PF=0).")
i("0F 88 cw", "JS rel16", "Jump near if sign (SF=1).")
i("0F 88 cd", "JS rel32", "Jump near if sign (SF=1).")
i("EB cb", "JMP rel8", "Jump short, relative, displacement relative to next instruction.")
i("E9 cw", "JMP rel16", "Jump near, relative, displacement relative to next instruction.")
i("E9 cd", "JMP rel32", "Jump near, relative, displacement relative to next instruction.")
i("FF /4", "JMP r/m16", "Jump near, absolute indirect, address given in r/m16.")
i("FF /4", "JMP r/m32", "Jump near, absolute indirect, address given in r/m32.")
#i("EA cd", "JMP ptr16:16", "Jump far, absolute, address given in operand.")
#i("EA cp", "JMP ptr16:32", "Jump far, absolute, address given in operand.")
#i("FF /5", "JMP m16:16", "Jump far, absolute indirect, address given in m16:16.")
#i("FF /5", "JMP m16:32", "Jump far, absolute indirect, address given in m16:32.")
#changed def here. Should be 'm'
i("8D /r", "LEA r16,m16", "Store effective address for m in register r16.")
i("8D /r", "LEA r32,m32", "Store effective address for m in register r32")
i("88 /r","MOV r/m8,r8","Move r8 to r/m8.")
i("89 /r","MOV r/m16,r16","Move r16 to r/m16.")
i("89 /r", "MOV r/m32,r32", "Move r32 to r/m32")
i("8A /r","MOV r8,r/m8","Move r/m8 to r8")
i("8B /r", "MOV r16,r/m16","Move r/m16 to r16")
i("8B /r","MOV r32,r/m32", "Move r/m32 to r32")
i("8C /r", "MOV r/m16,Sreg", "Move Segment register to r/m16")
i("8E /r", "MOV Sreg,r/m16", "Move r/m16 to Segment Register")
i("A0", "MOV AL,moffs8", "Move byte at (sef:offset) to AL.")
i("A1", "MOV AX,moffs16", "Move word at (seg:offset) to AX.")
i("A1", "MOV EAX,moffs32","Move doubleword at (seg:offset) to EAX.")
i("A2","MOV moffs8,AL","Move AL to (seg:offset)")
i("A3", "MOV moffs16,AX", "Move AX to (seg:offset)")
i("B0 +rb","MOV r8,imm8", "Move imm8 to r8")
i("B8 +rw", "MOV r16,imm16","Move imm16 to r16")
i("B8 +rd", "MOV r32,imm32", "Move imm32 to r32")
i("C6 /0", "MOV r/m8,imm8", "Move imm8 to r/m8")
i("C7 /0", "MOV r/m16,imm16", "Move imm16 to r/m16")
i("C7 /0", "MOV r/m32,imm32", "Move imm32 to r/m32")
i("90","NOP","No operation.")
i("8F /0", "POP r/m16", "Pop top of stack into m16; increment stack pointer.")
i("8F /0", "POP r/m32", "Pop top of stack into m32; increment stack pointer.")
i("58 +rw", "POP r16", "Pop top of stack into r16; increment stack pointer.")
i("58 +rd", "POP r32", "Pop top of stack into r32; increment stack pointer.")
i("1F", "POP DS", "Pop top of stack into DS; increment stack pointer.")
i("07", "POP ES", "Pop top of stack into ES; increment stack pointer.")
i("17", "POP SS", "Pop top of stack into SS; increment stack pointer.")
i("0F A1", "POP FS", "Pop top of stack into FS; increment stack pointer.")
i("0F A9", "POP GS", "Pop top of stack into GS; increment stack pointer.")
i("FF /6", "PUSH r/m16", "Push r/m16.")
i("FF /6", "PUSH r/m32", "PUSH r/m32.")
i("50 +rw", "PUSH r16", "Push r16.")
i("50 +rd", "PUSH r32", "Push r32.")
i("6A", "PUSH imm8", "Push imm8.")
i("68", "PUSH imm16", "push imm16.")
i("68", "PUSH imm32", "Push imm32.")
i("0E", "PUSH CS", 'Push CS')
i("16", "PUSH SS", "Push SS")
i("1E", "PUSH DS", "Push DS")
i("06", "PUSH ES", "PUsh ES")
i("0F A0", "PUSH FS", "Push FS.")
i("0F A8", "PUSH GS", "Push GS.")
i("F3 6C", "REP INS m8,DX" ,"Input (E)CX bytes from port DX into ES:[(E)DI].")
i("F3 6D", "REP INS m16,DX", "Input (E)CX words from port DX into ES:[(E)DI].")
i("F3 6D", "REP INS m32,DX", "Input (E)CX doublewords from port DX into ES:[(E)DI].")
i("F3 A4", "REP MOVS m8,m8", "Move (E)CX bytes from DS:[(E)SI] to ES:[(E)DI].")
i("F3 A5", "REP MOVS m16,m16","Move (E)CX words from DS:[(E)SI] to ES:[(E)DI].")
i("F3 A5", "REP MOVS m32,m32", "Move (E)CX doublewords from DS:[(E)SI] to ES:[(E)DI].")
i("F3 6E", "REP OUTS DX,r/m8","Output (E)CX bytes from DS:[(E)SI] to port DX.")
i("F3 6F", "REP OUTS DX,r/m16","Output (E)CX words from DS:[(E)SI] to port DX.")
i("F3 6F", "REP OUTS DX,r/m32", "Output (E)CX doublewords from DS:[(E)SI] to port DX.")
i("F3 AC", "REP LODS AL" ,"Load (E)CX bytes from DS:[(E)SI] to AL.")
i("F3 AD", "REP LODS AX", "Load (E)CX words from DS:[(E)SI] to AX.")
i("F3 AD", "REP LODS EAX", "Load (E)CX doublewords from DS:[(E)SI] to EAX.")
i("F3 AA", "REP STOS m8", "Fill (E)CX bytes at ES:[(E)DI] with AL.")
i("F3 AB", "REP STOS m16", "Fill (E)CX words at ES:[(E)DI] with AX.")
#i("F3 AB", "REP STOS m32", "Fill (E)CX words at ES:[(E)DI] with AX.")
i("F3 AB", "REP STOS [EDI]" ,"Fill (E)CX doublewords at ES:[(E)DI] with EAX.")
i("F3 A6", "REPE CMPS m8,m8", "Find nonmatching bytes in ES:[(E)DI] and DS:[(E)SI].")
i("F3 A7", "REPE CMPS m16,m16", "Find nonmatching words in ES:[(E)DI] and DS:[(E)SI].")
i("F3 A7", "REPE CMPS m32,m32","Find nonmatching doublewords in ES:[(E)DI] and DS:[(E)SI].")
i("F3 AE", "REPE SCAS m8", "Find non-AL byte starting at ES:[(E)DI].")
i("F3 AF", "REPE SCAS m16", "Find non-AX word starting at ES:[(E)DI].")
i("F3 AF", "REPE SCAS m32", "Find non-EAX doubleword starting at ES:[(E)DI].")
i("F2 A6", "REPNE CMPS m8,m8", "Find matching bytes in ES:[(E)DI] and DS:[(E)SI].")
i("F2 A7", "REPNE CMPS m16,m16", "Find matching words in ES:[(E)DI] and DS:[(E)SI].")
i("F2 A7", "REPNE CMPS m32,m32", "Find matching doublewords in ES:[(E)DI] and DS:[(E)SI].")
i("F2 AE", "REPNE SCAS m8", "Find AL, starting at ES:[(E)DI].")
i("F2 AF", "REPNE SCAS m16", "Find AX, starting at ES:[(E)DI].")
i("F2 AF", "REPNE SCAS m32", "Find EAX, starting at ES:[(E)DI].")
i("C3", "RET", "Near return to calling procedure")
#i("CB", "RET", "Far Return to calling procedure")
i("C2 iw", "RET imm16", "Near return to calling procedure and pop imm16 bytes from stack")
#i("CA iw", "RET imm32", "Far Return to calling procedure and pop imm16 bytes from the stack")
#AA STOS m8 Store AL at address ES:(E)DI.
#AB STOS m16 Store AX at address ES:(E)DI.
#AB STOS m32 Store EAX at address ES:(E)DI.
i("AA" , "STOSB", "Store AL at address ES:(E)DI.")
i("AB", "STOSW", "Store AX at address ES:(E)DI.")
i("AB", "STOSD", "Store EAX at address ES:(E)DI.")
i("2C ib", "SUB AL,imm8", "Subtract imm8 from AL.")
i("2D iw", "SUB AX,imm16", "Subtract imm16 from AX.")
i("2D id", "SUB EAX,imm32", "Subtract imm32 from EAX.")
i("80 /5 ib", "SUB r/m8,imm8", "Subtract imm8 from r/m8")
i("81 /5 iw", "SUB r/m16,imm16", "Subrtact imm16 from r/m16")
i("81 /5 id", "SUB r/m32,imm32", "Subrtract imm32 from r/m32")
i("83 /5 ib", "SUB r/m16,imm8", "Subtract imm8 from r/m16")
i("83 /5 id", "SUB r/m32,imm8", "Subtract imm8 from r/m32")
i("28 /r", "SUB r/m8,r8", "Subtract r8 from r/m8")
i("29 /r", "SUB r/m16,r16", "Subtract r16 from r/m16")
i("29 /r", "SUB r/m32,r32", "Subtract r32 from r/m32")
i("2A /r", "SUB r8,r/m8", "Subtract r/m8 from r8")
i("2B /r", "SUB r16,r/m16","Subtract r/m16 from r16")
i("2B /r", "SUB r32,r/m32", "Subtract r/m32 from r32")
i("A8 ib", "TEST AL,imm8", "AND imm8 with AL; set SF, ZF, PF according to result.")
i("A9 iw", "TEST AX,imm16", "AND imm16 with AX; set SF, ZF, PF according to result.")
i("A9 id", "TEST EAX,imm32", "AND imm32 with EAX; set SF, ZF, PF according to result.")
i("F6 /0 ib", "TEST r/m8,imm8", "AND imm8 with r/m8; set SF, ZF, PF according to result.")
i("F7 /0 iw", "TEST r/m16,imm16", "AND imm16 with r/m16; set SF, ZF, PF according to result.")
i("F7 /0 id", "TEST r/m32,imm32", "AND imm32 with r/m32; set SF, ZF, PF according to result.")
i("84 /r", "TEST r/m8,r8", "AND r8 with r/m8; set SF, ZF, PF according to result.")
i("85 /r", "TEST r/m16,r16", "AND r16 with r/m16; set SF, ZF, PF according to result.")
i("85 /r", "TEST r/m32,r32", "AND r32 with r/m32; set SF, ZF, PF according to result.")
i("34 ib", "XOR AL, imm8", "AL XOR imm8.")
i("35 iw", "XOR AX,imm16", "AX XOR imm16.")
i("35 id", "XOR EAX,imm32", "EAX XOR imm32.")
i("80 /6 ib", "XOR r/m8,imm8", "r/m8 XOR imm8.")
i("81 /6 iw", "XOR r/m16,imm16", "r/m16 xor imm16")
i("81 /6 iw", "XOR r/m32,imm32", "r/m32 xor imm32")
i("83 /6 ib", "XOR r/m16,imm8", "r/m16 XOR imm8 (sign-extended)")
i("83 /6 iw", "XOR r/m32,imm8", "r/m32 XOR imm8 (sign-extended)")
i("30 /r", "XOR r/m8,r8", "r/m8 XOR r8.")
i("31 /r", "XOR r/m16,r16", "r/m16 XOR r16")
i("31 /r", "XOR r/m32,r32", "r/m32 XOR r32")
i("32 /r", "XOR r8,r/m8", "r8 XOR r/m8")
i("33 /r", "XOR r16,r/m16", "r16 XOR r/m16")
i("33 /r", "XOR r32,r/m32", "r32 XOR r/m32")