You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
283 lines
8.3 KiB
283 lines
8.3 KiB
/* BEGIN_LEGAL
|
|
|
|
Copyright (c) 2021 Intel Corporation
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
END_LEGAL */
|
|
|
|
/// @file xed-ex5-enc.c
|
|
|
|
// encoder example. (uses decoder too)
|
|
|
|
#include "xed/xed-interface.h"
|
|
#include "xed-examples-util.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h> // malloc, etc.
|
|
#include <string.h> //strcmp
|
|
#include <assert.h>
|
|
|
|
int main(int argc, char** argv);
|
|
|
|
int
|
|
main(int argc, char** argv)
|
|
{
|
|
xed_error_enum_t xed_error;
|
|
xed_state_t dstate32, dstate64;
|
|
xed_uint8_t itext[XED_MAX_INSTRUCTION_BYTES];
|
|
unsigned int ilen = XED_MAX_INSTRUCTION_BYTES;
|
|
unsigned int i, j, olen = 0, ninst=0;
|
|
xed_encoder_request_t enc_req;
|
|
#define NINST 50
|
|
xed_encoder_instruction_t x[NINST];
|
|
xed_bool_t convert_ok;
|
|
#if defined(XED_DECODER)
|
|
xed_bool_t ok;
|
|
# define DBUFLEN 1000
|
|
char buffer[DBUFLEN];
|
|
|
|
xed_decoded_inst_t xedd;
|
|
#endif
|
|
|
|
xed_tables_init();
|
|
xed_state_zero(&dstate32);
|
|
xed_state_zero(&dstate64);
|
|
|
|
dstate32.stack_addr_width=XED_ADDRESS_WIDTH_32b;
|
|
dstate32.mmode=XED_MACHINE_MODE_LEGACY_32;
|
|
|
|
dstate64.stack_addr_width=XED_ADDRESS_WIDTH_64b;
|
|
dstate64.mmode=XED_MACHINE_MODE_LONG_64;
|
|
|
|
xed_inst1(x+ninst, dstate64, XED_ICLASS_JMP, 64,
|
|
xed_relbr(0x11223344, 32));
|
|
ninst++;
|
|
|
|
/* using 0 for instructions that have the default effective operand
|
|
* width for their mode. The default effective operand width for 16b
|
|
* mode is 16b. The default effective operand width for 32b and 64b
|
|
* modes is 32b. */
|
|
|
|
// add an lock and xacquire
|
|
xed_inst2(x+ninst, dstate32, XED_ICLASS_XOR_LOCK, 0,
|
|
xed_mem_bd(XED_REG_EDX, xed_disp(0x11, 8), 32),
|
|
xed_reg(XED_REG_ECX) );
|
|
xed_repne(x+ninst); // xacquire
|
|
ninst++;
|
|
|
|
xed_inst2(x+ninst,
|
|
dstate32, XED_ICLASS_ADD, 0,
|
|
xed_reg(XED_REG_EAX),
|
|
xed_mem_bd(XED_REG_EDX, xed_disp(0x11223344, 32), 32));
|
|
ninst++;
|
|
|
|
xed_inst2(x+ninst,
|
|
dstate32, XED_ICLASS_ADD, 0,
|
|
xed_reg(XED_REG_EAX),
|
|
xed_mem_gbisd(XED_REG_FS,
|
|
XED_REG_EAX,
|
|
XED_REG_ESI,4, xed_disp(0x11223344, 32), 32));
|
|
ninst++;
|
|
|
|
// displacment-only LEA
|
|
xed_inst2(x+ninst,
|
|
dstate32, XED_ICLASS_LEA, 32,
|
|
xed_reg(XED_REG_EAX),
|
|
xed_mem_bd(XED_REG_INVALID, xed_disp(0x11223344, 32), 32));
|
|
ninst++;
|
|
|
|
|
|
xed_inst0(x+ninst, dstate32, XED_ICLASS_REPE_CMPSB, 0);
|
|
ninst++;
|
|
|
|
/* nondefault effective operand width for 32b mode so we must specify
|
|
it. XED could figure it out from the opcode, but currently does
|
|
not. */
|
|
xed_inst0(x+ninst, dstate32, XED_ICLASS_REPE_CMPSW, 16);
|
|
ninst++;
|
|
|
|
xed_inst0(x+ninst, dstate32, XED_ICLASS_REPE_CMPSD, 0);
|
|
ninst++;
|
|
|
|
xed_inst1(x+ninst, dstate32, XED_ICLASS_PUSH, 0, xed_reg(XED_REG_ECX));
|
|
ninst++;
|
|
|
|
xed_inst2(x+ninst, dstate32, XED_ICLASS_XOR, 0,
|
|
xed_reg(XED_REG_ECX),
|
|
xed_reg(XED_REG_EDX));
|
|
ninst++;
|
|
|
|
|
|
/* this one has a nondefault effective operand width for 64b mode so we
|
|
must specify it. XED could figure this output from the operands,
|
|
but currently it does not. */
|
|
|
|
xed_inst2(x+ninst, dstate64, XED_ICLASS_XOR, 64,
|
|
xed_reg(XED_REG_RCX),
|
|
xed_reg(XED_REG_RDX));
|
|
ninst++;
|
|
|
|
/* nondefault effective operand width for 64b mode so we must specify
|
|
it. XED could figure it out from the opcode, but currently does
|
|
not. */
|
|
xed_inst0(x+ninst, dstate64, XED_ICLASS_REPE_CMPSQ, 64);
|
|
ninst++;
|
|
|
|
/* here it is ambiguous from the opcode what the effective operand
|
|
* width is. I could use the operand, but do not do that yet. */
|
|
xed_inst1(x+ninst, dstate64, XED_ICLASS_PUSH, 64, xed_reg(XED_REG_RCX));
|
|
ninst++;
|
|
|
|
/* again, here's one where I could infer that the operation is 64b from
|
|
* the memory operand, but not yet. */
|
|
xed_inst1(x+ninst, dstate64, XED_ICLASS_PUSH, 64,
|
|
xed_mem_bd(XED_REG_RDX, xed_disp(0x11223344, 32), 64));
|
|
ninst++;
|
|
|
|
// move a 64b quantity in to RAX using only a 64b displacment
|
|
xed_inst2(x+ninst, dstate64, XED_ICLASS_MOV, 64,
|
|
xed_reg(XED_REG_RAX),
|
|
xed_mem_bd(XED_REG_INVALID, xed_disp(0x1122334455667788, 64), 64));
|
|
ninst++;
|
|
|
|
|
|
|
|
xed_inst1(x+ninst, dstate64, XED_ICLASS_JMP_FAR, 64,
|
|
xed_mem_bd(XED_REG_RAX, xed_disp(0x20, 8), 80));
|
|
|
|
ninst++;
|
|
|
|
xed_inst2(x+ninst,
|
|
dstate64, XED_ICLASS_ADD, 64,
|
|
xed_reg(XED_REG_RAX),
|
|
xed_imm0(0x77,8));
|
|
ninst++;
|
|
|
|
xed_inst2(x+ninst,
|
|
dstate64, XED_ICLASS_ADD, 64,
|
|
xed_reg(XED_REG_RAX),
|
|
xed_imm0(0x44332211,32));
|
|
ninst++;
|
|
|
|
xed_inst2(x+ninst,
|
|
dstate64, XED_ICLASS_MOV_CR, 64,
|
|
xed_reg(XED_REG_CR3),
|
|
xed_reg(XED_REG_RDI));
|
|
ninst++;
|
|
|
|
xed_inst2(x+ninst,
|
|
dstate64, XED_ICLASS_MOV, 32,
|
|
xed_mem_bisd(XED_REG_R8, XED_REG_RBP, 1, xed_disp(0xf8, 8), 32),
|
|
xed_simm0(0x0,32));
|
|
ninst++;
|
|
|
|
|
|
// example showing how to set the effective address size to 32b in 64b
|
|
// mode. Normally XED deduces that from the memory operand base
|
|
// register, but in this case the memops are implicit.
|
|
xed_inst0(x+ninst,
|
|
dstate64, XED_ICLASS_STOSQ, 64);
|
|
xed_addr(x+ninst, 32);
|
|
ninst++;
|
|
|
|
|
|
xed_inst1(x+ninst,
|
|
dstate32,
|
|
XED_ICLASS_JECXZ,
|
|
4,
|
|
xed_relbr(5, 8));
|
|
ninst++;
|
|
|
|
xed_inst1(x+ninst,
|
|
dstate64,
|
|
XED_ICLASS_JECXZ,
|
|
4,
|
|
xed_relbr(5, 8));
|
|
xed_addr(x+ninst,32);
|
|
ninst++;
|
|
|
|
xed_inst1(x+ninst,
|
|
dstate64,
|
|
XED_ICLASS_JRCXZ,
|
|
4,
|
|
xed_relbr(5, 8));
|
|
ninst++;
|
|
|
|
|
|
#if defined(XED_AVX)
|
|
xed_inst2(x+ninst,
|
|
dstate64,
|
|
XED_ICLASS_VBROADCASTSD,
|
|
32,
|
|
xed_reg(XED_REG_YMM4),
|
|
xed_mem_gbisd(XED_REG_GS,XED_REG_INVALID,0,0,
|
|
xed_disp(0x808, 32),
|
|
64));
|
|
ninst++;
|
|
#endif
|
|
|
|
#if defined(XED_SUPPORTS_AVX512)
|
|
// example showing how to set EVEX features.
|
|
// increase the number of operands and use xed_other(...)
|
|
xed_inst5(x+ninst,
|
|
dstate64,
|
|
XED_ICLASS_VADDPS,
|
|
32,
|
|
xed_reg(XED_REG_XMM1),
|
|
xed_reg(XED_REG_K1),
|
|
xed_reg(XED_REG_XMM2),
|
|
xed_mem_b(XED_REG_RCX, 16),
|
|
xed_other(XED_OPERAND_ZEROING,1));
|
|
ninst++;
|
|
#endif
|
|
|
|
|
|
for(i=0;i<ninst;i++) {
|
|
xed_encoder_request_zero_set_mode(&enc_req, &(x[i].mode));
|
|
convert_ok = xed_convert_to_encoder_request(&enc_req, x+i);
|
|
if (!convert_ok) {
|
|
fprintf(stderr,"conversion to encode request failed\n");
|
|
continue;
|
|
}
|
|
xed_error = xed_encode(&enc_req, itext, ilen, &olen);
|
|
if (xed_error != XED_ERROR_NONE) {
|
|
fprintf(stderr,"ENCODE ERROR: %s\n",
|
|
xed_error_enum_t2str(xed_error));
|
|
continue;
|
|
}
|
|
printf("Result: %d\n\t", (int)i);
|
|
for(j=0;j<olen;j++)
|
|
printf("%02x ", itext[j]);
|
|
|
|
printf("\n");
|
|
#if defined(XED_DECODER)
|
|
xed_decoded_inst_zero_set_mode(&xedd, &(x[i].mode));
|
|
xed_error = xed_decode(&xedd, itext, olen);
|
|
if (xed_error != XED_ERROR_NONE) {
|
|
fprintf(stderr,"DECODE ERROR: %s\n",
|
|
xed_error_enum_t2str(xed_error));
|
|
continue;
|
|
}
|
|
ok = xed_format_context(XED_SYNTAX_INTEL, &xedd, buffer, DBUFLEN, 0, 0, 0);
|
|
if (ok)
|
|
printf("\t%s\n", buffer);
|
|
else
|
|
fprintf(stderr,"DISASSEMBLY ERROR\n");
|
|
#endif
|
|
|
|
}
|
|
return 0;
|
|
(void) argc;
|
|
(void) argv;
|
|
}
|