Skip to content

Instantly share code, notes, and snippets.

@ice799
Created November 16, 2010 20:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ice799/702435 to your computer and use it in GitHub Desktop.
Save ice799/702435 to your computer and use it in GitHub Desktop.
// Returns number of bytes used, including *data.
int DisassemblerX64::JumpConditionalShort(byte* data) {
byte cond = *data & 0x0F;
byte b = *(data + 1);
byte* dest = data + static_cast<int8_t>(b) + 2;
const char* mnem = conditional_code_suffix[cond];
AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
return 2;
}
//
//
// elsewhere....
//
//
Operand::Operand(const Operand& operand, int32_t offset) {
ASSERT(operand.len_ >= 1);
// Operand encodes REX ModR/M [SIB] [Disp].
byte modrm = operand.buf_[0];
ASSERT(modrm < 0xC0); // Disallow mode 3 (register target).
bool has_sib = ((modrm & 0x07) == 0x04);
byte mode = modrm & 0xC0;
int disp_offset = has_sib ? 2 : 1;
int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07;
// Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit
// displacement.
bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base.
int32_t disp_value = 0;
if (mode == 0x80 || is_baseless) {
// Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
disp_value = *BitCast<const int32_t*>(&operand.buf_[disp_offset]);
} else if (mode == 0x40) {
// Mode 1: Byte displacement.
disp_value = static_cast<signed char>(operand.buf_[disp_offset]);
}
// Write new operand with same registers, but with modified displacement.
ASSERT(offset >= 0 ? disp_value + offset > disp_value
: disp_value + offset < disp_value); // No overflow.
disp_value += offset;
rex_ = operand.rex_;
if (!is_int8(disp_value) || is_baseless) {
// Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80);
len_ = disp_offset + 4;
Memory::int32_at(&buf_[disp_offset]) = disp_value;
} else if (disp_value != 0 || (base_reg == 0x05)) {
// Need 8 bits of displacement.
buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1.
len_ = disp_offset + 1;
buf_[disp_offset] = static_cast<byte>(disp_value);
} else {
// Need no displacement.
buf_[0] = (modrm & 0x3f); // Mode 0.
len_ = disp_offset;
}
if (has_sib) {
buf_[1] = operand.buf_[1];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment