New approach to disambiguating /disp32 arguments: based on opcodes rather
than metadata.

I interpret /disp32 as PC-relative in a short list of instructions. Otherwise
it's absolute if it gets a label.

There should be no reason to pass labels into /disp8 or /disp16.
This commit is contained in:
Kartik Agaram 2020-12-28 23:20:14 -08:00
parent d6d8ce2244
commit b15db82f7c
1 changed files with 15 additions and 2 deletions

View File

@ -224,6 +224,7 @@ void replace_labels_with_displacements(segment& code, const map<string, int32_t>
const word& curr = inst.words.at(j);
if (contains_key(byte_index, curr.data)) {
int32_t displacement = static_cast<int32_t>(get(byte_index, curr.data)) - byte_index_next_instruction_starts_at;
int32_t absolute_address = code.start + get(byte_index, curr.data);
if (has_argument_metadata(curr, "disp8")) {
if (displacement > 0x7f || displacement < -0x7f)
raise << "'" << to_string(inst) << "': label too far away for displacement " << std::hex << displacement << " to fit in 8 signed bits\n" << end();
@ -237,9 +238,12 @@ void replace_labels_with_displacements(segment& code, const map<string, int32_t>
emit_hex_bytes(new_inst, displacement, 2);
}
else if (has_argument_metadata(curr, "disp32")) {
emit_hex_bytes(new_inst, displacement, 4);
if (is_far_jump_or_call(new_inst))
emit_hex_bytes(new_inst, displacement, 4);
else
emit_hex_bytes(new_inst, absolute_address, 4);
} else if (has_argument_metadata(curr, "imm32")) {
emit_hex_bytes(new_inst, code.start + get(byte_index, curr.data), 4);
emit_hex_bytes(new_inst, absolute_address, 4);
}
}
else {
@ -251,6 +255,15 @@ void replace_labels_with_displacements(segment& code, const map<string, int32_t>
}
}
bool is_far_jump_or_call(const line& inst) {
string first_opcode = inst.words.at(0).data;
if (first_opcode == "e8" || first_opcode == "e9") return true;
if (SIZE(inst.words) < 2) return false;
if (first_opcode != "0f") return false;
string second_opcode = inst.words.at(1).data;
return starts_with(second_opcode, "8");
}
string data_to_string(const line& inst) {
ostringstream out;
for (int i = 0; i < SIZE(inst.words); ++i) {