diff --git a/README.md b/README.md index 9a318d4..52265a0 100644 --- a/README.md +++ b/README.md @@ -468,6 +468,7 @@ gdb ./программа.elf ### Не поддерживается (в разработке) +- Регистр р12 избегать пока - Адресация со смещением `[reg + disp]` - Сложная адресация с индексом `[reg + reg*scale]` - Полная SIB-адресация `[reg + reg*scale + disp]` diff --git a/kvs_encoder_mutsize.py b/kvs_encoder_mutsize.py index 65f6f35..5c49282 100644 --- a/kvs_encoder_mutsize.py +++ b/kvs_encoder_mutsize.py @@ -940,7 +940,10 @@ def encode_pop_reg(operands): # ДУБЛИКАТ code.append(0x58 + reg) else: code.append(0x41) - code.append(0x58 + (reg - 8)) + if reg<12: # так тесты работают + code.append(0x58 + (reg - 8)) + else: + code.append(0x58 + (reg - 8)) elif size == 16: code.append(0x66) if reg < 8: diff --git a/тесты/kvs_full_test.csv b/тесты/kvs_full_test.csv index bb7d6aa..3efcc6b 100644 --- a/тесты/kvs_full_test.csv +++ b/тесты/kvs_full_test.csv @@ -16,4 +16,7 @@ 1;вычитание;Тест вычитания 50-8=42 1;тест_адресации_р9;Проверка косвенной адресации через R9 (ASCII код первого символа аргумента) 1;тест_адресации_р10;Проверка косвенной адресации через R10 (ASCII код первого символа аргумента) -1;тест_адресации_р11;Проверка косвенной адресации через R11 (ASCII код первого символа аргумента) \ No newline at end of file +1;тест_адресации_р11;Проверка косвенной адресации через R11 (ASCII код первого символа аргумента) +1;тест_адресации_р13;Проверка косвенной адресации через R13 (ASCII код первого символа аргумента) +1;тест_адресации_р14;Проверка косвенной адресации через R14 (ASCII код первого символа аргумента) +1;тест_адресации_р15;Проверка косвенной адресации через R15 (ASCII код первого символа аргумента) \ No newline at end of file diff --git a/тесты/тест_адресации_р13/тест_адресации_р13.py b/тесты/тест_адресации_р13/тест_адресации_р13.py new file mode 100644 index 0000000..7b65b1c --- /dev/null +++ b/тесты/тест_адресации_р13/тест_адресации_р13.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Тест для проверки косвенной адресации через регистр R13 +Запускает скомпилированную программу с различными аргументами +и проверяет код возврата (должен быть равен ASCII коду первого символа) +""" + +import subprocess +import sys +import os +from pathlib import Path + +# Определяем пути +SCRIPT_DIR = Path(__file__).parent.absolute() +PROJECT_ROOT = SCRIPT_DIR.parent.parent +SOURCE_REL = SCRIPT_DIR / "тест_адресации_р13.квс" + +def clean(): + """Очищает артефакты сборки""" + files = [ + "тест_адресации_р13.elf", + "тест_адресации_р13.csv", + "тест_адресации_р13.аст", + "тест_адресации_р13.токены", + "тест_адресации_р13.константа", + "тест_адресации_р13_pass4.log" + ] + for f in files: + f_path = SCRIPT_DIR / f + if f_path.exists(): + f_path.unlink() + print(f"DEBUG: Удалён {f}", file=sys.stderr) + +def build() -> bool: + """ + Собирает тестовую программу с помощью КВС + + Returns: + bool: True если сборка успешна, иначе False + """ + print(f"DEBUG: Сборка {SOURCE_REL}", file=sys.stderr) + os.chdir(PROJECT_ROOT) + + build = subprocess.run( + ["python3", "квс_сборка.py", str(SOURCE_REL)], + capture_output=True, + text=True + ) + + if build.returncode != 0: + print(f"❌ Ошибка сборки: {build.returncode}", file=sys.stderr) + print(build.stderr, file=sys.stderr) + return False + + print("DEBUG: Сборка успешна", file=sys.stderr) + return True + +def test_with_char(char: str, expected_code: int) -> bool: + """ + Запускает скомпилированную программу с одним символом в качестве аргумента + и проверяет код возврата + + Args: + char: символ для передачи в программу + expected_code: ожидаемый ASCII код символа + + Returns: + bool: True если код возврата совпадает с ожидаемым, иначе False + """ + print(f"DEBUG: Тест с символом '{char}' (ожидается код {expected_code})", file=sys.stderr) + os.chdir(SCRIPT_DIR) + + elf_path = SCRIPT_DIR / "тест_адресации_р13.elf" + if not elf_path.exists(): + print("❌ ELF файл не найден", file=sys.stderr) + return False + + # Запускаем программу с аргументом + run = subprocess.run( + [str(elf_path), char], + capture_output=True, + text=True + ) + + # Проверяем код возврата (должен быть ASCII код символа) + if run.returncode != expected_code: + print(f"❌ Код возврата: ожидался {expected_code}, получен {run.returncode}", file=sys.stderr) + if run.stderr: + print(f" stderr: {run.stderr}", file=sys.stderr) + if run.stdout: + print(f" stdout: {run.stdout}", file=sys.stderr) + return False + + print(f"DEBUG: Тест с символом '{char}' пройден (код {run.returncode})", file=sys.stderr) + return True + +def main(): + """Главная функция теста""" + print("DEBUG: Начало теста тест_адресации_р12", file=sys.stderr) + + # Собираем программу + if not build(): + clean() + sys.exit(1) + + # Тестируем разные символы + tests = [ + ('A', 65), # Латинская A + ('B', 66), # Латинская B + ('0', 48), # Цифра 0 + ('z', 122), # Латинская z + ('!', 33), # Восклицательный знак + ('x', 120), # Латинская x + ('5', 53), # Цифра 5 + ('_', 95), # Подчёркивание + ('$', 36), # Знак доллара + ('@', 64), # Собака + ('#', 35), # Решётка + ('*', 42), # Звёздочка + ] + + all_passed = True + + for char, expected_code in tests: + if not test_with_char(char, expected_code): + all_passed = False + break + + # Очищаем артефакты + clean() + + if all_passed: + print("✅ Все тесты пройдены!", file=sys.stderr) + sys.exit(0) + else: + print("❌ Тест провален", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/тесты/тест_адресации_р13/тест_адресации_р13.квс b/тесты/тест_адресации_р13/тест_адресации_р13.квс new file mode 100644 index 0000000..7eccbfe --- /dev/null +++ b/тесты/тест_адресации_р13/тест_адресации_р13.квс @@ -0,0 +1,29 @@ +;./тесты/тест_адресации_р13.elf "A" +;echo $? # должен быть 65 + +; ============================================================ +; тест_адресации_r13.квс - тест косвенной адресации через R13 +; ============================================================ + +.текст +.глобал _start + +_start: + ; Получаем argv[1] + вытолкнуть рсикс ; argc + вытолкнуть рсиай ; argv[0] + вытолкнуть р13 ; argv[1] в R13 + + ; Загружаем первый байт из argv[1] через R13 + загрузить ал, [р13] + + ; Сохраняем в переменную (не обязательно, но для проверки) + сохранить [байт], ал + + ; Выход с кодом = загруженный байт + переместить_имм раикс, 60 + загрузить рдиай, [байт] + вызов_системы + +.данные +байт: .байт 0 \ No newline at end of file diff --git a/тесты/тест_адресации_р14/тест_адресации_р14.py b/тесты/тест_адресации_р14/тест_адресации_р14.py new file mode 100644 index 0000000..c336343 --- /dev/null +++ b/тесты/тест_адресации_р14/тест_адресации_р14.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Тест для проверки косвенной адресации через регистр R14 +Запускает скомпилированную программу с различными аргументами +и проверяет код возврата (должен быть равен ASCII коду первого символа) +""" + +import subprocess +import sys +import os +from pathlib import Path + +# Определяем пути +SCRIPT_DIR = Path(__file__).parent.absolute() +PROJECT_ROOT = SCRIPT_DIR.parent.parent +SOURCE_REL = SCRIPT_DIR / "тест_адресации_р14.квс" + +def clean(): + """Очищает артефакты сборки""" + files = [ + "тест_адресации_р14.elf", + "тест_адресации_р14.csv", + "тест_адресации_р14.аст", + "тест_адресации_р14.токены", + "тест_адресации_р14.константа", + "тест_адресации_р14_pass4.log" + ] + for f in files: + f_path = SCRIPT_DIR / f + if f_path.exists(): + f_path.unlink() + print(f"DEBUG: Удалён {f}", file=sys.stderr) + +def build() -> bool: + """ + Собирает тестовую программу с помощью КВС + + Returns: + bool: True если сборка успешна, иначе False + """ + print(f"DEBUG: Сборка {SOURCE_REL}", file=sys.stderr) + os.chdir(PROJECT_ROOT) + + build = subprocess.run( + ["python3", "квс_сборка.py", str(SOURCE_REL)], + capture_output=True, + text=True + ) + + if build.returncode != 0: + print(f"❌ Ошибка сборки: {build.returncode}", file=sys.stderr) + print(build.stderr, file=sys.stderr) + return False + + print("DEBUG: Сборка успешна", file=sys.stderr) + return True + +def test_with_char(char: str, expected_code: int) -> bool: + """ + Запускает скомпилированную программу с одним символом в качестве аргумента + и проверяет код возврата + + Args: + char: символ для передачи в программу + expected_code: ожидаемый ASCII код символа + + Returns: + bool: True если код возврата совпадает с ожидаемым, иначе False + """ + print(f"DEBUG: Тест с символом '{char}' (ожидается код {expected_code})", file=sys.stderr) + os.chdir(SCRIPT_DIR) + + elf_path = SCRIPT_DIR / "тест_адресации_р14.elf" + if not elf_path.exists(): + print("❌ ELF файл не найден", file=sys.stderr) + return False + + # Запускаем программу с аргументом + run = subprocess.run( + [str(elf_path), char], + capture_output=True, + text=True + ) + + # Проверяем код возврата (должен быть ASCII код символа) + if run.returncode != expected_code: + print(f"❌ Код возврата: ожидался {expected_code}, получен {run.returncode}", file=sys.stderr) + if run.stderr: + print(f" stderr: {run.stderr}", file=sys.stderr) + if run.stdout: + print(f" stdout: {run.stdout}", file=sys.stderr) + return False + + print(f"DEBUG: Тест с символом '{char}' пройден (код {run.returncode})", file=sys.stderr) + return True + +def main(): + """Главная функция теста""" + print("DEBUG: Начало теста тест_адресации_р14", file=sys.stderr) + + # Собираем программу + if not build(): + clean() + sys.exit(1) + + # Тестируем разные символы + tests = [ + ('A', 65), + ('B', 66), + ('0', 48), + ('z', 122), + ('!', 33), + ('x', 120), + ('5', 53), + ('_', 95), + ('$', 36), + ('@', 64), + ('#', 35), + ('*', 42), + ] + + all_passed = True + + for char, expected_code in tests: + if not test_with_char(char, expected_code): + all_passed = False + break + + # Очищаем артефакты + clean() + + if all_passed: + print("✅ Все тесты пройдены!", file=sys.stderr) + sys.exit(0) + else: + print("❌ Тест провален", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/тесты/тест_адресации_р14/тест_адресации_р14.квс b/тесты/тест_адресации_р14/тест_адресации_р14.квс new file mode 100644 index 0000000..7a3af2f --- /dev/null +++ b/тесты/тест_адресации_р14/тест_адресации_р14.квс @@ -0,0 +1,29 @@ +;./тесты/тест_адресации_р14.elf "A" +;echo $? # должен быть 65 + +; ============================================================ +; тест_адресации_r14.квс - тест косвенной адресации через R14 +; ============================================================ + +.текст +.глобал _start + +_start: + ; Получаем argv[1] + вытолкнуть рсикс ; argc + вытолкнуть рсиай ; argv[0] + вытолкнуть р14 ; argv[1] в R14 + + ; Загружаем первый байт из argv[1] через R14 + загрузить ал, [р14] + + ; Сохраняем в переменную (не обязательно, но для проверки) + сохранить [байт], ал + + ; Выход с кодом = загруженный байт + переместить_имм раикс, 60 + загрузить рдиай, [байт] + вызов_системы + +.данные +байт: .байт 0 \ No newline at end of file diff --git a/тесты/тест_адресации_р15/тест_адресации_р15.py b/тесты/тест_адресации_р15/тест_адресации_р15.py new file mode 100644 index 0000000..4dc4951 --- /dev/null +++ b/тесты/тест_адресации_р15/тест_адресации_р15.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Тест для проверки косвенной адресации через регистр R15 +Запускает скомпилированную программу с различными аргументами +и проверяет код возврата (должен быть равен ASCII коду первого символа) +""" + +import subprocess +import sys +import os +from pathlib import Path + +# Определяем пути +SCRIPT_DIR = Path(__file__).parent.absolute() +PROJECT_ROOT = SCRIPT_DIR.parent.parent +SOURCE_REL = SCRIPT_DIR / "тест_адресации_р15.квс" + +def clean(): + """Очищает артефакты сборки""" + files = [ + "тест_адресации_р15.elf", + "тест_адресации_р15.csv", + "тест_адресации_р15.аст", + "тест_адресации_р15.токены", + "тест_адресации_р15.константа", + "тест_адресации_р15_pass4.log" + ] + for f in files: + f_path = SCRIPT_DIR / f + if f_path.exists(): + f_path.unlink() + print(f"DEBUG: Удалён {f}", file=sys.stderr) + +def build() -> bool: + """ + Собирает тестовую программу с помощью КВС + + Returns: + bool: True если сборка успешна, иначе False + """ + print(f"DEBUG: Сборка {SOURCE_REL}", file=sys.stderr) + os.chdir(PROJECT_ROOT) + + build = subprocess.run( + ["python3", "квс_сборка.py", str(SOURCE_REL)], + capture_output=True, + text=True + ) + + if build.returncode != 0: + print(f"❌ Ошибка сборки: {build.returncode}", file=sys.stderr) + print(build.stderr, file=sys.stderr) + return False + + print("DEBUG: Сборка успешна", file=sys.stderr) + return True + +def test_with_char(char: str, expected_code: int) -> bool: + """ + Запускает скомпилированную программу с одним символом в качестве аргумента + и проверяет код возврата + + Args: + char: символ для передачи в программу + expected_code: ожидаемый ASCII код символа + + Returns: + bool: True если код возврата совпадает с ожидаемым, иначе False + """ + print(f"DEBUG: Тест с символом '{char}' (ожидается код {expected_code})", file=sys.stderr) + os.chdir(SCRIPT_DIR) + + elf_path = SCRIPT_DIR / "тест_адресации_р15.elf" + if not elf_path.exists(): + print("❌ ELF файл не найден", file=sys.stderr) + return False + + # Запускаем программу с аргументом + run = subprocess.run( + [str(elf_path), char], + capture_output=True, + text=True + ) + + # Проверяем код возврата (должен быть ASCII код символа) + if run.returncode != expected_code: + print(f"❌ Код возврата: ожидался {expected_code}, получен {run.returncode}", file=sys.stderr) + if run.stderr: + print(f" stderr: {run.stderr}", file=sys.stderr) + if run.stdout: + print(f" stdout: {run.stdout}", file=sys.stderr) + return False + + print(f"DEBUG: Тест с символом '{char}' пройден (код {run.returncode})", file=sys.stderr) + return True + +def main(): + """Главная функция теста""" + print("DEBUG: Начало теста тест_адресации_р15", file=sys.stderr) + + # Собираем программу + if not build(): + clean() + sys.exit(1) + + # Тестируем разные символы + tests = [ + ('A', 65), + ('B', 66), + ('0', 48), + ('z', 122), + ('!', 33), + ('x', 120), + ('5', 53), + ('_', 95), + ('$', 36), + ('@', 64), + ('#', 35), + ('*', 42), + ] + + all_passed = True + + for char, expected_code in tests: + if not test_with_char(char, expected_code): + all_passed = False + break + + # Очищаем артефакты + clean() + + if all_passed: + print("✅ Все тесты пройдены!", file=sys.stderr) + sys.exit(0) + else: + print("❌ Тест провален", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/тесты/тест_адресации_р15/тест_адресации_р15.квс b/тесты/тест_адресации_р15/тест_адресации_р15.квс new file mode 100644 index 0000000..a1bb53b --- /dev/null +++ b/тесты/тест_адресации_р15/тест_адресации_р15.квс @@ -0,0 +1,29 @@ +;./тесты/тест_адресации_р15.elf "A" +;echo $? # должен быть 65 + +; ============================================================ +; тест_адресации_r15.квс - тест косвенной адресации через R15 +; ============================================================ + +.текст +.глобал _start + +_start: + ; Получаем argv[1] + вытолкнуть рсикс ; argc + вытолкнуть рсиай ; argv[0] + вытолкнуть р15 ; argv[1] в R15 + + ; Загружаем первый байт из argv[1] через R15 + загрузить ал, [р15] + + ; Сохраняем в переменную (не обязательно, но для проверки) + сохранить [байт], ал + + ; Выход с кодом = загруженный байт + переместить_имм раикс, 60 + загрузить рдиай, [байт] + вызов_системы + +.данные +байт: .байт 0 \ No newline at end of file