diff --git a/kvs_build.py b/kvs_build.py index 5838b1b..27668d7 100644 --- a/kvs_build.py +++ b/kvs_build.py @@ -34,6 +34,7 @@ if __name__ == "__main__": ("kvs_pass3.py", [ast_file, csv_file], "3 проход"), ("kvs_pass4.py", [csv_file], "4 проход"), ("kvs_pass5.py", [csv_file], "5 проход"), + ("kvs_pass6.py", [csv_file], "6 проход"), ("kvs_builder.py", [csv_file, elf_file], "Сборка ELF"), ] diff --git a/kvs_pass6.py b/kvs_pass6.py new file mode 100644 index 0000000..d4649e7 --- /dev/null +++ b/kvs_pass6.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Шестой проход КВС — сортировка CSV по адресам +- Сортирует все записи по числовому значению адреса +- Записи с адресом "BSS" помещает в конец (после всех реальных адресов) +- Обеспечивает правильный порядок байтов в итоговом ELF-файле +""" + +import sys +import csv + + +def get_addr_value(addr_str): + """ + Преобразует адрес в число для сортировки + BSS и пустые адреса отправляются в конец (большое число) + """ + if not addr_str or addr_str == '': + return 999999999 # Пустые адреса в конец + if addr_str == 'BSS': + return 999999999 # BSS в самый конец (после всех реальных адресов) + if addr_str.startswith('0x'): + try: + return int(addr_str, 16) + except ValueError: + return 999999999 + return 999999999 + + +def sort_csv_by_address(input_csv, output_csv): + """ + Сортирует CSV по адресам (числовым значениям) + BSS и пустые адреса помещаются в конец + + Args: + input_csv: входной CSV файл + output_csv: выходной CSV файл + """ + + print(f"\n=== ШЕСТОЙ ПРОХОД КВС: сортировка CSV ===") + print(f"Чтение: {input_csv}") + + # Читаем CSV + with open(input_csv, 'r', encoding='utf-8') as f: + reader = csv.DictReader(f, delimiter=';') + fieldnames = reader.fieldnames + rows = list(reader) + + print(f"Найдено записей: {len(rows)}") + + # Подсчёт статистики до сортировки + bss_count = sum(1 for row in rows if row.get('адрес') == 'BSS') + empty_count = sum(1 for row in rows if not row.get('адрес') or row.get('адрес') == '') + normal_count = len(rows) - bss_count - empty_count + + print(f" Обычных записей (с числовыми адресами): {normal_count}") + print(f" BSS-записей: {bss_count}") + print(f" Пустых адресов: {empty_count}") + + # Сортировка + def sort_key(row): + addr = row.get('адрес', '') + value = get_addr_value(addr) + return (value, 0) + + rows.sort(key=sort_key) + + # Записываем отсортированный CSV + with open(output_csv, 'w', newline='', encoding='utf-8') as f: + writer = csv.DictWriter(f, fieldnames=fieldnames, delimiter=';', restval='') + writer.writeheader() + writer.writerows(rows) + + print(f"\n✅ CSV отсортирован и сохранён: {output_csv}") + + # Показываем первые 10 адресов для проверки + print("\n📊 Первые 10 адресов после сортировки:") + for i, row in enumerate(rows[:10]): + addr = row.get('адрес', '') + seg = row.get('сегмент', '') + source = row.get('исходная_команда', '')[:30] + print(f" {i+1:2d}. {addr:12s} [{seg:10s}] {source}") + + # Показываем последние 5 адресов (должны быть BSS) + if bss_count > 0: + print("\n📊 Последние 5 записей (BSS в конце):") + for i, row in enumerate(rows[-5:]): + addr = row.get('адрес', '') + seg = row.get('сегмент', '') + source = row.get('исходная_команда', '')[:30] + print(f" {len(rows)-5+i+1:2d}. {addr:12s} [{seg:10s}] {source}") + + # Проверка: убеждаемся, что после сортировки нет числовых адресов после BSS + found_bss = False + for row in rows: + addr = row.get('адрес', '') + if addr == 'BSS': + found_bss = True + elif found_bss and addr and addr != '' and addr.startswith('0x'): + print(f"\n⚠️ ВНИМАНИЕ: Найден числовой адрес {addr} после BSS!") + print(" Это может указывать на проблему в данных.") + break + else: + if found_bss: + print("\n✅ Проверка пройдена: все BSS-записи в конце, числовых адресов после них нет.") + else: + print("\n✅ BSS-записей не найдено.") + + +def main(): + if len(sys.argv) not in (2, 3): + print("Использование: python kvs_pass6.py <входной.csv> [выходной.csv]") + print(" Если выходной не указан, перезаписывается входной файл") + sys.exit(1) + + input_csv = sys.argv[1] + + # Определяем выходной файл + if len(sys.argv) >= 3: + output_csv = sys.argv[2] + else: + # По умолчанию: перезаписываем исходный файл + output_csv = input_csv + + sort_csv_by_address(input_csv, output_csv) + + +if __name__ == "__main__": + main() \ No newline at end of file