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}