From 8ab5f5fb5b07d62aa9941a15cd7c9a71981c80dd Mon Sep 17 00:00:00 2001 From: Sven Steinbauer Date: Fri, 23 Sep 2016 16:26:07 +0100 Subject: [PATCH] Add short jumps to nz (#5832) --- libr/asm/p/asm_x86_nz.c | 69 ++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/libr/asm/p/asm_x86_nz.c b/libr/asm/p/asm_x86_nz.c index 06a44d3a1e..6d883b2369 100644 --- a/libr/asm/p/asm_x86_nz.c +++ b/libr/asm/p/asm_x86_nz.c @@ -110,6 +110,7 @@ typedef struct Opcode_t { char *mnemonic; ut32 op[3]; size_t op_len; + bool is_short; ut8 opcode[3]; Operand operands[2]; } Opcode; @@ -785,6 +786,9 @@ static int opjc(RAsm *a, ut8 *data, const Opcode op) { int l = 0; ut64 instr_offset = a->pc; int immediate = op.operands[0].immediate * op.operands[0].sign; + if (op.is_short && (immediate > ST8_MAX || immediate < ST8_MIN)) { + return l; + } if (!strcmp (op.mnemonic, "jmp")) { if (op.operands[0].type & OT_GPREG) { data[l++] = 0xff; @@ -807,59 +811,70 @@ static int opjc(RAsm *a, ut8 *data, const Opcode op) { } return l; } - immediate -= 6; - data[l++] = 0x0f; + if (op.is_short) { + immediate -= 2; + } else { + immediate -= 6; + } + if (!op.is_short) {data[l++] = 0x0f;} if (!strcmp (op.mnemonic, "ja") || !strcmp (op.mnemonic, "jnbe")) { data[l++] = 0x87; } else if (!strcmp (op.mnemonic, "jae") || - !strcmp (op.mnemonic, "jnb") || - !strcmp (op.mnemonic, "jnc")) { + !strcmp (op.mnemonic, "jnb") || + !strcmp (op.mnemonic, "jnc")) { data[l++] = 0x83; } else if (!strcmp (op.mnemonic, "jz") || - !strcmp (op.mnemonic, "je")) { + !strcmp (op.mnemonic, "je")) { data[l++] = 0x84; } else if (!strcmp (op.mnemonic, "jb") || - !strcmp (op.mnemonic, "jnae") || - !strcmp (op.mnemonic, "jc")) { + !strcmp (op.mnemonic, "jnae") || + !strcmp (op.mnemonic, "jc")) { data[l++] = 0x82; } else if (!strcmp (op.mnemonic, "jbe") || - !strcmp (op.mnemonic, "jna")) { + !strcmp (op.mnemonic, "jna")) { data[l++] = 0x86; - } else if (!strcmp (op.mnemonic, "jg")) { + } else if (!strcmp (op.mnemonic, "jg") || + !strcmp (op.mnemonic, "jnle")) { data[l++] = 0x8f; } else if (!strcmp (op.mnemonic, "jge") || - !strcmp (op.mnemonic, "jnl")) { + !strcmp (op.mnemonic, "jnl")) { data[l++] = 0x8d; } else if (!strcmp (op.mnemonic, "jl") || - !strcmp (op.mnemonic, "jnge")) { + !strcmp (op.mnemonic, "jnge")) { data[l++] = 0x8c; } else if (!strcmp (op.mnemonic, "jle") || - !strcmp (op.mnemonic, "jng")) { + !strcmp (op.mnemonic, "jng")) { data[l++] = 0x8e; } else if (!strcmp (op.mnemonic, "jne") || - !strcmp (op.mnemonic, "jnz")) { + !strcmp (op.mnemonic, "jnz")) { data[l++] = 0x85; } else if (!strcmp (op.mnemonic, "jno")) { data[l++] = 0x81; - } else if (!strcmp (op.mnemonic, "jnp")) { + } else if (!strcmp (op.mnemonic, "jnp") || + !strcmp (op.mnemonic, "jpo")) { data[l++] = 0x8b; } else if (!strcmp (op.mnemonic, "jns")) { data[l++] = 0x89; } else if (!strcmp (op.mnemonic, "jo")) { data[l++] = 0x80; } else if (!strcmp (op.mnemonic, "jp") || - !strcmp(op.mnemonic, "jpe")) { + !strcmp(op.mnemonic, "jpe")) { data[l++] = 0x8a; } else if (!strcmp (op.mnemonic, "js") || - !strcmp (op.mnemonic, "jz") || - !strcmp (op.mnemonic, "jpo")) { + !strcmp (op.mnemonic, "jz")) { data[l++] = 0x88; } + if (op.is_short) { + data[l-1] -= 0x10; + } + data[l++] = immediate; - data[l++] = immediate >> 8; - data[l++] = immediate >> 16; - data[l++] = immediate >> 24; + if (!op.is_short) { + data[l++] = immediate >> 8; + data[l++] = immediate >> 16; + data[l++] = immediate >> 24; + } return l; } @@ -1525,6 +1540,7 @@ LookupTable oplookup[] = { {"jae", &opjc, 0}, {"jb", &opjc, 0}, {"jbe", &opjc, 0}, + {"jc", &opjc, 0}, {"je", &opjc, 0}, {"jg", &opjc, 0}, {"jge", &opjc, 0}, @@ -1533,11 +1549,14 @@ LookupTable oplookup[] = { {"jmp", &opjc, 0}, {"jna", &opjc, 0}, {"jnae", &opjc, 0}, + {"jnb", &opjc, 0}, {"jnbe", &opjc, 0}, + {"jnc", &opjc, 0}, {"jne", &opjc, 0}, {"jng", &opjc, 0}, {"jnge", &opjc, 0}, {"jnl", &opjc, 0}, + {"jnle", &opjc, 0}, {"jno", &opjc, 0}, {"jnp", &opjc, 0}, {"jns", &opjc, 0}, @@ -1986,12 +2005,18 @@ static int parseOpcode(RAsm *a, const char *op, Opcode *out) { out->operands[0].immediate = out->operands[1].immediate = 0; out->operands[0].sign = out->operands[1].sign = 1; out->operands[0].is_good_flag = out->operands[1].is_good_flag = true; - + out->is_short = false; if (args) { args++; } else { return 1; } + + if (!strncasecmp (args, "short", 5)) { + out->is_short = true; + args += 5; + } + parseOperand (a, args, &(out->operands[0])); args = strchr (args, ','); if (args) { @@ -2057,7 +2082,7 @@ static int assemble(RAsm *a, RAsmOp *ao, const char *str) { } break; } - } + } } //eprintf ("Error: Unknown instruction (%s)\n", instr.mnemonic); return -1;