iced_x86/code_asm/code_asm_methods.rs
1// SPDX-License-Identifier: MIT
2// Copyright (C) 2018-present iced project and contributors
3
4// All methods are in this file instead of code_asm.rs to prevent `cargo doc` from
5// putting all generated methods (thousands of methods) ahead of non-generated fns
6// such as the constructor, prefix fns, etc.
7
8use crate::code_asm::op_state::CodeAsmOpState;
9use crate::code_asm::{CodeAssembler, CodeAssemblerOptions, CodeAssemblerResult, CodeLabel, PrefixFlags};
10use crate::IcedError;
11use crate::{BlockEncoder, BlockEncoderOptions, Code, Instruction, InstructionBlock, MemoryOperand, Register};
12use alloc::vec::Vec;
13
14impl CodeAssembler {
15 const MAX_DB_COUNT: usize = 16;
16 const MAX_DW_COUNT: usize = CodeAssembler::MAX_DB_COUNT / 2;
17 const MAX_DD_COUNT: usize = CodeAssembler::MAX_DB_COUNT / 4;
18 const MAX_DQ_COUNT: usize = CodeAssembler::MAX_DB_COUNT / 8;
19
20 /// Creates a new instance
21 ///
22 /// # Errors
23 ///
24 /// Fails if `bitness` is invalid
25 ///
26 /// # Arguments
27 ///
28 /// * `bitness`: 16, 32, or 64
29 #[inline]
30 pub fn new(bitness: u32) -> Result<CodeAssembler, IcedError> {
31 match bitness {
32 16 | 32 | 64 => {}
33 _ => return Err(IcedError::new("Invalid bitness")),
34 }
35
36 Ok(Self {
37 bitness,
38 instructions: Vec::new(),
39 current_label_id: 0,
40 current_label: CodeLabel::default(),
41 current_anon_label: CodeLabel::default(),
42 next_anon_label: CodeLabel::default(),
43 defined_anon_label: false,
44 prefix_flags: PrefixFlags::NONE,
45 options: CodeAssemblerOptions::PREFER_VEX | CodeAssemblerOptions::PREFER_SHORT_BRANCH,
46 })
47 }
48
49 /// Adds an `XACQUIRE` prefix to the next added instruction
50 #[must_use]
51 #[inline]
52 pub fn xacquire(&mut self) -> &mut Self {
53 self.prefix_flags |= PrefixFlags::REPNE;
54 self
55 }
56
57 /// Adds an `XRELEASE` prefix to the next added instruction
58 #[must_use]
59 #[inline]
60 pub fn xrelease(&mut self) -> &mut Self {
61 self.prefix_flags |= PrefixFlags::REPE;
62 self
63 }
64
65 /// Adds a `LOCK` prefix to the next added instruction
66 #[must_use]
67 #[inline]
68 pub fn lock(&mut self) -> &mut Self {
69 self.prefix_flags |= PrefixFlags::LOCK;
70 self
71 }
72
73 /// Adds a `REP` prefix to the next added instruction
74 ///
75 /// # Examples
76 ///
77 /// ```
78 /// use iced_x86::code_asm::*;
79 ///
80 /// # fn main() -> Result<(), IcedError> {
81 /// let mut a = CodeAssembler::new(64)?;
82 ///
83 /// a.rep().stosq()?;
84 /// a.nop()?;
85 ///
86 /// let bytes = a.assemble(0x1234_5678)?;
87 /// assert_eq!(bytes, vec![0xF3, 0x48, 0xAB, 0x90]);
88 /// # Ok(())
89 /// # }
90 /// ```
91 #[must_use]
92 #[inline]
93 pub fn rep(&mut self) -> &mut Self {
94 self.prefix_flags |= PrefixFlags::REPE;
95 self
96 }
97
98 /// Adds a `REPE`/`REPZ` prefix to the next added instruction
99 ///
100 /// # Examples
101 ///
102 /// ```
103 /// use iced_x86::code_asm::*;
104 ///
105 /// # fn main() -> Result<(), IcedError> {
106 /// let mut a = CodeAssembler::new(64)?;
107 ///
108 /// a.repe().cmpsb()?;
109 /// a.nop()?;
110 ///
111 /// let bytes = a.assemble(0x1234_5678)?;
112 /// assert_eq!(bytes, vec![0xF3, 0xA6, 0x90]);
113 /// # Ok(())
114 /// # }
115 /// ```
116 #[must_use]
117 #[inline]
118 pub fn repe(&mut self) -> &mut Self {
119 self.prefix_flags |= PrefixFlags::REPE;
120 self
121 }
122
123 /// Adds a `REPE`/`REPZ` prefix to the next added instruction
124 ///
125 /// # Examples
126 ///
127 /// ```
128 /// use iced_x86::code_asm::*;
129 ///
130 /// # fn main() -> Result<(), IcedError> {
131 /// let mut a = CodeAssembler::new(64)?;
132 ///
133 /// a.repz().cmpsb()?;
134 /// a.nop()?;
135 ///
136 /// let bytes = a.assemble(0x1234_5678)?;
137 /// assert_eq!(bytes, vec![0xF3, 0xA6, 0x90]);
138 /// # Ok(())
139 /// # }
140 /// ```
141 #[must_use]
142 #[inline]
143 pub fn repz(&mut self) -> &mut Self {
144 self.repe()
145 }
146
147 /// Adds a `REPNE`/`REPNZ` prefix to the next added instruction
148 ///
149 /// # Examples
150 ///
151 /// ```
152 /// use iced_x86::code_asm::*;
153 ///
154 /// # fn main() -> Result<(), IcedError> {
155 /// let mut a = CodeAssembler::new(64)?;
156 ///
157 /// a.repne().scasb()?;
158 /// a.nop()?;
159 ///
160 /// let bytes = a.assemble(0x1234_5678)?;
161 /// assert_eq!(bytes, vec![0xF2, 0xAE, 0x90]);
162 /// # Ok(())
163 /// # }
164 /// ```
165 #[must_use]
166 #[inline]
167 pub fn repne(&mut self) -> &mut Self {
168 self.prefix_flags |= PrefixFlags::REPNE;
169 self
170 }
171
172 /// Adds a `REPNE`/`REPNZ` prefix to the next added instruction
173 ///
174 /// # Examples
175 ///
176 /// ```
177 /// use iced_x86::code_asm::*;
178 ///
179 /// # fn main() -> Result<(), IcedError> {
180 /// let mut a = CodeAssembler::new(64)?;
181 ///
182 /// a.repnz().scasb()?;
183 /// a.nop()?;
184 ///
185 /// let bytes = a.assemble(0x1234_5678)?;
186 /// assert_eq!(bytes, vec![0xF2, 0xAE, 0x90]);
187 /// # Ok(())
188 /// # }
189 /// ```
190 #[must_use]
191 #[inline]
192 pub fn repnz(&mut self) -> &mut Self {
193 self.repne()
194 }
195
196 /// Adds a `BND` prefix to the next added instruction
197 #[must_use]
198 #[inline]
199 pub fn bnd(&mut self) -> &mut Self {
200 self.prefix_flags |= PrefixFlags::REPNE;
201 self
202 }
203
204 /// Adds a `NOTRACK` prefix to the next added instruction
205 #[must_use]
206 #[inline]
207 pub fn notrack(&mut self) -> &mut Self {
208 self.prefix_flags |= PrefixFlags::NOTRACK;
209 self
210 }
211
212 /// Prefer `VEX` encoding if the next instruction can be `VEX` and `EVEX` encoded
213 ///
214 /// # Examples
215 ///
216 /// ```
217 /// use iced_x86::code_asm::*;
218 ///
219 /// # fn main() -> Result<(), IcedError> {
220 /// let mut a = CodeAssembler::new(64)?;
221 ///
222 /// // This instruction can be VEX and EVEX encoded
223 /// a.vex().vaddpd(xmm1, xmm2, xmm3)?;
224 /// a.evex().vaddpd(xmm1, xmm2, xmm3)?;
225 ///
226 /// let bytes = a.assemble(0x1234_5678)?;
227 /// assert_eq!(bytes, b"\xC5\xE9\x58\xCB\x62\xF1\xED\x08\x58\xCB");
228 /// # Ok(())
229 /// # }
230 /// ```
231 #[must_use]
232 #[inline]
233 pub fn vex(&mut self) -> &mut Self {
234 self.prefix_flags |= PrefixFlags::PREFER_VEX;
235 self
236 }
237
238 /// Prefer `EVEX` encoding if the next instruction can be `VEX` and `EVEX` encoded
239 ///
240 /// # Examples
241 ///
242 /// ```
243 /// use iced_x86::code_asm::*;
244 ///
245 /// # fn main() -> Result<(), IcedError> {
246 /// let mut a = CodeAssembler::new(64)?;
247 ///
248 /// // This instruction can be VEX and EVEX encoded
249 /// a.vex().vaddpd(xmm1, xmm2, xmm3)?;
250 /// a.evex().vaddpd(xmm1, xmm2, xmm3)?;
251 ///
252 /// let bytes = a.assemble(0x1234_5678)?;
253 /// assert_eq!(bytes, b"\xC5\xE9\x58\xCB\x62\xF1\xED\x08\x58\xCB");
254 /// # Ok(())
255 /// # }
256 /// ```
257 #[must_use]
258 #[inline]
259 pub fn evex(&mut self) -> &mut Self {
260 self.prefix_flags |= PrefixFlags::PREFER_EVEX;
261 self
262 }
263
264 /// Gets all added instructions, see also [`take_instructions()`] and [`assemble()`]
265 ///
266 /// [`take_instructions()`]: #method.take_instructions
267 /// [`assemble()`]: #method.assemble
268 ///
269 /// # Examples
270 ///
271 /// ```
272 /// use iced_x86::*;
273 /// use iced_x86::code_asm::*;
274 ///
275 /// # fn main() -> Result<(), IcedError> {
276 /// let mut a = CodeAssembler::new(64)?;
277 /// a.push(rcx)?;
278 /// a.xor(rcx, rdx)?;
279 /// assert_eq!(a.instructions(), &[
280 /// Instruction::with1(Code::Push_r64, Register::RCX)?,
281 /// Instruction::with2(Code::Xor_rm64_r64, Register::RCX, Register::RDX)?,
282 /// ]);
283 /// # Ok(())
284 /// # }
285 /// ```
286 #[must_use]
287 #[inline]
288 pub fn instructions(&self) -> &[Instruction] {
289 &self.instructions
290 }
291
292 /// Takes ownership of all instructions and returns them. Instruction state is also reset (see [`reset()`])
293 ///
294 /// [`reset()`]: #method.reset
295 ///
296 /// # Examples
297 ///
298 /// ```
299 /// use iced_x86::*;
300 /// use iced_x86::code_asm::*;
301 ///
302 /// # fn main() -> Result<(), IcedError> {
303 /// let mut a = CodeAssembler::new(64)?;
304 /// a.push(rcx)?;
305 /// a.xor(rcx, rdx)?;
306 /// assert_eq!(a.instructions().len(), 2);
307 /// let instrs = a.take_instructions();
308 /// assert_eq!(a.instructions().len(), 0);
309 /// assert_eq!(instrs.len(), 2);
310 /// assert_eq!(instrs, vec![
311 /// Instruction::with1(Code::Push_r64, Register::RCX)?,
312 /// Instruction::with2(Code::Xor_rm64_r64, Register::RCX, Register::RDX)?,
313 /// ]);
314 /// # Ok(())
315 /// # }
316 /// ```
317 #[must_use]
318 #[inline]
319 pub fn take_instructions(&mut self) -> Vec<Instruction> {
320 let instrs = core::mem::take(&mut self.instructions);
321 self.reset();
322 instrs
323 }
324
325 /// Resets all instructions and labels so this instance can be re-used
326 ///
327 /// # Examples
328 ///
329 /// ```
330 /// use iced_x86::code_asm::*;
331 ///
332 /// # fn main() -> Result<(), IcedError> {
333 /// let mut a = CodeAssembler::new(64)?;
334 /// a.push(rcx)?;
335 /// a.xor(rcx, rdx)?;
336 /// assert_eq!(a.instructions().len(), 2);
337 /// a.reset();
338 /// assert_eq!(a.instructions().len(), 0);
339 /// # Ok(())
340 /// # }
341 /// ```
342 #[inline]
343 pub fn reset(&mut self) {
344 self.instructions.clear();
345 self.current_label_id = 0;
346 self.current_label = CodeLabel::default();
347 self.current_anon_label = CodeLabel::default();
348 self.next_anon_label = CodeLabel::default();
349 self.defined_anon_label = false;
350 self.prefix_flags = PrefixFlags::NONE;
351 }
352
353 /// Creates a label that can be referenced by instructions
354 #[must_use]
355 #[inline]
356 pub fn create_label(&mut self) -> CodeLabel {
357 self.current_label_id += 1;
358 CodeLabel::new(self.current_label_id)
359 }
360
361 /// Initializes the label to the next instruction
362 ///
363 /// # Errors
364 ///
365 /// Fails if the label wasn't created by [`create_label()`], if this method was called
366 /// multiple times for the same label, or if the next instruction already has a label.
367 ///
368 /// [`create_label()`]: #method.create_label
369 ///
370 /// # Examples
371 ///
372 /// ```
373 /// use iced_x86::code_asm::*;
374 ///
375 /// # fn main() -> Result<(), IcedError> {
376 /// let mut a = CodeAssembler::new(64)?;
377 /// let mut label1 = a.create_label();
378 /// a.push(rcx)?;
379 /// // The address of this label is the next added instruction
380 /// a.set_label(&mut label1)?;
381 /// a.xor(rcx, rdx)?;
382 /// // Target is the `xor rcx, rdx` instruction
383 /// a.je(label1)?;
384 /// a.nop()?;
385 /// let bytes = a.assemble(0x1234_5678)?;
386 /// assert_eq!(bytes, b"\x51\x48\x31\xD1\x74\xFB\x90");
387 /// # Ok(())
388 /// # }
389 /// ```
390 #[allow(clippy::missing_inline_in_public_items)]
391 pub fn set_label(&mut self, label: &mut CodeLabel) -> Result<(), IcedError> {
392 if label.is_empty() {
393 return Err(IcedError::new("Invalid label. Must be created by current_label()"));
394 }
395 if label.has_instruction_index() {
396 return Err(IcedError::new("Labels can't be re-used and can only be set once."));
397 }
398 if !self.current_label.is_empty() {
399 return Err(IcedError::new("Only one label per instruction is allowed"));
400 }
401 label.instruction_index = self.instructions.len();
402 self.current_label = *label;
403 Ok(())
404 }
405
406 /// Creates an anonymous label that can be referenced by calling [`bwd()`] and [`fwd()`]
407 ///
408 /// # Errors
409 ///
410 /// Fails if the next instruction already has an anonymous label
411 ///
412 /// [`bwd()`]: #method.bwd
413 /// [`fwd()`]: #method.fwd
414 ///
415 /// # Examples
416 ///
417 /// ```
418 /// use iced_x86::code_asm::*;
419 ///
420 /// # fn main() -> Result<(), IcedError> {
421 /// let mut a = CodeAssembler::new(64)?;
422 /// a.push(rcx)?;
423 /// // The address of this label is the next added instruction
424 /// a.anonymous_label()?;
425 /// a.xor(rcx, rdx)?;
426 /// // Target is the `xor rcx, rdx` instruction
427 /// let anon = a.bwd()?; // Unfortunately, Rust forces us to create a local
428 /// a.je(anon)?;
429 /// // Target is the `sub eax, eax` instruction
430 /// let anon = a.fwd()?; // Unfortunately, Rust forces us to create a local
431 /// a.js(anon)?;
432 /// a.nop()?;
433 /// // Create the label referenced by `fwd()` above
434 /// a.anonymous_label()?;
435 /// a.sub(eax, eax)?;
436 /// let bytes = a.assemble(0x1234_5678)?;
437 /// assert_eq!(bytes, b"\x51\x48\x31\xD1\x74\xFB\x78\x01\x90\x29\xC0");
438 /// # Ok(())
439 /// # }
440 /// ```
441 #[allow(clippy::missing_inline_in_public_items)]
442 pub fn anonymous_label(&mut self) -> Result<(), IcedError> {
443 if self.defined_anon_label {
444 return Err(IcedError::new("At most one anonymous label per instruction is allowed"));
445 }
446 self.current_anon_label = if self.next_anon_label.is_empty() { self.create_label() } else { self.next_anon_label };
447 self.next_anon_label = CodeLabel::default();
448 self.defined_anon_label = true;
449 Ok(())
450 }
451
452 /// Gets the previously created anonymous label created by [`anonymous_label()`]
453 ///
454 /// [`anonymous_label()`]: #method.anonymous_label
455 ///
456 /// # Errors
457 ///
458 /// Fails if no anonymous label has been created yet
459 #[inline]
460 pub fn bwd(&mut self) -> Result<CodeLabel, IcedError> {
461 if self.current_anon_label.is_empty() {
462 Err(IcedError::new("No anonymous label has been created yet"))
463 } else {
464 Ok(self.current_anon_label)
465 }
466 }
467
468 /// Gets the next anonymous label created by a future call to [`anonymous_label()`]
469 ///
470 /// [`anonymous_label()`]: #method.anonymous_label
471 ///
472 /// # Errors
473 ///
474 /// Fails if an error was detected
475 #[inline]
476 pub fn fwd(&mut self) -> Result<CodeLabel, IcedError> {
477 // This method returns a `Result<T, E>` for consistency with other methods, including `bwd()`,
478 // so you don't have to memorize which methods return a Result and which don't.
479
480 if self.next_anon_label.is_empty() {
481 self.next_anon_label = self.create_label();
482 }
483 Ok(self.next_anon_label)
484 }
485
486 #[inline]
487 fn decl_data_verify_no_prefixes(&self) -> Result<(), IcedError> {
488 if self.prefix_flags != 0 {
489 Err(IcedError::new("db/dw/dd/dq: No prefixes are allowed"))
490 } else {
491 Ok(())
492 }
493 }
494
495 /// Adds data
496 ///
497 /// # Errors
498 ///
499 /// Fails if an error was detected
500 ///
501 /// # Arguments
502 ///
503 /// * `data`: The data that will be added at the current position
504 ///
505 /// # Examples
506 ///
507 /// ```
508 /// use iced_x86::code_asm::*;
509 ///
510 /// # fn main() -> Result<(), IcedError> {
511 /// let mut a = CodeAssembler::new(64)?;
512 /// a.int3()?;
513 /// a.db(b"\x16\x85\x10\xA0\xFA\x9E\x11\xEB\x97\x34\x3B\x7E\xB7\x2B\x92\x63\x16\x85")?;
514 /// a.nop()?;
515 /// let bytes = a.assemble(0x1234_5678)?;
516 /// assert_eq!(bytes, b"\xCC\x16\x85\x10\xA0\xFA\x9E\x11\xEB\x97\x34\x3B\x7E\xB7\x2B\x92\x63\x16\x85\x90");
517 /// # Ok(())
518 /// # }
519 /// ```
520 #[allow(clippy::missing_inline_in_public_items)]
521 pub fn db(&mut self, data: &[u8]) -> Result<(), IcedError> {
522 self.decl_data_verify_no_prefixes()?;
523 for bytes in data.chunks(CodeAssembler::MAX_DB_COUNT) {
524 self.add_instr(Instruction::with_declare_byte(bytes)?)?;
525 }
526
527 Ok(())
528 }
529
530 /// Adds data
531 ///
532 /// # Errors
533 ///
534 /// Fails if an error was detected
535 ///
536 /// # Arguments
537 ///
538 /// * `data`: The data that will be added at the current position
539 ///
540 /// # Examples
541 ///
542 /// ```
543 /// use iced_x86::code_asm::*;
544 ///
545 /// # fn main() -> Result<(), IcedError> {
546 /// let mut a = CodeAssembler::new(64)?;
547 /// a.int3()?;
548 /// a.db_i(&[0x16, -0x7B, 0x10, -0x60, -0x06, -0x62, 0x11, -0x15, -0x69, 0x34, 0x3B, 0x7E, -0x49, 0x2B, -0x6E, 0x63, 0x16, -0x7B])?;
549 /// a.nop()?;
550 /// let bytes = a.assemble(0x1234_5678)?;
551 /// assert_eq!(bytes, b"\xCC\x16\x85\x10\xA0\xFA\x9E\x11\xEB\x97\x34\x3B\x7E\xB7\x2B\x92\x63\x16\x85\x90");
552 /// # Ok(())
553 /// # }
554 /// ```
555 #[allow(clippy::missing_inline_in_public_items)]
556 pub fn db_i(&mut self, data: &[i8]) -> Result<(), IcedError> {
557 self.decl_data_verify_no_prefixes()?;
558 let mut tmp = [0; CodeAssembler::MAX_DB_COUNT];
559 for bytes in data.chunks(CodeAssembler::MAX_DB_COUNT) {
560 for (t, b) in tmp.iter_mut().zip(bytes.iter()) {
561 *t = *b as u8;
562 }
563 self.add_instr(Instruction::with_declare_byte(&tmp[0..bytes.len()])?)?;
564 }
565
566 Ok(())
567 }
568
569 /// Adds data
570 ///
571 /// # Errors
572 ///
573 /// Fails if an error was detected
574 ///
575 /// # Arguments
576 ///
577 /// * `data`: The data that will be added at the current position
578 ///
579 /// # Examples
580 ///
581 /// ```
582 /// use iced_x86::code_asm::*;
583 ///
584 /// # fn main() -> Result<(), IcedError> {
585 /// let mut a = CodeAssembler::new(64)?;
586 /// a.int3()?;
587 /// a.dw(&[0x4068, 0x7956, 0xFA9F, 0x11EB, 0x9467, 0x77FA, 0x747C, 0xD088, 0x7D7E])?;
588 /// a.nop()?;
589 /// let bytes = a.assemble(0x1234_5678)?;
590 /// assert_eq!(bytes, b"\xCC\x68\x40\x56\x79\x9F\xFA\xEB\x11\x67\x94\xFA\x77\x7C\x74\x88\xD0\x7E\x7D\x90");
591 /// # Ok(())
592 /// # }
593 /// ```
594 #[allow(clippy::missing_inline_in_public_items)]
595 pub fn dw(&mut self, data: &[u16]) -> Result<(), IcedError> {
596 self.decl_data_verify_no_prefixes()?;
597 for words in data.chunks(CodeAssembler::MAX_DW_COUNT) {
598 self.add_instr(Instruction::with_declare_word(words)?)?;
599 }
600
601 Ok(())
602 }
603
604 /// Adds data
605 ///
606 /// # Errors
607 ///
608 /// Fails if an error was detected
609 ///
610 /// # Arguments
611 ///
612 /// * `data`: The data that will be added at the current position
613 ///
614 /// # Examples
615 ///
616 /// ```
617 /// use iced_x86::code_asm::*;
618 ///
619 /// # fn main() -> Result<(), IcedError> {
620 /// let mut a = CodeAssembler::new(64)?;
621 /// a.int3()?;
622 /// a.dw_i(&[0x4068, 0x7956, -0x0561, 0x11EB, -0x6B99, 0x77FA, 0x747C, -0x2F78, 0x7D7E])?;
623 /// a.nop()?;
624 /// let bytes = a.assemble(0x1234_5678)?;
625 /// assert_eq!(bytes, b"\xCC\x68\x40\x56\x79\x9F\xFA\xEB\x11\x67\x94\xFA\x77\x7C\x74\x88\xD0\x7E\x7D\x90");
626 /// # Ok(())
627 /// # }
628 /// ```
629 #[allow(clippy::missing_inline_in_public_items)]
630 pub fn dw_i(&mut self, data: &[i16]) -> Result<(), IcedError> {
631 self.decl_data_verify_no_prefixes()?;
632 let mut tmp = [0; CodeAssembler::MAX_DW_COUNT];
633 for words in data.chunks(CodeAssembler::MAX_DW_COUNT) {
634 for (t, w) in tmp.iter_mut().zip(words.iter()) {
635 *t = *w as u16;
636 }
637 self.add_instr(Instruction::with_declare_word(&tmp[0..words.len()])?)?;
638 }
639
640 Ok(())
641 }
642
643 /// Adds data
644 ///
645 /// # Errors
646 ///
647 /// Fails if an error was detected
648 ///
649 /// # Arguments
650 ///
651 /// * `data`: The data that will be added at the current position
652 ///
653 /// # Examples
654 ///
655 /// ```
656 /// use iced_x86::code_asm::*;
657 ///
658 /// # fn main() -> Result<(), IcedError> {
659 /// let mut a = CodeAssembler::new(64)?;
660 /// a.int3()?;
661 /// a.dd(&[0x40687956, 0xFA9F11EB, 0x946777FA, 0x747CD088, 0x7D7E7C58])?;
662 /// a.nop()?;
663 /// let bytes = a.assemble(0x1234_5678)?;
664 /// assert_eq!(bytes, b"\xCC\x56\x79\x68\x40\xEB\x11\x9F\xFA\xFA\x77\x67\x94\x88\xD0\x7C\x74\x58\x7C\x7E\x7D\x90");
665 /// # Ok(())
666 /// # }
667 /// ```
668 #[allow(clippy::missing_inline_in_public_items)]
669 pub fn dd(&mut self, data: &[u32]) -> Result<(), IcedError> {
670 self.decl_data_verify_no_prefixes()?;
671 for dwords in data.chunks(CodeAssembler::MAX_DD_COUNT) {
672 self.add_instr(Instruction::with_declare_dword(dwords)?)?;
673 }
674
675 Ok(())
676 }
677
678 /// Adds data
679 ///
680 /// # Errors
681 ///
682 /// Fails if an error was detected
683 ///
684 /// # Arguments
685 ///
686 /// * `data`: The data that will be added at the current position
687 ///
688 /// # Examples
689 ///
690 /// ```
691 /// use iced_x86::code_asm::*;
692 ///
693 /// # fn main() -> Result<(), IcedError> {
694 /// let mut a = CodeAssembler::new(64)?;
695 /// a.int3()?;
696 /// a.dd_i(&[0x40687956, -0x0560EE15, -0x6B988806, 0x747CD088, 0x7D7E7C58])?;
697 /// a.nop()?;
698 /// let bytes = a.assemble(0x1234_5678)?;
699 /// assert_eq!(bytes, b"\xCC\x56\x79\x68\x40\xEB\x11\x9F\xFA\xFA\x77\x67\x94\x88\xD0\x7C\x74\x58\x7C\x7E\x7D\x90");
700 /// # Ok(())
701 /// # }
702 /// ```
703 #[allow(clippy::missing_inline_in_public_items)]
704 pub fn dd_i(&mut self, data: &[i32]) -> Result<(), IcedError> {
705 self.decl_data_verify_no_prefixes()?;
706 let mut tmp = [0; CodeAssembler::MAX_DD_COUNT];
707 for dwords in data.chunks(CodeAssembler::MAX_DD_COUNT) {
708 for (t, d) in tmp.iter_mut().zip(dwords.iter()) {
709 *t = *d as u32;
710 }
711 self.add_instr(Instruction::with_declare_dword(&tmp[0..dwords.len()])?)?;
712 }
713
714 Ok(())
715 }
716
717 /// Adds data
718 ///
719 /// # Errors
720 ///
721 /// Fails if an error was detected
722 ///
723 /// # Arguments
724 ///
725 /// * `data`: The data that will be added at the current position
726 ///
727 /// # Examples
728 ///
729 /// ```
730 /// use iced_x86::code_asm::*;
731 ///
732 /// # fn main() -> Result<(), IcedError> {
733 /// let mut a = CodeAssembler::new(64)?;
734 /// a.int3()?;
735 /// a.dd_f32(&[3.14, -1234.5678, 1e12, -3.14, 1234.5678, -1e12])?;
736 /// a.nop()?;
737 /// let bytes = a.assemble(0x1234_5678)?;
738 /// assert_eq!(bytes, b"\xCC\xC3\xF5\x48\x40\x2B\x52\x9A\xC4\xA5\xD4\x68\x53\xC3\xF5\x48\xC0\x2B\x52\x9A\x44\xA5\xD4\x68\xD3\x90");
739 /// # Ok(())
740 /// # }
741 /// ```
742 #[allow(clippy::missing_inline_in_public_items)]
743 pub fn dd_f32(&mut self, data: &[f32]) -> Result<(), IcedError> {
744 self.decl_data_verify_no_prefixes()?;
745 let mut tmp = [0; CodeAssembler::MAX_DD_COUNT];
746 for dwords in data.chunks(CodeAssembler::MAX_DD_COUNT) {
747 for (t, d) in tmp.iter_mut().zip(dwords.iter()) {
748 *t = f32::to_bits(*d);
749 }
750 self.add_instr(Instruction::with_declare_dword(&tmp[0..dwords.len()])?)?;
751 }
752
753 Ok(())
754 }
755
756 /// Adds data
757 ///
758 /// # Errors
759 ///
760 /// Fails if an error was detected
761 ///
762 /// # Arguments
763 ///
764 /// * `data`: The data that will be added at the current position
765 ///
766 /// # Examples
767 ///
768 /// ```
769 /// use iced_x86::code_asm::*;
770 ///
771 /// # fn main() -> Result<(), IcedError> {
772 /// let mut a = CodeAssembler::new(64)?;
773 /// a.int3()?;
774 /// a.dq(&[0x40687956FA9F11EB, 0x946777FA747CD088, 0x7D7E7C5814C2BA6E])?;
775 /// a.nop()?;
776 /// let bytes = a.assemble(0x1234_5678)?;
777 /// assert_eq!(bytes, b"\xCC\xEB\x11\x9F\xFA\x56\x79\x68\x40\x88\xD0\x7C\x74\xFA\x77\x67\x94\x6E\xBA\xC2\x14\x58\x7C\x7E\x7D\x90");
778 /// # Ok(())
779 /// # }
780 /// ```
781 #[allow(clippy::missing_inline_in_public_items)]
782 pub fn dq(&mut self, data: &[u64]) -> Result<(), IcedError> {
783 self.decl_data_verify_no_prefixes()?;
784 for qwords in data.chunks(CodeAssembler::MAX_DQ_COUNT) {
785 self.add_instr(Instruction::with_declare_qword(qwords)?)?;
786 }
787
788 Ok(())
789 }
790
791 /// Adds data
792 ///
793 /// # Errors
794 ///
795 /// Fails if an error was detected
796 ///
797 /// # Arguments
798 ///
799 /// * `data`: The data that will be added at the current position
800 ///
801 /// # Examples
802 ///
803 /// ```
804 /// use iced_x86::code_asm::*;
805 ///
806 /// # fn main() -> Result<(), IcedError> {
807 /// let mut a = CodeAssembler::new(64)?;
808 /// a.int3()?;
809 /// a.dq_i(&[0x40687956FA9F11EB, -0x6B9888058B832F78, 0x7D7E7C5814C2BA6E])?;
810 /// a.nop()?;
811 /// let bytes = a.assemble(0x1234_5678)?;
812 /// assert_eq!(bytes, b"\xCC\xEB\x11\x9F\xFA\x56\x79\x68\x40\x88\xD0\x7C\x74\xFA\x77\x67\x94\x6E\xBA\xC2\x14\x58\x7C\x7E\x7D\x90");
813 /// # Ok(())
814 /// # }
815 /// ```
816 #[allow(clippy::missing_inline_in_public_items)]
817 pub fn dq_i(&mut self, data: &[i64]) -> Result<(), IcedError> {
818 self.decl_data_verify_no_prefixes()?;
819 let mut tmp = [0; CodeAssembler::MAX_DQ_COUNT];
820 for qwords in data.chunks(CodeAssembler::MAX_DQ_COUNT) {
821 for (t, q) in tmp.iter_mut().zip(qwords.iter()) {
822 *t = *q as u64;
823 }
824 self.add_instr(Instruction::with_declare_qword(&tmp[0..qwords.len()])?)?;
825 }
826
827 Ok(())
828 }
829
830 /// Adds data
831 ///
832 /// # Errors
833 ///
834 /// Fails if an error was detected
835 ///
836 /// # Arguments
837 ///
838 /// * `data`: The data that will be added at the current position
839 ///
840 /// # Examples
841 ///
842 /// ```
843 /// use iced_x86::code_asm::*;
844 ///
845 /// # fn main() -> Result<(), IcedError> {
846 /// let mut a = CodeAssembler::new(64)?;
847 /// a.int3()?;
848 /// a.dq_f64(&[3.14, -1234.5678, 1e123])?;
849 /// a.nop()?;
850 /// let bytes = a.assemble(0x1234_5678)?;
851 /// assert_eq!(bytes, b"\xCC\x1F\x85\xEB\x51\xB8\x1E\x09\x40\xAD\xFA\x5C\x6D\x45\x4A\x93\xC0\xF1\x72\xF8\xA5\x25\x34\x78\x59\x90");
852 /// # Ok(())
853 /// # }
854 /// ```
855 #[allow(clippy::missing_inline_in_public_items)]
856 pub fn dq_f64(&mut self, data: &[f64]) -> Result<(), IcedError> {
857 self.decl_data_verify_no_prefixes()?;
858 let mut tmp = [0; CodeAssembler::MAX_DQ_COUNT];
859 for qwords in data.chunks(CodeAssembler::MAX_DQ_COUNT) {
860 for (t, q) in tmp.iter_mut().zip(qwords.iter()) {
861 *t = f64::to_bits(*q);
862 }
863 self.add_instr(Instruction::with_declare_qword(&tmp[0..qwords.len()])?)?;
864 }
865
866 Ok(())
867 }
868
869 /// Adds nops, preferring long nops
870 ///
871 /// # Errors
872 ///
873 /// Fails if an error was detected
874 ///
875 /// # Arguments
876 ///
877 /// * `size`: Size in bytes of all nops
878 ///
879 /// # Examples
880 ///
881 /// ```
882 /// use iced_x86::code_asm::*;
883 ///
884 /// # fn main() -> Result<(), IcedError> {
885 /// let mut a = CodeAssembler::new(64)?;
886 /// a.nops_with_size(17)?;
887 /// let bytes = a.assemble(0x1234_5678)?;
888 /// assert_eq!(bytes.len(), 17);
889 /// # Ok(())
890 /// # }
891 /// ```
892 #[allow(clippy::missing_inline_in_public_items)]
893 pub fn nops_with_size(&mut self, size: usize) -> Result<(), IcedError> {
894 if self.prefix_flags != 0 {
895 return Err(IcedError::new("No prefixes are allowed"));
896 }
897
898 const MAX_NOP_LEN: usize = 9;
899 if size >= MAX_NOP_LEN {
900 let bytes = self.get_nop_bytes(MAX_NOP_LEN);
901 for _ in 0..size / MAX_NOP_LEN {
902 self.db(bytes)?;
903 }
904 }
905 match size % MAX_NOP_LEN {
906 0 => {}
907 remaining => self.db(self.get_nop_bytes(remaining))?,
908 }
909
910 Ok(())
911 }
912
913 fn get_nop_bytes(&self, size: usize) -> &'static [u8] {
914 match size {
915 1 => &[0x90], // NOP
916 2 => &[0x66, 0x90], // 66 NOP
917 3 => &[0x0F, 0x1F, 0x00], // NOP dword ptr [eax] or NOP word ptr [bx+si]
918 4 => &[0x0F, 0x1F, 0x40, 0x00], // NOP dword ptr [eax + 00] or NOP word ptr [bx+si]
919 5 => {
920 if self.bitness() != 16 {
921 &[0x0F, 0x1F, 0x44, 0x00, 0x00] // NOP dword ptr [eax + eax*1 + 00]
922 } else {
923 &[0x0F, 0x1F, 0x80, 0x00, 0x00] // NOP word ptr[bx + si]
924 }
925 }
926 6 => {
927 if self.bitness() != 16 {
928 &[0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00] // 66 NOP dword ptr [eax + eax*1 + 00]
929 } else {
930 &[0x66, 0x0F, 0x1F, 0x80, 0x00, 0x00] // NOP dword ptr [bx+si]
931 }
932 }
933 7 => {
934 if self.bitness() != 16 {
935 &[0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00] // NOP dword ptr [eax + 00000000]
936 } else {
937 &[0x67, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00] // NOP dword ptr [eax+eax]
938 }
939 }
940 8 => {
941 if self.bitness() != 16 {
942 &[0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00] // NOP dword ptr [eax + eax*1 + 00000000]
943 } else {
944 &[0x67, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00] // NOP word ptr [eax]
945 }
946 }
947 9 => {
948 if self.bitness() != 16 {
949 &[0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00] // 66 NOP dword ptr [eax + eax*1 + 00000000]
950 } else {
951 &[0x67, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00] // NOP word ptr [eax+eax]
952 }
953 }
954 _ => unreachable!(),
955 }
956 }
957
958 /// Adds an instruction created by the decoder or by `Instruction::with*()` methods
959 ///
960 /// # Errors
961 ///
962 /// Fails if an error was detected
963 ///
964 /// # Arguments
965 ///
966 /// * `instruction`: Instruction to add
967 ///
968 /// # Examples
969 ///
970 /// ```
971 /// use iced_x86::*;
972 /// use iced_x86::code_asm::*;
973 ///
974 /// # fn main() -> Result<(), IcedError> {
975 /// let mut a = CodeAssembler::new(64)?;
976 /// a.nop()?;
977 /// a.add_instruction(Instruction::with1(Code::Push_r64, Register::RCX)?)?;
978 /// let bytes = a.assemble(0x1234_5678)?;
979 /// assert_eq!(bytes, b"\x90\x51");
980 /// # Ok(())
981 /// # }
982 /// ```
983 #[inline]
984 pub fn add_instruction(&mut self, instruction: Instruction) -> Result<(), IcedError> {
985 self.add_instr(instruction)
986 }
987
988 pub(crate) fn add_instr_with_state(&mut self, mut instruction: Instruction, state: CodeAsmOpState) -> Result<(), IcedError> {
989 if !state.is_default() {
990 if state.is_broadcast() {
991 instruction.set_is_broadcast(true);
992 }
993 if state.zeroing_masking() {
994 instruction.set_zeroing_masking(true);
995 }
996 if state.suppress_all_exceptions() {
997 instruction.set_suppress_all_exceptions(true);
998 }
999 instruction.set_op_mask(state.op_mask());
1000 instruction.set_rounding_control(state.rounding_control());
1001 }
1002 self.add_instr(instruction)
1003 }
1004
1005 pub(crate) fn add_instr(&mut self, mut instruction: Instruction) -> Result<(), IcedError> {
1006 if !self.current_label.is_empty() && self.defined_anon_label {
1007 return Err(IcedError::new("You can't create both an anonymous label and a normal label"));
1008 }
1009 if !self.current_label.is_empty() {
1010 instruction.set_ip(self.current_label.id());
1011 } else if self.defined_anon_label {
1012 instruction.set_ip(self.current_anon_label.id());
1013 }
1014
1015 if self.prefix_flags != 0 {
1016 if (self.prefix_flags & PrefixFlags::LOCK) != 0 {
1017 instruction.set_has_lock_prefix(true);
1018 }
1019 if (self.prefix_flags & PrefixFlags::REPE) != 0 {
1020 instruction.set_has_repe_prefix(true);
1021 } else if (self.prefix_flags & PrefixFlags::REPNE) != 0 {
1022 instruction.set_has_repne_prefix(true);
1023 }
1024 if (self.prefix_flags & PrefixFlags::NOTRACK) != 0 {
1025 instruction.set_segment_prefix(Register::DS);
1026 }
1027 }
1028
1029 self.instructions.push(instruction);
1030 self.current_label = CodeLabel::default();
1031 self.defined_anon_label = false;
1032 self.prefix_flags = PrefixFlags::NONE;
1033 Ok(())
1034 }
1035
1036 /// Encodes all added instructions and returns the result
1037 ///
1038 /// # Errors
1039 ///
1040 /// Fails if an error was detected (eg. an invalid instruction operand)
1041 ///
1042 /// # Arguments
1043 ///
1044 /// * `ip`: Base address of all instructions
1045 ///
1046 /// # Examples
1047 ///
1048 /// ```
1049 /// use iced_x86::code_asm::*;
1050 ///
1051 /// # fn main() -> Result<(), IcedError> {
1052 /// let mut a = CodeAssembler::new(64)?;
1053 /// let mut label1 = a.create_label();
1054 /// a.push(rcx)?;
1055 /// // The address of this label is the next added instruction
1056 /// a.set_label(&mut label1)?;
1057 /// a.xor(rcx, rdx)?;
1058 /// // Target is the `xor rcx, rdx` instruction
1059 /// a.je(label1)?;
1060 /// a.nop()?;
1061 /// let bytes = a.assemble(0x1234_5678)?;
1062 /// assert_eq!(bytes, b"\x51\x48\x31\xD1\x74\xFB\x90");
1063 /// # Ok(())
1064 /// # }
1065 /// ```
1066 #[inline]
1067 pub fn assemble(&mut self, ip: u64) -> Result<Vec<u8>, IcedError> {
1068 Ok(self.assemble_options(ip, BlockEncoderOptions::NONE)?.inner.code_buffer)
1069 }
1070
1071 /// Encodes all added instructions and returns the result
1072 ///
1073 /// # Errors
1074 ///
1075 /// Fails if an error was detected (eg. an invalid instruction operand)
1076 ///
1077 /// # Arguments
1078 ///
1079 /// * `ip`: Base address of all instructions
1080 /// * `options`: [`BlockEncoderOptions`] flags
1081 ///
1082 /// # Examples
1083 ///
1084 /// ```
1085 /// use iced_x86::BlockEncoderOptions;
1086 /// use iced_x86::code_asm::*;
1087 ///
1088 /// # fn main() -> Result<(), IcedError> {
1089 /// let mut a = CodeAssembler::new(64)?;
1090 /// let mut label1 = a.create_label();
1091 /// a.push(rcx)?;
1092 /// // The address of this label is the next added instruction
1093 /// a.set_label(&mut label1)?;
1094 /// a.xor(rcx, rdx)?;
1095 /// // Target is the `xor rcx, rdx` instruction
1096 /// a.je(label1)?;
1097 /// a.nop()?;
1098 /// let result = a.assemble_options(0x1234_5678, BlockEncoderOptions::RETURN_NEW_INSTRUCTION_OFFSETS)?;
1099 /// assert_eq!(result.inner.rip, 0x1234_5678);
1100 /// assert_eq!(result.inner.code_buffer, b"\x51\x48\x31\xD1\x74\xFB\x90");
1101 /// // Get the address of the label, requires `BlockEncoderOptions::RETURN_NEW_INSTRUCTION_OFFSETS`
1102 /// assert_eq!(result.label_ip(&label1)?, 0x1234_5679);
1103 /// # Ok(())
1104 /// # }
1105 /// ```
1106 ///
1107 /// [`BlockEncoderOptions`]: ../struct.BlockEncoderOptions.html
1108 #[inline]
1109 pub fn assemble_options(&mut self, ip: u64, options: u32) -> Result<CodeAssemblerResult, IcedError> {
1110 if self.prefix_flags != 0 {
1111 return Err(IcedError::new("Unused prefixes. Did you forget to add an instruction?"));
1112 }
1113 if !self.current_label.is_empty() {
1114 return Err(IcedError::new("Unused label. Did you forget to add an instruction?"));
1115 }
1116 if self.defined_anon_label {
1117 return Err(IcedError::new("Unused anonymous label. Did you forget to add an instruction?"));
1118 }
1119 if !self.next_anon_label.is_empty() {
1120 return Err(IcedError::new("Unused anonymous fwd() label. Did you forget to call anonymous_label()?"));
1121 }
1122
1123 let block = InstructionBlock::new(self.instructions(), ip);
1124 let result = BlockEncoder::encode(self.bitness(), block, options)?;
1125 Ok(CodeAssemblerResult { inner: result })
1126 }
1127
1128 /// Gets the bitness (16, 32 or 64)
1129 #[must_use]
1130 #[inline]
1131 pub fn bitness(&self) -> u32 {
1132 self.bitness
1133 }
1134
1135 /// `true` (default value) to use `VEX` encoding intead of `EVEX` encoding if we must pick one of the encodings. See also [`vex()`] and [`evex()`]
1136 ///
1137 /// [`vex()`]: #method.vex
1138 /// [`evex()`]: #method.evex
1139 #[must_use]
1140 #[inline]
1141 pub fn prefer_vex(&self) -> bool {
1142 (self.options & CodeAssemblerOptions::PREFER_VEX) != 0
1143 }
1144
1145 /// `true` (default value) to use `VEX` encoding intead of `EVEX` encoding if we must pick one of the encodings. See also [`vex()`] and [`evex()`]
1146 ///
1147 /// [`vex()`]: #method.vex
1148 /// [`evex()`]: #method.evex
1149 ///
1150 /// # Arguments
1151 ///
1152 /// * `new_value`: New value
1153 #[inline]
1154 pub fn set_prefer_vex(&mut self, new_value: bool) {
1155 if new_value {
1156 self.options |= CodeAssemblerOptions::PREFER_VEX;
1157 } else {
1158 self.options &= !CodeAssemblerOptions::PREFER_VEX;
1159 }
1160 }
1161
1162 /// `true` (default value) to create short branches, `false` to create near branches.
1163 #[must_use]
1164 #[inline]
1165 pub fn prefer_short_branch(&self) -> bool {
1166 (self.options & CodeAssemblerOptions::PREFER_SHORT_BRANCH) != 0
1167 }
1168
1169 /// `true` (default value) to create short branches, `false` to create near branches.
1170 ///
1171 /// # Arguments
1172 ///
1173 /// * `new_value`: New value
1174 #[inline]
1175 pub fn set_prefer_short_branch(&mut self, new_value: bool) {
1176 if new_value {
1177 self.options |= CodeAssemblerOptions::PREFER_SHORT_BRANCH;
1178 } else {
1179 self.options &= !CodeAssemblerOptions::PREFER_SHORT_BRANCH;
1180 }
1181 }
1182
1183 #[inline]
1184 pub(crate) fn instruction_prefer_vex(&self) -> bool {
1185 if (self.prefix_flags & (PrefixFlags::PREFER_VEX | PrefixFlags::PREFER_EVEX)) != 0 {
1186 (self.prefix_flags & PrefixFlags::PREFER_VEX) != 0
1187 } else {
1188 (self.options & CodeAssemblerOptions::PREFER_VEX) != 0
1189 }
1190 }
1191
1192 /// `CALL FAR` instruction
1193 ///
1194 /// Instruction | Opcode | CPUID
1195 /// ------------|--------|------
1196 /// `CALL ptr16:16` | `o16 9A cd` | `8086+`
1197 /// `CALL ptr16:32` | `o32 9A cp` | `386+`
1198 ///
1199 /// # Errors
1200 ///
1201 /// Fails if an operand is invalid (basic checks only)
1202 ///
1203 /// # Arguments
1204 ///
1205 /// * `selector`: Selector/segment
1206 /// * `offset`: Offset within the segment
1207 #[inline]
1208 pub fn call_far(&mut self, selector: u16, offset: u32) -> Result<(), IcedError> {
1209 let code = if self.bitness() >= 32 { Code::Call_ptr1632 } else { Code::Call_ptr1616 };
1210 self.add_instr(Instruction::with_far_branch(code, selector, offset)?)
1211 }
1212
1213 /// `JMP FAR` instruction
1214 ///
1215 /// Instruction | Opcode | CPUID
1216 /// ------------|--------|------
1217 /// `JMP ptr16:16` | `o16 EA cd` | `8086+`
1218 /// `JMP ptr16:32` | `o32 EA cp` | `386+`
1219 ///
1220 /// # Errors
1221 ///
1222 /// Fails if an operand is invalid (basic checks only)
1223 ///
1224 /// # Arguments
1225 ///
1226 /// * `selector`: Selector/segment
1227 /// * `offset`: Offset within the segment
1228 #[inline]
1229 pub fn jmp_far(&mut self, selector: u16, offset: u32) -> Result<(), IcedError> {
1230 let code = if self.bitness() >= 32 { Code::Jmp_ptr1632 } else { Code::Jmp_ptr1616 };
1231 self.add_instr(Instruction::with_far_branch(code, selector, offset)?)
1232 }
1233
1234 /// `XLATB` instruction
1235 ///
1236 /// Instruction | Opcode | CPUID
1237 /// ------------|--------|------
1238 /// `XLATB` | `D7` | `8086+`
1239 ///
1240 /// # Errors
1241 ///
1242 /// Fails if an operand is invalid (basic checks only)
1243 #[inline]
1244 pub fn xlatb(&mut self) -> Result<(), IcedError> {
1245 let base = match self.bitness() {
1246 64 => Register::RBX,
1247 32 => Register::EBX,
1248 16 => Register::BX,
1249 _ => unreachable!(),
1250 };
1251 self.add_instr(Instruction::with1(Code::Xlat_m8, MemoryOperand::with_base_index(base, Register::AL))?)
1252 }
1253}