/src/zydis/src/FormatterIntel.c
Line | Count | Source |
1 | | /*************************************************************************************************** |
2 | | |
3 | | Zyan Disassembler Library (Zydis) |
4 | | |
5 | | Original Author : Florian Bernd, Joel Hoener |
6 | | |
7 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
8 | | * of this software and associated documentation files (the "Software"), to deal |
9 | | * in the Software without restriction, including without limitation the rights |
10 | | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
11 | | * copies of the Software, and to permit persons to whom the Software is |
12 | | * furnished to do so, subject to the following conditions: |
13 | | * |
14 | | * The above copyright notice and this permission notice shall be included in all |
15 | | * copies or substantial portions of the Software. |
16 | | * |
17 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
18 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
19 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
20 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
21 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
22 | | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
23 | | * SOFTWARE. |
24 | | |
25 | | ***************************************************************************************************/ |
26 | | |
27 | | #include <Zydis/Internal/FormatterIntel.h> |
28 | | #include <Zydis/Utils.h> |
29 | | #include <Zycore/Format.h> |
30 | | |
31 | | /* ============================================================================================== */ |
32 | | /* Constants */ |
33 | | /* ============================================================================================== */ |
34 | | |
35 | | #include <Generated/FormatterStrings.inc> |
36 | | |
37 | | /* ============================================================================================== */ |
38 | | /* Formatter functions */ |
39 | | /* ============================================================================================== */ |
40 | | |
41 | | /* ---------------------------------------------------------------------------------------------- */ |
42 | | /* Intel */ |
43 | | /* ---------------------------------------------------------------------------------------------- */ |
44 | | |
45 | | ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter, |
46 | | ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) |
47 | 2.51k | { |
48 | 2.51k | ZYAN_ASSERT(formatter); |
49 | 2.51k | ZYAN_ASSERT(buffer); |
50 | 2.51k | ZYAN_ASSERT(context); |
51 | 2.51k | ZYAN_ASSERT(context->instruction); |
52 | 2.51k | ZYAN_ASSERT(context->operands); |
53 | | |
54 | 2.51k | if (!formatter->deco_apx_nf_use_suffix) |
55 | 2.51k | { |
56 | 2.51k | ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, |
57 | 2.51k | ZYDIS_DECORATOR_APX_NF)); |
58 | 2.51k | } |
59 | | |
60 | 2.50k | ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context)); |
61 | 2.47k | ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context)); |
62 | | |
63 | 2.28k | if (!formatter->deco_apx_dfv_use_immediate) |
64 | 2.28k | { |
65 | 2.28k | ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, |
66 | 2.28k | ZYDIS_DECORATOR_APX_DFV)); |
67 | 2.28k | } |
68 | | |
69 | 2.24k | ZyanUPointer state_mnemonic; |
70 | 2.24k | ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic); |
71 | | |
72 | 2.24k | if (formatter->deco_apx_dfv_use_immediate && (context->instruction->apx.scc != ZYDIS_SCC_NONE)) |
73 | 0 | { |
74 | 0 | ZYDIS_BUFFER_APPEND(buffer, DELIM_MNEMONIC); |
75 | 0 | ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); |
76 | 0 | ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, |
77 | 0 | context->instruction->apx.default_flags, 0, |
78 | 0 | formatter->number_format[ZYDIS_NUMERIC_BASE_DEC][0].string, |
79 | 0 | formatter->number_format[ZYDIS_NUMERIC_BASE_DEC][1].string)); |
80 | 0 | } |
81 | | |
82 | 4.77k | for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i) |
83 | 3.35k | { |
84 | 3.35k | const ZydisDecodedOperand* const operand = &context->operands[i]; |
85 | | |
86 | | // Print embedded-mask registers as decorator instead of a regular operand |
87 | 3.35k | if ((i == 1) && (operand->type == ZYDIS_OPERAND_TYPE_REGISTER) && |
88 | 615 | (operand->encoding == ZYDIS_OPERAND_ENCODING_MASK)) |
89 | 114 | { |
90 | 114 | continue; |
91 | 114 | } |
92 | | |
93 | 3.24k | ZyanUPointer buffer_state; |
94 | 3.24k | ZYDIS_BUFFER_REMEMBER(buffer, buffer_state); |
95 | | |
96 | 3.24k | if (buffer_state != state_mnemonic) |
97 | 1.19k | { |
98 | 1.19k | ZYDIS_BUFFER_APPEND(buffer, DELIM_OPERAND); |
99 | 1.15k | } else |
100 | 2.04k | { |
101 | 2.04k | ZYDIS_BUFFER_APPEND(buffer, DELIM_MNEMONIC); |
102 | 1.97k | } |
103 | | |
104 | | // Set current operand |
105 | 3.13k | context->operand = operand; |
106 | | |
107 | 3.13k | ZyanStatus status; |
108 | 3.13k | if (formatter->func_pre_operand) |
109 | 0 | { |
110 | 0 | status = formatter->func_pre_operand(formatter, buffer, context); |
111 | 0 | if (status == ZYDIS_STATUS_SKIP_TOKEN) |
112 | 0 | { |
113 | 0 | ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state)); |
114 | 0 | continue; |
115 | 0 | } |
116 | 0 | if (!ZYAN_SUCCESS(status)) |
117 | 0 | { |
118 | 0 | return status; |
119 | 0 | } |
120 | 0 | } |
121 | | |
122 | 3.13k | switch (operand->type) |
123 | 3.13k | { |
124 | 1.33k | case ZYDIS_OPERAND_TYPE_REGISTER: |
125 | 1.33k | status = formatter->func_format_operand_reg(formatter, buffer, context); |
126 | 1.33k | break; |
127 | 1.28k | case ZYDIS_OPERAND_TYPE_MEMORY: |
128 | 1.28k | status = formatter->func_format_operand_mem(formatter, buffer, context); |
129 | 1.28k | break; |
130 | 23 | case ZYDIS_OPERAND_TYPE_POINTER: |
131 | 23 | status = formatter->func_format_operand_ptr(formatter, buffer, context); |
132 | 23 | break; |
133 | 490 | case ZYDIS_OPERAND_TYPE_IMMEDIATE: |
134 | 490 | status = formatter->func_format_operand_imm(formatter, buffer, context); |
135 | 490 | break; |
136 | 0 | default: |
137 | 0 | return ZYAN_STATUS_INVALID_ARGUMENT; |
138 | 3.13k | } |
139 | 3.13k | if (status == ZYDIS_STATUS_SKIP_TOKEN) |
140 | 0 | { |
141 | 0 | ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state)); |
142 | 0 | continue; |
143 | 0 | } |
144 | 3.13k | if (!ZYAN_SUCCESS(status)) |
145 | 684 | { |
146 | 684 | return status; |
147 | 684 | } |
148 | | |
149 | 2.44k | if (formatter->func_post_operand) |
150 | 0 | { |
151 | 0 | status = formatter->func_post_operand(formatter, buffer, context); |
152 | 0 | if (status == ZYDIS_STATUS_SKIP_TOKEN) |
153 | 0 | { |
154 | 0 | ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state)); |
155 | 0 | continue; |
156 | 0 | } |
157 | 0 | if (ZYAN_SUCCESS(status)) |
158 | 0 | { |
159 | 0 | return status; |
160 | 0 | } |
161 | 0 | } |
162 | | |
163 | 2.44k | #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC) |
164 | 2.44k | if ((context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) || |
165 | 2.21k | (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)) |
166 | 435 | { |
167 | 435 | if ((i == 0) && |
168 | 190 | (context->instruction->operand_count_visible > 1) && |
169 | 183 | (context->operands[i + 1].encoding == ZYDIS_OPERAND_ENCODING_MASK)) |
170 | 129 | { |
171 | 129 | ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, |
172 | 129 | ZYDIS_DECORATOR_MASK)); |
173 | 129 | } |
174 | 422 | if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY) |
175 | 113 | { |
176 | 113 | ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, |
177 | 113 | ZYDIS_DECORATOR_BC)); |
178 | 105 | if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX) |
179 | 40 | { |
180 | 40 | ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, |
181 | 40 | ZYDIS_DECORATOR_CONVERSION)); |
182 | 37 | ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, |
183 | 37 | ZYDIS_DECORATOR_EH)); |
184 | 37 | } |
185 | 105 | } else |
186 | 309 | { |
187 | 309 | ZyanBool decorate_operand; |
188 | 309 | if (i == (context->instruction->operand_count_visible - 1)) |
189 | 83 | { |
190 | 83 | decorate_operand = operand->type != ZYDIS_OPERAND_TYPE_IMMEDIATE; |
191 | 83 | } |
192 | 226 | else |
193 | 226 | { |
194 | 226 | decorate_operand = |
195 | 226 | (context->instruction->operand_count_visible > (i + 1)) && |
196 | 226 | ((context->operands[i + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) || |
197 | 216 | (context->operands[i + 1].visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN)); |
198 | 226 | } |
199 | 309 | if (decorate_operand) |
200 | 83 | { |
201 | 83 | if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX) |
202 | 33 | { |
203 | 33 | ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, |
204 | 33 | ZYDIS_DECORATOR_SWIZZLE)); |
205 | 33 | } |
206 | 79 | ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, |
207 | 79 | ZYDIS_DECORATOR_RC)); |
208 | 74 | ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, |
209 | 74 | ZYDIS_DECORATOR_SAE)); |
210 | 74 | } |
211 | 309 | } |
212 | 422 | } |
213 | 2.44k | #endif |
214 | 2.44k | } |
215 | | |
216 | 1.41k | return ZYAN_STATUS_SUCCESS; |
217 | 2.24k | } |
218 | | |
219 | | ZyanStatus ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter* formatter, |
220 | | ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) |
221 | 2.37k | { |
222 | 2.37k | ZYAN_ASSERT(formatter); |
223 | 2.37k | ZYAN_ASSERT(buffer); |
224 | 2.37k | ZYAN_ASSERT(context); |
225 | | |
226 | 2.37k | if ((context->operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) || |
227 | 156 | (context->operand->mem.type == ZYDIS_MEMOP_TYPE_AGEN) || |
228 | 93 | (context->operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB)) |
229 | 2.34k | { |
230 | 2.34k | ZYAN_CHECK(formatter->func_print_typecast(formatter, buffer, context)); |
231 | 2.34k | } |
232 | 2.14k | ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context)); |
233 | | |
234 | 2.04k | ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_INTEL); |
235 | | |
236 | 1.98k | const ZyanBool absolute = !formatter->force_relative_riprel && |
237 | 1.06k | (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE); |
238 | 1.98k | if (absolute && context->operand->mem.disp.size && |
239 | 389 | (context->operand->mem.index == ZYDIS_REGISTER_NONE) && |
240 | 275 | ((context->operand->mem.base == ZYDIS_REGISTER_NONE) || |
241 | 204 | (context->operand->mem.base == ZYDIS_REGISTER_EIP ) || |
242 | 190 | (context->operand->mem.base == ZYDIS_REGISTER_RIP ))) |
243 | 111 | { |
244 | | // EIP/RIP-relative or absolute-displacement address operand |
245 | 111 | ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context)); |
246 | 111 | } else |
247 | 1.87k | { |
248 | 1.87k | const ZyanBool should_print_reg = context->operand->mem.base != ZYDIS_REGISTER_NONE; |
249 | 1.87k | const ZyanBool should_print_idx = context->operand->mem.index != ZYDIS_REGISTER_NONE; |
250 | 1.87k | const ZyanBool neither_reg_nor_idx = !should_print_reg && !should_print_idx; |
251 | | |
252 | | // Regular memory operand |
253 | 1.87k | if (should_print_reg) |
254 | 1.73k | { |
255 | 1.73k | ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, |
256 | 1.73k | context->operand->mem.base)); |
257 | 1.73k | } |
258 | 1.79k | if (should_print_idx) |
259 | 674 | { |
260 | 674 | if (context->operand->mem.base != ZYDIS_REGISTER_NONE) |
261 | 612 | { |
262 | 612 | ZYDIS_BUFFER_APPEND(buffer, ADD); |
263 | 591 | } |
264 | 653 | ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, |
265 | 653 | context->operand->mem.index)); |
266 | 627 | if (context->operand->mem.scale && |
267 | 627 | (context->operand->mem.type != ZYDIS_MEMOP_TYPE_MIB) && |
268 | 610 | ((context->operand->mem.scale > 1) || formatter->force_memory_scale)) |
269 | 478 | { |
270 | 478 | ZYDIS_BUFFER_APPEND(buffer, MUL); |
271 | 464 | ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); |
272 | 458 | ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, context->operand->mem.scale, 0, |
273 | 458 | ZYAN_NULL, ZYAN_NULL)); |
274 | 458 | } |
275 | 627 | } |
276 | 1.72k | if (neither_reg_nor_idx) |
277 | 84 | { |
278 | 84 | ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context)); |
279 | 1.64k | } else if (context->operand->mem.disp.size && context->operand->mem.disp.value) |
280 | 643 | { |
281 | 643 | ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context)); |
282 | 643 | } |
283 | 1.72k | } |
284 | | |
285 | 1.53k | ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_INTEL); |
286 | 1.48k | return ZYAN_STATUS_SUCCESS; |
287 | 1.53k | } |
288 | | |
289 | | ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter, |
290 | | ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) |
291 | 2.47k | { |
292 | 2.47k | ZYAN_ASSERT(formatter); |
293 | 2.47k | ZYAN_ASSERT(buffer); |
294 | 2.47k | ZYAN_ASSERT(context); |
295 | | |
296 | 2.47k | const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped( |
297 | 2.47k | context->instruction->mnemonic); |
298 | 2.47k | if (!mnemonic) |
299 | 0 | { |
300 | 0 | ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic); |
301 | 0 | return ZYAN_STATUS_SUCCESS; |
302 | 0 | } |
303 | | |
304 | 2.47k | ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC); |
305 | 2.45k | ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic)); |
306 | | |
307 | 2.33k | if (formatter->deco_apx_nf_use_suffix && context->instruction->apx.has_nf) |
308 | 0 | { |
309 | 0 | ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_NF, formatter->case_mnemonic)); |
310 | 0 | } |
311 | | |
312 | 2.33k | if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR) |
313 | 81 | { |
314 | 81 | return ZydisStringAppendShortCase(&buffer->string, &STR_FAR, formatter->case_mnemonic); |
315 | 81 | } |
316 | | |
317 | 2.25k | if (formatter->print_branch_size) |
318 | 1.46k | { |
319 | 1.46k | switch (context->instruction->meta.branch_type) |
320 | 1.46k | { |
321 | 1.18k | case ZYDIS_BRANCH_TYPE_NONE: |
322 | 1.18k | break; |
323 | 183 | case ZYDIS_BRANCH_TYPE_SHORT: |
324 | 183 | return ZydisStringAppendShortCase(&buffer->string, &STR_SHORT, |
325 | 183 | formatter->case_mnemonic); |
326 | 95 | case ZYDIS_BRANCH_TYPE_NEAR: |
327 | 95 | return ZydisStringAppendShortCase(&buffer->string, &STR_NEAR, |
328 | 95 | formatter->case_mnemonic); |
329 | 3 | default: |
330 | 3 | return ZYAN_STATUS_INVALID_ARGUMENT; |
331 | 1.46k | } |
332 | 1.46k | } |
333 | | |
334 | 1.97k | return ZYAN_STATUS_SUCCESS; |
335 | 2.25k | } |
336 | | |
337 | | ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter, |
338 | | ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg) |
339 | 6.01k | { |
340 | 6.01k | ZYAN_UNUSED(context); |
341 | | |
342 | 6.01k | ZYAN_ASSERT(formatter); |
343 | 6.01k | ZYAN_ASSERT(buffer); |
344 | 6.01k | ZYAN_ASSERT(context); |
345 | | |
346 | 6.01k | const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg); |
347 | 6.01k | if (!str) |
348 | 0 | { |
349 | 0 | ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_REG, formatter->case_registers); |
350 | 0 | return ZYAN_STATUS_SUCCESS; |
351 | 0 | } |
352 | | |
353 | 6.01k | ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_REGISTER); |
354 | 5.94k | return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers); |
355 | 6.01k | } |
356 | | |
357 | | ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter, |
358 | | ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) |
359 | 643 | { |
360 | 643 | ZYAN_ASSERT(formatter); |
361 | 643 | ZYAN_ASSERT(buffer); |
362 | 643 | ZYAN_ASSERT(context); |
363 | | |
364 | 643 | switch (formatter->disp_signedness) |
365 | 643 | { |
366 | 374 | case ZYDIS_SIGNEDNESS_AUTO: |
367 | 620 | case ZYDIS_SIGNEDNESS_SIGNED: |
368 | 620 | if (context->operand->mem.disp.value < 0) |
369 | 433 | { |
370 | 433 | if ((context->operand->mem.base != ZYDIS_REGISTER_NONE) || |
371 | 24 | (context->operand->mem.index != ZYDIS_REGISTER_NONE)) |
372 | 433 | { |
373 | 433 | ZYDIS_BUFFER_APPEND(buffer, SUB); |
374 | 423 | } |
375 | 423 | ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT); |
376 | 419 | ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string, |
377 | 419 | ZyanAbsI64(context->operand->mem.disp.value), formatter->disp_padding, |
378 | 419 | formatter->hex_force_leading_number); |
379 | 284 | break; |
380 | 419 | } |
381 | 187 | ZYAN_FALLTHROUGH; |
382 | 210 | case ZYDIS_SIGNEDNESS_UNSIGNED: |
383 | 210 | if ((context->operand->mem.base != ZYDIS_REGISTER_NONE) || |
384 | 33 | (context->operand->mem.index != ZYDIS_REGISTER_NONE)) |
385 | 210 | { |
386 | 210 | ZYDIS_BUFFER_APPEND(buffer, ADD); |
387 | 196 | } |
388 | 196 | ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT); |
389 | 194 | ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string, |
390 | 194 | context->operand->mem.disp.value, formatter->disp_padding, |
391 | 194 | formatter->hex_force_leading_number); |
392 | 131 | break; |
393 | 0 | default: |
394 | 0 | return ZYAN_STATUS_INVALID_ARGUMENT; |
395 | 643 | } |
396 | | |
397 | 415 | return ZYAN_STATUS_SUCCESS; |
398 | 643 | } |
399 | | |
400 | | ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter, |
401 | | ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) |
402 | 2.34k | { |
403 | 2.34k | ZYAN_ASSERT(formatter); |
404 | 2.34k | ZYAN_ASSERT(buffer); |
405 | 2.34k | ZYAN_ASSERT(context); |
406 | | |
407 | 2.34k | switch (ZydisFormatterHelperGetExplicitSize(formatter, context, context->operand)) |
408 | 2.34k | { |
409 | 750 | case 8: ZYDIS_BUFFER_APPEND(buffer, SIZE_8_INTEL ); break; |
410 | 311 | case 16: ZYDIS_BUFFER_APPEND(buffer, SIZE_16_INTEL ); break; |
411 | 317 | case 32: ZYDIS_BUFFER_APPEND(buffer, SIZE_32_INTEL ); break; |
412 | 84 | case 48: ZYDIS_BUFFER_APPEND(buffer, SIZE_48 ); break; |
413 | 134 | case 64: ZYDIS_BUFFER_APPEND(buffer, SIZE_64_INTEL ); break; |
414 | 109 | case 80: ZYDIS_BUFFER_APPEND(buffer, SIZE_80 ); break; |
415 | 86 | case 128: ZYDIS_BUFFER_APPEND(buffer, SIZE_128_INTEL); break; |
416 | 94 | case 256: ZYDIS_BUFFER_APPEND(buffer, SIZE_256_INTEL); break; |
417 | 72 | case 512: ZYDIS_BUFFER_APPEND(buffer, SIZE_512_INTEL); break; |
418 | 386 | default: |
419 | 386 | break; |
420 | 2.34k | } |
421 | | |
422 | 2.10k | return ZYAN_STATUS_SUCCESS; |
423 | 2.34k | } |
424 | | |
425 | | /* ---------------------------------------------------------------------------------------------- */ |
426 | | /* MASM */ |
427 | | /* ---------------------------------------------------------------------------------------------- */ |
428 | | |
429 | | ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter, |
430 | | ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) |
431 | 1.11k | { |
432 | 1.11k | ZYAN_ASSERT(formatter); |
433 | 1.11k | ZYAN_ASSERT(buffer); |
434 | 1.11k | ZYAN_ASSERT(context); |
435 | | |
436 | | // Force the formatter to always call our MASM `ZYDIS_FORMATTER_PRINT_ADDRESS_ABS` function. |
437 | | // This implicitly omits printing of the `RIP`/`EIP` registers for `RIP`/`EIP`-relative |
438 | | // memory operands |
439 | 1.11k | context->runtime_address = 0; |
440 | | |
441 | 1.11k | return ZydisFormatterIntelFormatInstruction(formatter, buffer, context); |
442 | 1.11k | } |
443 | | |
444 | | ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter, |
445 | | ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) |
446 | 635 | { |
447 | 635 | ZYAN_ASSERT(formatter); |
448 | 635 | ZYAN_ASSERT(buffer); |
449 | 635 | ZYAN_ASSERT(context); |
450 | | |
451 | 635 | ZyanU64 address; |
452 | 635 | ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address)); |
453 | | |
454 | 635 | ZyanU8 padding = (formatter->addr_padding_relative == |
455 | 635 | ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative; |
456 | 635 | if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) && |
457 | 145 | (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX)) |
458 | 88 | { |
459 | 88 | switch (context->instruction->address_width) |
460 | 88 | { |
461 | 27 | case 16: |
462 | 27 | padding = 4; |
463 | 27 | address = (ZyanU16)address; |
464 | 27 | break; |
465 | 40 | case 32: |
466 | 40 | padding = 8; |
467 | 40 | address = (ZyanU32)address; |
468 | 40 | break; |
469 | 21 | case 64: |
470 | 21 | padding = 16; |
471 | 21 | break; |
472 | 0 | default: |
473 | 0 | return ZYAN_STATUS_INVALID_ARGUMENT; |
474 | 88 | } |
475 | 88 | } |
476 | | |
477 | 635 | ZYDIS_BUFFER_APPEND(buffer, ADDR_RELATIVE); |
478 | 607 | ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address, padding, |
479 | 607 | formatter->hex_force_leading_number, ZYAN_TRUE); |
480 | | |
481 | 390 | return ZYAN_STATUS_SUCCESS; |
482 | 607 | } |
483 | | |
484 | | /* ---------------------------------------------------------------------------------------------- */ |
485 | | |
486 | | /* ============================================================================================== */ |