1 #include <assert.h>
2 #include <stdexcept>
3 #include "X86Assembler.h"
4 #include "LiteralPool.h"
5
Begin()6 void CX86Assembler::Begin()
7 {
8 m_nextLabelId = 1;
9 m_nextLiteral128Id = 1;
10 m_currentLabel = nullptr;
11 m_tmpStream.ResetBuffer();
12 m_labels.clear();
13 m_labelOrder.clear();
14 }
15
End()16 void CX86Assembler::End()
17 {
18 //Mark last label
19 if(m_currentLabel != nullptr)
20 {
21 uint32 currentPos = static_cast<uint32>(m_tmpStream.Tell());
22 m_currentLabel->size = currentPos - m_currentLabel->start;
23 }
24
25 //Initialize
26 for(auto& labelPair : m_labels)
27 {
28 auto& label = labelPair.second;
29 label.projectedStart = label.start;
30 }
31
32 while(1)
33 {
34 bool changed = false;
35
36 for(LabelArray::const_iterator labelIterator(m_labelOrder.begin());
37 labelIterator != m_labelOrder.end(); ++labelIterator)
38 {
39 auto& label = m_labels[*labelIterator];
40
41 for(LabelRefArray::iterator labelRefIterator(label.labelRefs.begin());
42 labelRefIterator != label.labelRefs.end(); ++labelRefIterator)
43 {
44 auto& labelRef(*labelRefIterator);
45 switch(labelRef.length)
46 {
47 case JMP_NOTSET:
48 {
49 //Assume a short jump first.
50 unsigned int jumpSize = GetJumpSize(labelRef.type, JMP_NEAR);
51 labelRef.length = JMP_NEAR;
52 IncrementJumpOffsetsLocal(label, labelRefIterator + 1, jumpSize);
53 IncrementJumpOffsets(labelIterator + 1, jumpSize);
54 changed = true;
55 }
56 break;
57 case JMP_NEAR:
58 {
59 //We need to verify if the jump is still good for us, since sizes might have changed
60 LABELINFO& referencedLabel(m_labels[labelRef.label]);
61 unsigned int smallJumpSize = GetJumpSize(labelRef.type, JMP_NEAR);
62 uint32 offset = referencedLabel.projectedStart - (labelRef.offset + smallJumpSize);
63 uint32 offsetSize = GetMinimumConstantSize(offset);
64 if(offsetSize != 1)
65 {
66 //Doesn't fit, recompute offsets
67 labelRef.length = JMP_FAR;
68 unsigned int longJumpSize = GetJumpSize(labelRef.type, JMP_FAR);
69 unsigned int incrementAmount = longJumpSize - smallJumpSize;
70 IncrementJumpOffsetsLocal(label, labelRefIterator + 1, incrementAmount);
71 IncrementJumpOffsets(labelIterator + 1, incrementAmount);
72 changed = true;
73 }
74 }
75 break;
76 }
77 }
78 }
79
80 if(!changed) break;
81 }
82
83 assert(m_outputStream != nullptr);
84 m_tmpStream.Seek(0, Framework::STREAM_SEEK_SET);
85
86 for(const auto& labelId : m_labelOrder)
87 {
88 const auto& label = m_labels[labelId];
89
90 unsigned int currentPos = label.start;
91 unsigned int currentProjectedPos = label.projectedStart;
92 unsigned int endPos = label.start + label.size;
93
94 for(const auto& labelRef : label.labelRefs)
95 {
96 const auto& referencedLabel(m_labels[labelRef.label]);
97
98 unsigned int readSize = labelRef.offset - currentProjectedPos;
99 if(readSize != 0)
100 {
101 m_copyBuffer.resize(readSize);
102 m_tmpStream.Read(m_copyBuffer.data(), readSize);
103 m_outputStream->Write(m_copyBuffer.data(), readSize);
104 }
105
106 //Write our jump here.
107 unsigned int jumpSize = GetJumpSize(labelRef.type, labelRef.length);
108 uint32 distance = referencedLabel.projectedStart - (labelRef.offset + jumpSize);
109 WriteJump(m_outputStream, labelRef.type, labelRef.length, distance);
110
111 currentProjectedPos += readSize + jumpSize;
112 currentPos += readSize;
113 }
114
115 unsigned int lastCopySize = endPos - currentPos;
116 if(lastCopySize != 0)
117 {
118 m_copyBuffer.resize(lastCopySize);
119 m_tmpStream.Read(m_copyBuffer.data(), lastCopySize);
120 m_outputStream->Write(m_copyBuffer.data(), lastCopySize);
121 }
122 }
123
124 ResolveLiteralReferences();
125 }
126
IncrementJumpOffsets(LabelArray::const_iterator startLabel,unsigned int amount)127 void CX86Assembler::IncrementJumpOffsets(LabelArray::const_iterator startLabel, unsigned int amount)
128 {
129 for(LabelArray::const_iterator labelIterator(startLabel);
130 labelIterator != m_labelOrder.end(); ++labelIterator)
131 {
132 LABELINFO& label = m_labels[*labelIterator];
133 label.projectedStart += amount;
134 IncrementJumpOffsetsLocal(label, label.labelRefs.begin(), amount);
135 }
136 }
137
IncrementJumpOffsetsLocal(LABELINFO & label,LabelRefArray::iterator startJump,unsigned int amount)138 void CX86Assembler::IncrementJumpOffsetsLocal(LABELINFO& label, LabelRefArray::iterator startJump, unsigned int amount)
139 {
140 for(LabelRefArray::iterator labelRefIterator(startJump);
141 labelRefIterator != label.labelRefs.end(); ++labelRefIterator)
142 {
143 auto& labelRef(*labelRefIterator);
144
145 //Make sure any literal ref happens before a label ref
146 for(const auto& literalRefPair : label.literal128Refs)
147 {
148 const auto& literalRef = literalRefPair.second;
149 assert(literalRef.offset < labelRef.offset);
150 }
151
152 labelRef.offset += amount;
153 }
154 }
155
SetStream(Framework::CStream * stream)156 void CX86Assembler::SetStream(Framework::CStream* stream)
157 {
158 m_outputStream = stream;
159 }
160
MakeRegisterAddress(REGISTER nRegister)161 CX86Assembler::CAddress CX86Assembler::MakeRegisterAddress(REGISTER nRegister)
162 {
163 CAddress Address;
164
165 if(nRegister > 7)
166 {
167 Address.nIsExtendedModRM = true;
168 nRegister = static_cast<REGISTER>(nRegister & 7);
169 }
170
171 Address.ModRm.nMod = 3;
172 Address.ModRm.nRM = nRegister;
173
174 return Address;
175 }
176
MakeXmmRegisterAddress(XMMREGISTER registerId)177 CX86Assembler::CAddress CX86Assembler::MakeXmmRegisterAddress(XMMREGISTER registerId)
178 {
179 return MakeRegisterAddress(static_cast<REGISTER>(registerId));
180 }
181
MakeByteRegisterAddress(BYTEREGISTER registerId)182 CX86Assembler::CAddress CX86Assembler::MakeByteRegisterAddress(BYTEREGISTER registerId)
183 {
184 auto address = MakeRegisterAddress(static_cast<REGISTER>(registerId));
185 address.usesLegacyByteRegister = true;
186 return address;
187 }
188
MakeIndRegAddress(REGISTER registerId)189 CX86Assembler::CAddress CX86Assembler::MakeIndRegAddress(REGISTER registerId)
190 {
191 CAddress address;
192
193 //Cannot be done with rBP
194 assert(registerId != rBP);
195 if(registerId == r13)
196 {
197 return MakeIndRegOffAddress(registerId, 0);
198 }
199
200 if(registerId == rSP)
201 {
202 registerId = static_cast<REGISTER>(4);
203 address.sib.scale = 0;
204 address.sib.index = 4;
205 address.sib.base = 4;
206 }
207 else if(registerId == r12)
208 {
209 registerId = static_cast<REGISTER>(4);
210 address.sib.scale = 0;
211 address.sib.index = 4;
212 address.sib.base = 4;
213 address.nIsExtendedModRM = true;
214 }
215
216 if(registerId > 7)
217 {
218 address.nIsExtendedModRM = true;
219 registerId = static_cast<REGISTER>(registerId & 7);
220 }
221
222 address.ModRm.nMod = 0;
223 address.ModRm.nRM = registerId;
224 return address;
225 }
226
MakeIndRegOffAddress(REGISTER nRegister,uint32 nOffset)227 CX86Assembler::CAddress CX86Assembler::MakeIndRegOffAddress(REGISTER nRegister, uint32 nOffset)
228 {
229 if(
230 (nOffset == 0) &&
231 (nRegister != CX86Assembler::rBP) &&
232 (nRegister != CX86Assembler::r13)
233 )
234 {
235 return MakeIndRegAddress(nRegister);
236 }
237
238 CAddress Address;
239
240 if(nRegister == rSP)
241 {
242 nRegister = static_cast<REGISTER>(4);
243 Address.sib.scale = 0;
244 Address.sib.index = 4;
245 Address.sib.base = 4;
246 }
247 else if(nRegister == r12)
248 {
249 nRegister = static_cast<REGISTER>(4);
250 Address.nIsExtendedModRM = true;
251 Address.sib.scale = 0;
252 Address.sib.index = 4;
253 Address.sib.base = 4;
254 }
255
256 if(nRegister > 7)
257 {
258 Address.nIsExtendedModRM = true;
259 nRegister = static_cast<REGISTER>(nRegister & 7);
260 }
261
262 if(GetMinimumConstantSize(nOffset) == 1)
263 {
264 Address.ModRm.nMod = 1;
265 Address.nOffset = static_cast<uint8>(nOffset);
266 }
267 else
268 {
269 Address.ModRm.nMod = 2;
270 Address.nOffset = nOffset;
271 }
272
273 Address.ModRm.nRM = nRegister;
274
275 return Address;
276 }
277
MakeBaseIndexScaleAddress(REGISTER base,REGISTER index,uint8 scale)278 CX86Assembler::CAddress CX86Assembler::MakeBaseIndexScaleAddress(REGISTER base, REGISTER index, uint8 scale)
279 {
280 if(base == rBP)
281 {
282 throw std::runtime_error("Invalid base.");
283 }
284 if(base == r13)
285 {
286 return MakeBaseOffIndexScaleAddress(base, 0, index, scale);
287 }
288 if(index == rSP)
289 {
290 throw std::runtime_error("Invalid index.");
291 }
292
293 CAddress address;
294 address.ModRm.nRM = 4;
295
296 if(base > 7)
297 {
298 address.nIsExtendedModRM = true;
299 base = static_cast<REGISTER>(base & 7);
300 }
301 if(index > 7)
302 {
303 address.nIsExtendedSib = true;
304 index = static_cast<REGISTER>(index & 7);
305 }
306 address.sib.base = base;
307 address.sib.index = index;
308 switch(scale)
309 {
310 case 1:
311 address.sib.scale = 0;
312 break;
313 case 2:
314 address.sib.scale = 1;
315 break;
316 case 4:
317 address.sib.scale = 2;
318 break;
319 case 8:
320 address.sib.scale = 3;
321 break;
322 default:
323 throw std::runtime_error("Invalid scale.");
324 break;
325 }
326
327 return address;
328 }
329
MakeBaseOffIndexScaleAddress(REGISTER base,uint32 offset,REGISTER index,uint8 scale)330 CX86Assembler::CAddress CX86Assembler::MakeBaseOffIndexScaleAddress(REGISTER base, uint32 offset, REGISTER index, uint8 scale)
331 {
332 //This could also be rBP, but untested for now
333 if(base != r13)
334 {
335 throw std::runtime_error("Invalid base.");
336 }
337 if(index == rSP)
338 {
339 throw std::runtime_error("Invalid index.");
340 }
341
342 CAddress address;
343 address.ModRm.nRM = 4;
344
345 if(base > 7)
346 {
347 address.nIsExtendedModRM = true;
348 base = static_cast<REGISTER>(base & 7);
349 }
350 if(index > 7)
351 {
352 address.nIsExtendedSib = true;
353 index = static_cast<REGISTER>(index & 7);
354 }
355 address.sib.base = base;
356 address.sib.index = index;
357 switch(scale)
358 {
359 case 1:
360 address.sib.scale = 0;
361 break;
362 case 2:
363 address.sib.scale = 1;
364 break;
365 case 4:
366 address.sib.scale = 2;
367 break;
368 case 8:
369 address.sib.scale = 3;
370 break;
371 default:
372 throw std::runtime_error("Invalid scale.");
373 break;
374 }
375
376 if(GetMinimumConstantSize(offset) == 1)
377 {
378 address.ModRm.nMod = 1;
379 address.nOffset = static_cast<uint8>(offset);
380 }
381 else
382 {
383 address.ModRm.nMod = 2;
384 address.nOffset = offset;
385 }
386
387 return address;
388 }
389
MakeLiteral128Address(LITERAL128ID literalId)390 CX86Assembler::CAddress CX86Assembler::MakeLiteral128Address(LITERAL128ID literalId)
391 {
392 CAddress address;
393 address.nOffset = 0;
394 address.ModRm.nMod = 0;
395 address.ModRm.nRM = 5;
396 address.literal128Id = literalId;
397 return address;
398 }
399
CreateLabel()400 CX86Assembler::LABEL CX86Assembler::CreateLabel()
401 {
402 LABEL newLabelId = m_nextLabelId++;
403 m_labels[newLabelId] = LABELINFO();
404 return newLabelId;
405 }
406
MarkLabel(LABEL label,int32 offset)407 void CX86Assembler::MarkLabel(LABEL label, int32 offset)
408 {
409 uint32 currentPos = static_cast<uint32>(m_tmpStream.Tell()) + offset;
410
411 if(m_currentLabel != NULL)
412 {
413 m_currentLabel->size = currentPos - m_currentLabel->start;
414 }
415
416 auto labelIterator(m_labels.find(label));
417 assert(labelIterator != m_labels.end());
418 auto& labelInfo(labelIterator->second);
419 labelInfo.start = currentPos;
420 m_currentLabel = &labelInfo;
421 m_labelOrder.push_back(label);
422 }
423
GetLabelOffset(LABEL label) const424 uint32 CX86Assembler::GetLabelOffset(LABEL label) const
425 {
426 auto labelIterator(m_labels.find(label));
427 assert(labelIterator != m_labels.end());
428 const auto& labelInfo(labelIterator->second);
429 return labelInfo.projectedStart;
430 }
431
CreateLiteral128(const LITERAL128 & literal)432 CX86Assembler::LITERAL128ID CX86Assembler::CreateLiteral128(const LITERAL128& literal)
433 {
434 auto literalId = m_nextLiteral128Id++;
435 LITERAL128REF literalRef;
436 literalRef.value = literal;
437 assert(m_currentLabel);
438 m_currentLabel->literal128Refs.insert(std::make_pair(literalId, literalRef));
439 return literalId;
440 }
441
ResolveLiteralReferences()442 void CX86Assembler::ResolveLiteralReferences()
443 {
444 CLiteralPool literalPool(m_outputStream);
445 literalPool.AlignPool();
446
447 for(const auto& labelId : m_labelOrder)
448 {
449 const auto& label = m_labels[labelId];
450 assert(label.projectedStart >= label.start);
451 uint32 projectedDiff = label.projectedStart - label.start;
452 for(const auto& literalRefPair : label.literal128Refs)
453 {
454 const auto& literal = literalRefPair.second;
455 auto literalPos = static_cast<uint32>(literalPool.GetLiteralPosition(literal.value));
456 uint32 projectedOffset = literal.offset + projectedDiff;
457 m_outputStream->Seek(projectedOffset, Framework::STREAM_SEEK_SET);
458 static const uint32 opcodeSize = 4;
459 auto offset = literalPos - projectedOffset - opcodeSize;
460 m_outputStream->Write32(offset);
461 }
462 }
463
464 m_outputStream->Seek(0, Framework::STREAM_SEEK_END);
465 }
466
AdcEd(REGISTER registerId,const CAddress & address)467 void CX86Assembler::AdcEd(REGISTER registerId, const CAddress& address)
468 {
469 WriteEvGvOp(0x13, false, address, registerId);
470 }
471
AdcId(const CAddress & address,uint32 constant)472 void CX86Assembler::AdcId(const CAddress& address, uint32 constant)
473 {
474 WriteEvId(0x02, address, constant);
475 }
476
AddEd(REGISTER registerId,const CAddress & address)477 void CX86Assembler::AddEd(REGISTER registerId, const CAddress& address)
478 {
479 WriteEvGvOp(0x03, false, address, registerId);
480 }
481
AddEq(REGISTER registerId,const CAddress & address)482 void CX86Assembler::AddEq(REGISTER registerId, const CAddress& address)
483 {
484 WriteEvGvOp(0x03, true, address, registerId);
485 }
486
AddId(const CAddress & Address,uint32 nConstant)487 void CX86Assembler::AddId(const CAddress& Address, uint32 nConstant)
488 {
489 WriteEvId(0x00, Address, nConstant);
490 }
491
AddIq(const CAddress & address,uint64 constant)492 void CX86Assembler::AddIq(const CAddress& address, uint64 constant)
493 {
494 WriteEvIq(0x00, address, constant);
495 }
496
AndEd(REGISTER registerId,const CAddress & address)497 void CX86Assembler::AndEd(REGISTER registerId, const CAddress& address)
498 {
499 WriteEvGvOp(0x23, false, address, registerId);
500 }
501
AndEq(REGISTER registerId,const CAddress & address)502 void CX86Assembler::AndEq(REGISTER registerId, const CAddress& address)
503 {
504 WriteEvGvOp(0x23, true, address, registerId);
505 }
506
AndIb(const CAddress & address,uint8 constant)507 void CX86Assembler::AndIb(const CAddress& address, uint8 constant)
508 {
509 assert(!address.NeedsExtendedByteAddress());
510 WriteEvIb(0x04, address, constant);
511 }
512
AndId(const CAddress & address,uint32 constant)513 void CX86Assembler::AndId(const CAddress& address, uint32 constant)
514 {
515 WriteEvId(0x04, address, constant);
516 }
517
AndIq(const CAddress & address,uint64 constant)518 void CX86Assembler::AndIq(const CAddress& address, uint64 constant)
519 {
520 assert(0);
521 }
522
BsrEd(REGISTER registerId,const CAddress & address)523 void CX86Assembler::BsrEd(REGISTER registerId, const CAddress& address)
524 {
525 WriteEvGvOp0F(0xBD, false, address, registerId);
526 }
527
CallEd(const CAddress & address)528 void CX86Assembler::CallEd(const CAddress& address)
529 {
530 WriteEvOp(0xFF, 0x02, false, address);
531 }
532
CmovsEd(REGISTER registerId,const CAddress & address)533 void CX86Assembler::CmovsEd(REGISTER registerId, const CAddress& address)
534 {
535 WriteEvGvOp0F(0x48, false, address, registerId);
536 }
537
CmovnsEd(REGISTER registerId,const CAddress & address)538 void CX86Assembler::CmovnsEd(REGISTER registerId, const CAddress& address)
539 {
540 WriteEvGvOp0F(0x49, false, address, registerId);
541 }
542
CmpEd(REGISTER registerId,const CAddress & address)543 void CX86Assembler::CmpEd(REGISTER registerId, const CAddress& address)
544 {
545 WriteEvGvOp(0x3B, false, address, registerId);
546 }
547
CmpEq(REGISTER nRegister,const CAddress & Address)548 void CX86Assembler::CmpEq(REGISTER nRegister, const CAddress& Address)
549 {
550 WriteEvGvOp(0x3B, true, Address, nRegister);
551 }
552
CmpIb(const CAddress & address,uint8 constant)553 void CX86Assembler::CmpIb(const CAddress& address, uint8 constant)
554 {
555 assert(!address.NeedsExtendedByteAddress());
556 WriteEvIb(0x07, address, constant);
557 }
558
CmpId(const CAddress & address,uint32 constant)559 void CX86Assembler::CmpId(const CAddress& address, uint32 constant)
560 {
561 WriteEvId(0x07, address, constant);
562 }
563
CmpIq(const CAddress & Address,uint64 nConstant)564 void CX86Assembler::CmpIq(const CAddress& Address, uint64 nConstant)
565 {
566 WriteEvIq(0x07, Address, nConstant);
567 }
568
Cdq()569 void CX86Assembler::Cdq()
570 {
571 WriteByte(0x99);
572 }
573
DivEd(const CAddress & address)574 void CX86Assembler::DivEd(const CAddress& address)
575 {
576 WriteEvOp(0xF7, 0x06, false, address);
577 }
578
IdivEd(const CAddress & address)579 void CX86Assembler::IdivEd(const CAddress& address)
580 {
581 WriteEvOp(0xF7, 0x07, false, address);
582 }
583
ImulEw(const CAddress & address)584 void CX86Assembler::ImulEw(const CAddress& address)
585 {
586 WriteByte(0x66);
587 WriteEvOp(0xF7, 0x05, false, address);
588 }
589
ImulEd(const CAddress & address)590 void CX86Assembler::ImulEd(const CAddress& address)
591 {
592 WriteEvOp(0xF7, 0x05, false, address);
593 }
594
Int3()595 void CX86Assembler::Int3()
596 {
597 WriteByte(0xCC);
598 }
599
JbJx(LABEL label)600 void CX86Assembler::JbJx(LABEL label)
601 {
602 CreateLabelReference(label, JMP_B);
603 }
604
JbeJx(LABEL label)605 void CX86Assembler::JbeJx(LABEL label)
606 {
607 CreateLabelReference(label, JMP_BE);
608 }
609
JnbJx(LABEL label)610 void CX86Assembler::JnbJx(LABEL label)
611 {
612 CreateLabelReference(label, JMP_NB);
613 }
614
JlJx(LABEL label)615 void CX86Assembler::JlJx(LABEL label)
616 {
617 CreateLabelReference(label, JMP_L);
618 }
619
JleJx(LABEL label)620 void CX86Assembler::JleJx(LABEL label)
621 {
622 CreateLabelReference(label, JMP_LE);
623 }
624
JnlJx(LABEL label)625 void CX86Assembler::JnlJx(LABEL label)
626 {
627 CreateLabelReference(label, JMP_NL);
628 }
629
JnleJx(LABEL label)630 void CX86Assembler::JnleJx(LABEL label)
631 {
632 CreateLabelReference(label, JMP_NLE);
633 }
634
JmpEd(const CAddress & address)635 void CX86Assembler::JmpEd(const CAddress& address)
636 {
637 WriteEvOp(0xFF, 0x04, false, address);
638 }
639
JmpJx(LABEL label)640 void CX86Assembler::JmpJx(LABEL label)
641 {
642 CreateLabelReference(label, JMP_ALWAYS);
643 }
644
JzJx(LABEL label)645 void CX86Assembler::JzJx(LABEL label)
646 {
647 CreateLabelReference(label, JMP_Z);
648 }
649
JnzJx(LABEL label)650 void CX86Assembler::JnzJx(LABEL label)
651 {
652 CreateLabelReference(label, JMP_NZ);
653 }
654
JnbeJx(LABEL label)655 void CX86Assembler::JnbeJx(LABEL label)
656 {
657 CreateLabelReference(label, JMP_NBE);
658 }
659
JnoJx(LABEL label)660 void CX86Assembler::JnoJx(LABEL label)
661 {
662 CreateLabelReference(label, JMP_NO);
663 }
664
JnsJx(LABEL label)665 void CX86Assembler::JnsJx(LABEL label)
666 {
667 CreateLabelReference(label, JMP_NS);
668 }
669
LeaGd(REGISTER registerId,const CAddress & address)670 void CX86Assembler::LeaGd(REGISTER registerId, const CAddress& address)
671 {
672 WriteEvGvOp(0x8D, false, address, registerId);
673 }
674
LeaGq(REGISTER registerId,const CAddress & address)675 void CX86Assembler::LeaGq(REGISTER registerId, const CAddress& address)
676 {
677 WriteEvGvOp(0x8D, true, address, registerId);
678 }
679
MovEw(REGISTER registerId,const CAddress & address)680 void CX86Assembler::MovEw(REGISTER registerId, const CAddress& address)
681 {
682 WriteByte(0x66);
683 WriteEvGvOp(0x8B, false, address, registerId);
684 }
685
MovEd(REGISTER nRegister,const CAddress & Address)686 void CX86Assembler::MovEd(REGISTER nRegister, const CAddress& Address)
687 {
688 WriteEvGvOp(0x8B, false, Address, nRegister);
689 }
690
MovEq(REGISTER nRegister,const CAddress & Address)691 void CX86Assembler::MovEq(REGISTER nRegister, const CAddress& Address)
692 {
693 WriteEvGvOp(0x8B, true, Address, nRegister);
694 }
695
MovGb(const CAddress & Address,BYTEREGISTER nRegister)696 void CX86Assembler::MovGb(const CAddress& Address, BYTEREGISTER nRegister)
697 {
698 if(Address.NeedsExtendedByteAddress())
699 {
700 throw std::runtime_error("Invalid operation.");
701 }
702 WriteEbGbOp(0x88, false, Address, nRegister);
703 }
704
MovGb(const CAddress & Address,REGISTER nRegister)705 void CX86Assembler::MovGb(const CAddress& Address, REGISTER nRegister)
706 {
707 WriteEbGbOp(0x88, false, Address, nRegister);
708 }
709
MovGw(const CAddress & Address,REGISTER nRegister)710 void CX86Assembler::MovGw(const CAddress& Address, REGISTER nRegister)
711 {
712 WriteByte(0x66);
713 WriteEvGvOp(0x89, false, Address, nRegister);
714 }
715
MovGd(const CAddress & Address,REGISTER nRegister)716 void CX86Assembler::MovGd(const CAddress& Address, REGISTER nRegister)
717 {
718 WriteEvGvOp(0x89, false, Address, nRegister);
719 }
720
MovGq(const CAddress & Address,REGISTER nRegister)721 void CX86Assembler::MovGq(const CAddress& Address, REGISTER nRegister)
722 {
723 WriteEvGvOp(0x89, true, Address, nRegister);
724 }
725
MovId(REGISTER nRegister,uint32 nConstant)726 void CX86Assembler::MovId(REGISTER nRegister, uint32 nConstant)
727 {
728 CAddress Address(MakeRegisterAddress(nRegister));
729 WriteRexByte(false, Address);
730 WriteByte(0xB8 | Address.ModRm.nRM);
731 WriteDWord(nConstant);
732 }
733
MovIq(REGISTER registerId,uint64 constant)734 void CX86Assembler::MovIq(REGISTER registerId, uint64 constant)
735 {
736 CAddress address(MakeRegisterAddress(registerId));
737 WriteRexByte(true, address);
738 WriteByte(0xB8 | address.ModRm.nRM);
739 WriteDWord(static_cast<uint32>(constant & 0xFFFFFFFF));
740 WriteDWord(static_cast<uint32>(constant >> 32));
741 }
742
MovIb(const CX86Assembler::CAddress & address,uint8 constant)743 void CX86Assembler::MovIb(const CX86Assembler::CAddress& address, uint8 constant)
744 {
745 assert(!address.NeedsExtendedByteAddress());
746
747 WriteRexByte(false, address);
748 CAddress newAddress(address);
749 newAddress.ModRm.nFnReg = 0x00;
750
751 WriteByte(0xC6);
752 newAddress.Write(&m_tmpStream);
753 WriteByte(constant);
754 }
755
MovIw(const CX86Assembler::CAddress & address,uint16 constant)756 void CX86Assembler::MovIw(const CX86Assembler::CAddress& address, uint16 constant)
757 {
758 WriteByte(0x66);
759 WriteRexByte(false, address);
760 CAddress newAddress(address);
761 newAddress.ModRm.nFnReg = 0x00;
762
763 WriteByte(0xC7);
764 newAddress.Write(&m_tmpStream);
765 WriteWord(constant);
766 }
767
MovId(const CX86Assembler::CAddress & address,uint32 constant)768 void CX86Assembler::MovId(const CX86Assembler::CAddress& address, uint32 constant)
769 {
770 WriteRexByte(false, address);
771 CAddress newAddress(address);
772 newAddress.ModRm.nFnReg = 0x00;
773
774 WriteByte(0xC7);
775 newAddress.Write(&m_tmpStream);
776 WriteDWord(constant);
777 }
778
MovsxEb(REGISTER registerId,const CAddress & address)779 void CX86Assembler::MovsxEb(REGISTER registerId, const CAddress& address)
780 {
781 WriteEbGvOp0F(0xBE, false, address, registerId);
782 }
783
MovsxEw(REGISTER registerId,const CAddress & address)784 void CX86Assembler::MovsxEw(REGISTER registerId, const CAddress& address)
785 {
786 WriteEvGvOp0F(0xBF, false, address, registerId);
787 }
788
MovzxEb(REGISTER registerId,const CAddress & address)789 void CX86Assembler::MovzxEb(REGISTER registerId, const CAddress& address)
790 {
791 WriteEbGvOp0F(0xB6, false, address, registerId);
792 }
793
MovzxEw(REGISTER registerId,const CAddress & address)794 void CX86Assembler::MovzxEw(REGISTER registerId, const CAddress& address)
795 {
796 WriteEvGvOp0F(0xB7, false, address, registerId);
797 }
798
MulEd(const CAddress & address)799 void CX86Assembler::MulEd(const CAddress& address)
800 {
801 WriteEvOp(0xF7, 0x04, false, address);
802 }
803
NegEd(const CAddress & address)804 void CX86Assembler::NegEd(const CAddress& address)
805 {
806 WriteEvOp(0xF7, 0x03, false, address);
807 }
808
Nop()809 void CX86Assembler::Nop()
810 {
811 WriteByte(0x90);
812 }
813
NotEd(const CAddress & address)814 void CX86Assembler::NotEd(const CAddress& address)
815 {
816 WriteEvOp(0xF7, 0x02, false, address);
817 }
818
OrEd(REGISTER registerId,const CAddress & address)819 void CX86Assembler::OrEd(REGISTER registerId, const CAddress& address)
820 {
821 WriteEvGvOp(0x0B, false, address, registerId);
822 }
823
OrId(const CAddress & address,uint32 constant)824 void CX86Assembler::OrId(const CAddress& address, uint32 constant)
825 {
826 WriteEvId(0x01, address, constant);
827 }
828
Pop(REGISTER registerId)829 void CX86Assembler::Pop(REGISTER registerId)
830 {
831 CAddress Address(MakeRegisterAddress(registerId));
832 WriteRexByte(false, Address);
833 WriteByte(0x58 | Address.ModRm.nRM);
834 }
835
Push(REGISTER registerId)836 void CX86Assembler::Push(REGISTER registerId)
837 {
838 CAddress Address(MakeRegisterAddress(registerId));
839 WriteRexByte(false, Address);
840 WriteByte(0x50 | Address.ModRm.nRM);
841 }
842
PushEd(const CAddress & address)843 void CX86Assembler::PushEd(const CAddress& address)
844 {
845 WriteEvOp(0xFF, 0x06, false, address);
846 }
847
PushId(uint32 value)848 void CX86Assembler::PushId(uint32 value)
849 {
850 WriteByte(0x68);
851 WriteDWord(value);
852 }
853
RclEd(const CAddress & address,uint8 amount)854 void CX86Assembler::RclEd(const CAddress& address, uint8 amount)
855 {
856 WriteEvOp(0xC1, 0x02, false, address);
857 WriteByte(amount);
858 }
859
RepMovsb()860 void CX86Assembler::RepMovsb()
861 {
862 WriteByte(0xF3);
863 WriteByte(0xA4);
864 }
865
Ret()866 void CX86Assembler::Ret()
867 {
868 WriteByte(0xC3);
869 }
870
SarEd(const CAddress & address)871 void CX86Assembler::SarEd(const CAddress& address)
872 {
873 WriteEvOp(0xD3, 0x07, false, address);
874 }
875
SarEd(const CAddress & address,uint8 amount)876 void CX86Assembler::SarEd(const CAddress& address, uint8 amount)
877 {
878 WriteEvOp(0xC1, 0x07, false, address);
879 WriteByte(amount);
880 }
881
SarEq(const CAddress & address)882 void CX86Assembler::SarEq(const CAddress& address)
883 {
884 WriteEvOp(0xD3, 0x07, true, address);
885 }
886
SarEq(const CAddress & address,uint8 amount)887 void CX86Assembler::SarEq(const CAddress& address, uint8 amount)
888 {
889 WriteEvOp(0xC1, 0x07, true, address);
890 WriteByte(amount);
891 }
892
SbbEd(REGISTER registerId,const CAddress & address)893 void CX86Assembler::SbbEd(REGISTER registerId, const CAddress& address)
894 {
895 WriteEvGvOp(0x1B, false, address, registerId);
896 }
897
SbbId(const CAddress & Address,uint32 nConstant)898 void CX86Assembler::SbbId(const CAddress& Address, uint32 nConstant)
899 {
900 WriteEvId(0x03, Address, nConstant);
901 }
902
SetaEb(const CAddress & address)903 void CX86Assembler::SetaEb(const CAddress& address)
904 {
905 WriteEbOp_0F(0x97, 0x00, address);
906 }
907
SetaeEb(const CAddress & address)908 void CX86Assembler::SetaeEb(const CAddress& address)
909 {
910 throw std::exception();
911 }
912
SetbEb(const CAddress & address)913 void CX86Assembler::SetbEb(const CAddress& address)
914 {
915 WriteEbOp_0F(0x92, 0x00, address);
916 }
917
SetbeEb(const CAddress & address)918 void CX86Assembler::SetbeEb(const CAddress& address)
919 {
920 WriteEbOp_0F(0x96, 0x00, address);
921 }
922
SeteEb(const CAddress & address)923 void CX86Assembler::SeteEb(const CAddress& address)
924 {
925 WriteEbOp_0F(0x94, 0x00, address);
926 }
927
SetneEb(const CAddress & address)928 void CX86Assembler::SetneEb(const CAddress& address)
929 {
930 WriteEbOp_0F(0x95, 0x00, address);
931 }
932
SetlEb(const CAddress & address)933 void CX86Assembler::SetlEb(const CAddress& address)
934 {
935 WriteEbOp_0F(0x9C, 0x00, address);
936 }
937
SetleEb(const CAddress & address)938 void CX86Assembler::SetleEb(const CAddress& address)
939 {
940 WriteEbOp_0F(0x9E, 0x00, address);
941 }
942
SetgEb(const CAddress & address)943 void CX86Assembler::SetgEb(const CAddress& address)
944 {
945 WriteEbOp_0F(0x9F, 0x00, address);
946 }
947
ShlEd(const CAddress & address)948 void CX86Assembler::ShlEd(const CAddress& address)
949 {
950 WriteEvOp(0xD3, 0x04, false, address);
951 }
952
ShlEd(const CAddress & address,uint8 amount)953 void CX86Assembler::ShlEd(const CAddress& address, uint8 amount)
954 {
955 WriteEvOp(0xC1, 0x04, false, address);
956 WriteByte(amount);
957 }
958
ShlEq(const CAddress & address)959 void CX86Assembler::ShlEq(const CAddress& address)
960 {
961 WriteEvOp(0xD3, 0x04, true, address);
962 }
963
ShlEq(const CAddress & address,uint8 amount)964 void CX86Assembler::ShlEq(const CAddress& address, uint8 amount)
965 {
966 WriteEvOp(0xC1, 0x04, true, address);
967 WriteByte(amount);
968 }
969
ShrEd(const CAddress & address)970 void CX86Assembler::ShrEd(const CAddress& address)
971 {
972 WriteEvOp(0xD3, 0x05, false, address);
973 }
974
ShrEd(const CAddress & address,uint8 amount)975 void CX86Assembler::ShrEd(const CAddress& address, uint8 amount)
976 {
977 WriteEvOp(0xC1, 0x05, false, address);
978 WriteByte(amount);
979 }
980
ShrEq(const CAddress & address)981 void CX86Assembler::ShrEq(const CAddress& address)
982 {
983 WriteEvOp(0xD3, 0x05, true, address);
984 }
985
ShrEq(const CAddress & address,uint8 amount)986 void CX86Assembler::ShrEq(const CAddress& address, uint8 amount)
987 {
988 WriteEvOp(0xC1, 0x05, true, address);
989 WriteByte(amount);
990 }
991
ShldEd(const CAddress & address,REGISTER registerId)992 void CX86Assembler::ShldEd(const CAddress& address, REGISTER registerId)
993 {
994 WriteByte(0x0F);
995 WriteEvGvOp(0xA5, false, address, registerId);
996 }
997
ShldEd(const CAddress & address,REGISTER registerId,uint8 amount)998 void CX86Assembler::ShldEd(const CAddress& address, REGISTER registerId, uint8 amount)
999 {
1000 WriteByte(0x0F);
1001 WriteEvGvOp(0xA4, false, address, registerId);
1002 WriteByte(amount);
1003 }
1004
ShrdEd(const CAddress & address,REGISTER registerId)1005 void CX86Assembler::ShrdEd(const CAddress& address, REGISTER registerId)
1006 {
1007 WriteByte(0x0F);
1008 WriteEvGvOp(0xAD, false, address, registerId);
1009 }
1010
ShrdEd(const CAddress & address,REGISTER registerId,uint8 amount)1011 void CX86Assembler::ShrdEd(const CAddress& address, REGISTER registerId, uint8 amount)
1012 {
1013 WriteByte(0x0F);
1014 WriteEvGvOp(0xAC, false, address, registerId);
1015 WriteByte(amount);
1016 }
1017
SubEd(REGISTER nRegister,const CAddress & Address)1018 void CX86Assembler::SubEd(REGISTER nRegister, const CAddress& Address)
1019 {
1020 WriteEvGvOp(0x2B, false, Address, nRegister);
1021 }
1022
SubEq(REGISTER nRegister,const CAddress & Address)1023 void CX86Assembler::SubEq(REGISTER nRegister, const CAddress& Address)
1024 {
1025 WriteEvGvOp(0x2B, true, Address, nRegister);
1026 }
1027
SubId(const CAddress & Address,uint32 nConstant)1028 void CX86Assembler::SubId(const CAddress& Address, uint32 nConstant)
1029 {
1030 WriteEvId(0x05, Address, nConstant);
1031 }
1032
SubIq(const CAddress & address,uint64 constant)1033 void CX86Assembler::SubIq(const CAddress& address, uint64 constant)
1034 {
1035 WriteEvIq(0x05, address, constant);
1036 }
1037
TestEb(BYTEREGISTER registerId,const CAddress & address)1038 void CX86Assembler::TestEb(BYTEREGISTER registerId, const CAddress& address)
1039 {
1040 if(address.NeedsExtendedByteAddress())
1041 {
1042 throw std::runtime_error("Invalid operation.");
1043 }
1044 WriteEbGbOp(0x84, false, address, registerId);
1045 }
1046
TestEd(REGISTER registerId,const CAddress & address)1047 void CX86Assembler::TestEd(REGISTER registerId, const CAddress& address)
1048 {
1049 WriteEvGvOp(0x85, false, address, registerId);
1050 }
1051
TestEq(REGISTER registerId,const CAddress & address)1052 void CX86Assembler::TestEq(REGISTER registerId, const CAddress& address)
1053 {
1054 WriteEvGvOp(0x85, true, address, registerId);
1055 }
1056
XorEd(REGISTER registerId,const CAddress & address)1057 void CX86Assembler::XorEd(REGISTER registerId, const CAddress& address)
1058 {
1059 WriteEvGvOp(0x33, false, address, registerId);
1060 }
1061
XorId(const CAddress & address,uint32 constant)1062 void CX86Assembler::XorId(const CAddress& address, uint32 constant)
1063 {
1064 WriteEvId(0x06, address, constant);
1065 }
1066
XorGd(const CAddress & Address,REGISTER nRegister)1067 void CX86Assembler::XorGd(const CAddress& Address, REGISTER nRegister)
1068 {
1069 WriteEvGvOp(0x31, false, Address, nRegister);
1070 }
1071
XorGq(const CAddress & Address,REGISTER nRegister)1072 void CX86Assembler::XorGq(const CAddress& Address, REGISTER nRegister)
1073 {
1074 WriteEvGvOp(0x31, true, Address, nRegister);
1075 }
1076
WriteRexByte(bool nIs64,const CAddress & Address)1077 void CX86Assembler::WriteRexByte(bool nIs64, const CAddress& Address)
1078 {
1079 REGISTER nTemp = rAX;
1080 WriteRexByte(nIs64, Address, nTemp);
1081 }
1082
WriteRexByte(bool nIs64,const CAddress & Address,REGISTER & nRegister,bool forceWrite)1083 void CX86Assembler::WriteRexByte(bool nIs64, const CAddress& Address, REGISTER& nRegister, bool forceWrite)
1084 {
1085 if((nIs64) || (Address.nIsExtendedModRM) || (Address.nIsExtendedSib) || (nRegister > 7) || forceWrite)
1086 {
1087 uint8 nByte = 0x40;
1088 nByte |= nIs64 ? 0x8 : 0x0;
1089 nByte |= (nRegister > 7) ? 0x04 : 0x0;
1090 nByte |= Address.nIsExtendedSib ? 0x02 : 0x0;
1091 nByte |= Address.nIsExtendedModRM ? 0x1 : 0x0;
1092
1093 nRegister = static_cast<REGISTER>(nRegister & 7);
1094
1095 WriteByte(nByte);
1096 }
1097 }
1098
WriteEbOp_0F(uint8 opcode,uint8 subOpcode,const CAddress & address)1099 void CX86Assembler::WriteEbOp_0F(uint8 opcode, uint8 subOpcode, const CAddress& address)
1100 {
1101 auto dummyReg = CX86Assembler::rAX;
1102 bool forcedWrite = address.NeedsExtendedByteAddress();
1103 WriteRexByte(false, address, dummyReg, forcedWrite);
1104 WriteByte(0x0F);
1105 CAddress newAddress(address);
1106 newAddress.ModRm.nFnReg = subOpcode;
1107 WriteByte(opcode);
1108 newAddress.Write(&m_tmpStream);
1109 }
1110
WriteEbGbOp(uint8 nOp,bool nIs64,const CAddress & Address,REGISTER nRegister)1111 void CX86Assembler::WriteEbGbOp(uint8 nOp, bool nIs64, const CAddress& Address, REGISTER nRegister)
1112 {
1113 WriteRexByte(nIs64, Address, nRegister, true);
1114 CAddress NewAddress(Address);
1115 NewAddress.ModRm.nFnReg = nRegister;
1116 WriteByte(nOp);
1117 NewAddress.Write(&m_tmpStream);
1118 }
1119
WriteEbGbOp(uint8 nOp,bool nIs64,const CAddress & Address,BYTEREGISTER nRegister)1120 void CX86Assembler::WriteEbGbOp(uint8 nOp, bool nIs64, const CAddress& Address, BYTEREGISTER nRegister)
1121 {
1122 CAddress NewAddress(Address);
1123 NewAddress.ModRm.nFnReg = nRegister;
1124 WriteByte(nOp);
1125 NewAddress.Write(&m_tmpStream);
1126 }
1127
WriteEbGvOp0F(uint8 op,bool is64,const CAddress & address,REGISTER registerId)1128 void CX86Assembler::WriteEbGvOp0F(uint8 op, bool is64, const CAddress& address, REGISTER registerId)
1129 {
1130 assert(!(address.usesLegacyByteRegister && (registerId > 7)));
1131 bool forcedWrite = address.NeedsExtendedByteAddress();
1132 WriteRexByte(is64, address, registerId, forcedWrite);
1133 WriteByte(0x0F);
1134 CAddress NewAddress(address);
1135 NewAddress.ModRm.nFnReg = registerId;
1136 WriteByte(op);
1137 NewAddress.Write(&m_tmpStream);
1138 }
1139
WriteEvOp(uint8 opcode,uint8 subOpcode,bool is64,const CAddress & address)1140 void CX86Assembler::WriteEvOp(uint8 opcode, uint8 subOpcode, bool is64, const CAddress& address)
1141 {
1142 WriteRexByte(is64, address);
1143 CAddress newAddress(address);
1144 newAddress.ModRm.nFnReg = subOpcode;
1145 WriteByte(opcode);
1146 newAddress.Write(&m_tmpStream);
1147 }
1148
WriteEvGvOp(uint8 nOp,bool nIs64,const CAddress & Address,REGISTER nRegister)1149 void CX86Assembler::WriteEvGvOp(uint8 nOp, bool nIs64, const CAddress& Address, REGISTER nRegister)
1150 {
1151 WriteRexByte(nIs64, Address, nRegister);
1152 CAddress NewAddress(Address);
1153 NewAddress.ModRm.nFnReg = nRegister;
1154 WriteByte(nOp);
1155 NewAddress.Write(&m_tmpStream);
1156 }
1157
WriteEvGvOp0F(uint8 nOp,bool nIs64,const CAddress & Address,REGISTER nRegister)1158 void CX86Assembler::WriteEvGvOp0F(uint8 nOp, bool nIs64, const CAddress& Address, REGISTER nRegister)
1159 {
1160 WriteRexByte(nIs64, Address, nRegister);
1161 WriteByte(0x0F);
1162 CAddress NewAddress(Address);
1163 NewAddress.ModRm.nFnReg = nRegister;
1164 WriteByte(nOp);
1165 NewAddress.Write(&m_tmpStream);
1166 }
1167
WriteEvIb(uint8 op,const CAddress & address,uint8 constant)1168 void CX86Assembler::WriteEvIb(uint8 op, const CAddress& address, uint8 constant)
1169 {
1170 WriteRexByte(false, address);
1171 CAddress newAddress(address);
1172 newAddress.ModRm.nFnReg = op;
1173 WriteByte(0x80);
1174 newAddress.Write(&m_tmpStream);
1175 WriteByte(constant);
1176 }
1177
WriteEvId(uint8 nOp,const CAddress & Address,uint32 nConstant)1178 void CX86Assembler::WriteEvId(uint8 nOp, const CAddress& Address, uint32 nConstant)
1179 {
1180 //0x81 -> Id
1181 //0x83 -> Ib
1182
1183 WriteRexByte(false, Address);
1184 CAddress NewAddress(Address);
1185 NewAddress.ModRm.nFnReg = nOp;
1186
1187 if(GetMinimumConstantSize(nConstant) == 1)
1188 {
1189 WriteByte(0x83);
1190 NewAddress.Write(&m_tmpStream);
1191 WriteByte(static_cast<uint8>(nConstant));
1192 }
1193 else
1194 {
1195 WriteByte(0x81);
1196 NewAddress.Write(&m_tmpStream);
1197 WriteDWord(nConstant);
1198 }
1199 }
1200
WriteEvIq(uint8 nOp,const CAddress & Address,uint64 nConstant)1201 void CX86Assembler::WriteEvIq(uint8 nOp, const CAddress& Address, uint64 nConstant)
1202 {
1203 unsigned int nConstantSize(GetMinimumConstantSize64(nConstant));
1204 assert(nConstantSize <= 4);
1205
1206 WriteRexByte(true, Address);
1207 CAddress NewAddress(Address);
1208 NewAddress.ModRm.nFnReg = nOp;
1209
1210 if(nConstantSize == 1)
1211 {
1212 WriteByte(0x83);
1213 NewAddress.Write(&m_tmpStream);
1214 WriteByte(static_cast<uint8>(nConstant));
1215 }
1216 else
1217 {
1218 WriteByte(0x81);
1219 NewAddress.Write(&m_tmpStream);
1220 WriteDWord(static_cast<uint32>(nConstant));
1221 }
1222 }
1223
CreateLabelReference(LABEL label,JMP_TYPE type)1224 void CX86Assembler::CreateLabelReference(LABEL label, JMP_TYPE type)
1225 {
1226 assert(m_currentLabel != NULL);
1227
1228 LABELREF reference;
1229 reference.label = label;
1230 reference.offset = static_cast<uint32>(m_tmpStream.Tell());
1231 reference.type = type;
1232
1233 m_currentLabel->labelRefs.push_back(reference);
1234 }
1235
HasByteRegister(REGISTER registerId)1236 bool CX86Assembler::HasByteRegister(REGISTER registerId)
1237 {
1238 return (registerId < rSP);
1239 }
1240
GetByteRegister(REGISTER registerId)1241 CX86Assembler::BYTEREGISTER CX86Assembler::GetByteRegister(REGISTER registerId)
1242 {
1243 assert(HasByteRegister(registerId));
1244 return static_cast<BYTEREGISTER>(registerId);
1245 }
1246
GetMinimumConstantSize(uint32 nConstant)1247 unsigned int CX86Assembler::GetMinimumConstantSize(uint32 nConstant)
1248 {
1249 if((static_cast<int32>(nConstant) >= -128) && (static_cast<int32>(nConstant) <= 127))
1250 {
1251 return 1;
1252 }
1253 return 4;
1254 }
1255
GetMinimumConstantSize64(uint64 nConstant)1256 unsigned int CX86Assembler::GetMinimumConstantSize64(uint64 nConstant)
1257 {
1258 if((static_cast<int64>(nConstant) >= -128) && (static_cast<int64>(nConstant) <= 127))
1259 {
1260 return 1;
1261 }
1262 if((static_cast<int64>(nConstant) >= -2147483647) && (static_cast<int64>(nConstant) <= 2147483647))
1263 {
1264 return 4;
1265 }
1266 return 8;
1267 }
1268
GetJumpSize(JMP_TYPE type,JMP_LENGTH length)1269 unsigned int CX86Assembler::GetJumpSize(JMP_TYPE type, JMP_LENGTH length)
1270 {
1271 if(length == JMP_NEAR)
1272 {
1273 return 2;
1274 }
1275 else
1276 {
1277 if(type == JMP_ALWAYS)
1278 {
1279 return 5;
1280 }
1281 else
1282 {
1283 return 6;
1284 }
1285 }
1286 }
1287
WriteJump(Framework::CStream * stream,JMP_TYPE type,JMP_LENGTH length,uint32 offset)1288 void CX86Assembler::WriteJump(Framework::CStream* stream, JMP_TYPE type, JMP_LENGTH length, uint32 offset)
1289 {
1290 if(length == JMP_FAR)
1291 {
1292 switch(type)
1293 {
1294 case JMP_ALWAYS:
1295 stream->Write8(0xE9);
1296 break;
1297 default:
1298 stream->Write8(0x0F);
1299 stream->Write8(0x80 | static_cast<uint8>(type));
1300 break;
1301 }
1302 stream->Write32(offset);
1303 }
1304 else
1305 {
1306 switch(type)
1307 {
1308 case JMP_ALWAYS:
1309 stream->Write8(0xEB);
1310 break;
1311 default:
1312 stream->Write8(0x70 | static_cast<uint8>(type));
1313 break;
1314 }
1315 stream->Write8(static_cast<uint8>(offset));
1316 }
1317 }
1318
WriteByte(uint8 nByte)1319 void CX86Assembler::WriteByte(uint8 nByte)
1320 {
1321 m_tmpStream.Write8(nByte);
1322 }
1323
WriteWord(uint16 word)1324 void CX86Assembler::WriteWord(uint16 word)
1325 {
1326 m_tmpStream.Write16(word);
1327 }
1328
WriteDWord(uint32 nDWord)1329 void CX86Assembler::WriteDWord(uint32 nDWord)
1330 {
1331 //Endianess should be good, unless we target a different processor...
1332 m_tmpStream.Write32(nDWord);
1333 }
1334
1335 /////////////////////////////////////////////////
1336 /////////////////////////////////////////////////
1337
CAddress()1338 CX86Assembler::CAddress::CAddress()
1339 {
1340 nOffset = 0;
1341 ModRm.nByte = 0;
1342 sib.byteValue = 0;
1343 nIsExtendedModRM = false;
1344 nIsExtendedSib = false;
1345 usesLegacyByteRegister = false;
1346 }
1347
Write(Framework::CStream * stream)1348 void CX86Assembler::CAddress::Write(Framework::CStream* stream)
1349 {
1350 stream->Write8(ModRm.nByte);
1351
1352 if(HasSib())
1353 {
1354 stream->Write8(sib.byteValue);
1355 }
1356
1357 if(ModRm.nMod == 1)
1358 {
1359 stream->Write8(static_cast<uint8>(nOffset));
1360 }
1361 else if(ModRm.nMod == 2)
1362 {
1363 stream->Write32(nOffset);
1364 }
1365 }
1366
HasSib() const1367 bool CX86Assembler::CAddress::HasSib() const
1368 {
1369 if(ModRm.nMod == 3) return false;
1370 return ModRm.nRM == 4;
1371 }
1372
NeedsExtendedByteAddress() const1373 bool CX86Assembler::CAddress::NeedsExtendedByteAddress() const
1374 {
1375 return (ModRm.nMod == 0x03) && !usesLegacyByteRegister;
1376 }
1377