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