diff options
Diffstat (limited to 'subx')
-rw-r--r-- | subx/034compute_segment_address.cc | 18 | ||||
-rw-r--r-- | subx/035labels.cc | 6 | ||||
-rw-r--r-- | subx/036global_variables.cc | 44 |
3 files changed, 55 insertions, 13 deletions
diff --git a/subx/034compute_segment_address.cc b/subx/034compute_segment_address.cc index f6513114..b302e4d8 100644 --- a/subx/034compute_segment_address.cc +++ b/subx/034compute_segment_address.cc @@ -111,17 +111,19 @@ uint32_t size_of(const segment& s) { // Assumes all bitfields are packed. uint32_t num_bytes(const line& inst) { uint32_t sum = 0; - for (int i = 0; i < SIZE(inst.words); ++i) { - const word& curr = inst.words.at(i); - if (has_operand_metadata(curr, "disp32") || has_operand_metadata(curr, "imm32")) // only multi-byte operands - sum += 4; - // End num_bytes(curr) Special-cases - else - sum++; - } + for (int i = 0; i < SIZE(inst.words); ++i) + sum += size_of(inst.words.at(i)); return sum; } +int size_of(const word& w) { + if (has_operand_metadata(w, "disp32") || has_operand_metadata(w, "imm32")) + return 4; + // End size_of(word w) Special-cases + else + return 1; +} + //: Dependencies: //: - We'd like to compute segment addresses before setting up global variables, //: because computing addresses for global variables requires knowing where diff --git a/subx/035labels.cc b/subx/035labels.cc index 30a6082e..e07cede8 100644 --- a/subx/035labels.cc +++ b/subx/035labels.cc @@ -265,6 +265,6 @@ bar: 00 +transform: segment 1 begins at address 0x0a000079 -:(before "End num_bytes(curr) Special-cases") -else if (is_label(curr)) - ; // don't count it +:(before "End size_of(word w) Special-cases") +else if (is_label(w)) + return 0; diff --git a/subx/036global_variables.cc b/subx/036global_variables.cc index f1fdd963..afeb7427 100644 --- a/subx/036global_variables.cc +++ b/subx/036global_variables.cc @@ -38,7 +38,7 @@ void compute_addresses_for_global_variables(const segment& s, map<string, uint32 for (int j = 0; j < SIZE(inst.words); ++j) { const word& curr = inst.words.at(j); if (*curr.data.rbegin() != ':') { - ++current_address; + current_address += size_of(curr); } else { string variable = drop_last(curr.data); @@ -64,7 +64,12 @@ void drop_global_variables(program& p) { void replace_global_variables_with_addresses(program& p, const map<string, uint32_t>& address) { if (p.segments.empty()) return; - segment& code = p.segments.at(0); + replace_global_variables_in_code_segment(p.segments.at(0), address); + for (int i = /*skip code*/1; i < SIZE(p.segments); ++i) + replace_global_variables_in_data_segment(p.segments.at(i), address); +} + +void replace_global_variables_in_code_segment(segment& code, const map<string, uint32_t>& address) { for (int i = 0; i < SIZE(code.lines); ++i) { line& inst = code.lines.at(i); line new_inst; @@ -87,6 +92,26 @@ void replace_global_variables_with_addresses(program& p, const map<string, uint3 } } +void replace_global_variables_in_data_segment(segment& data, const map<string, uint32_t>& address) { + for (int i = 0; i < SIZE(data.lines); ++i) { + line& l = data.lines.at(i); + line new_l; + for (int j = 0; j < SIZE(l.words); ++j) { + const word& curr = l.words.at(j); + if (!contains_key(address, curr.data)) { + if (!looks_like_hex_int(curr.data)) + raise << "missing reference to global '" << curr.data << "'\n" << end(); + new_l.words.push_back(curr); + continue; + } + trace(99, "transform") << curr.data << " maps to " << HEXWORD << get(address, curr.data) << end(); + emit_hex_bytes(new_l, get(address, curr.data), 4); + } + l.words.swap(new_l.words); + trace(99, "transform") << "after transform: '" << data_to_string(l) << "'" << end(); + } +} + bool valid_use_of_global_variable(const word& curr) { if (has_operand_metadata(curr, "imm32")) return true; // End Valid Uses Of Global Variable(curr) @@ -148,6 +173,21 @@ x: # sub-optimal error message; should be #? +error: can't call to the data segment ('x') +:(scenario global_variable_in_data_segment) +== 0x1 +b9 x/imm32 +== 0x0a000000 +x: + y/imm32 +y: + 00 00 00 00 +# check that we loaded 'x' with the address of 'y' ++load: 0x0a000000 -> 04 ++load: 0x0a000001 -> 00 ++load: 0x0a000002 -> 00 ++load: 0x0a000003 -> 0a +$error: 0 + :(scenario disp32_data_with_modrm) == code 8b/copy 0/mod/indirect 5/rm32/.disp32 2/r32/EDX x/disp32 |