diff --git a/тесты/kvs_full_test.csv b/тесты/kvs_full_test.csv index 85c1f13..aeedab1 100644 --- a/тесты/kvs_full_test.csv +++ b/тесты/kvs_full_test.csv @@ -21,4 +21,5 @@ 1;тест_адресации_р14;Проверка косвенной адресации через R14 (ASCII код первого символа аргумента) 1;тест_адресации_р15;Проверка косвенной адресации через R15 (ASCII код первого символа аргумента) 1;двоеточие_в_строке;Проверка обработки строк с двоеточием внутри -1;тест_адресации_р12;Проверка косвенной адресации через R12 (ASCII код первого символа аргумента) \ No newline at end of file +1;тест_адресации_р12;Проверка косвенной адресации через R12 (ASCII код первого символа аргумента) +1;вызов_функции;Проверка вызова функций и возврата: сложение 10+20=30 через код возврата \ No newline at end of file diff --git a/тесты/вызов_функции/вызов_функции.py b/тесты/вызов_функции/вызов_функции.py new file mode 100644 index 0000000..386b799 --- /dev/null +++ b/тесты/вызов_функции/вызов_функции.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Тест для проверки вызова функций и возврата +Запускает скомпилированную программу и проверяет код возврата (должен быть 30 = 10+20) +""" + +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 / "вызов_функции.квс" + +def clean(): + """Очищает артефакты сборки""" + files = [ + "вызов_функции.elf", + "вызов_функции.csv", + "вызов_функции.аст", + "вызов_функции.токены", + "вызов_функции.константа", + "вызов_функции_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_call_return() -> bool: + """ + Запускает скомпилированную программу и проверяет код возврата + + Returns: + bool: True если код возврата = 30 (10+20), иначе False + """ + print("DEBUG: Запуск ELF, ожидается код возврата 30", file=sys.stderr) + os.chdir(SCRIPT_DIR) + + elf_path = SCRIPT_DIR / "вызов_функции.elf" + if not elf_path.exists(): + print("❌ ELF файл не найден", file=sys.stderr) + return False + + # Запускаем программу без аргументов + run = subprocess.run( + [str(elf_path)], + capture_output=True, + text=True + ) + + expected_code = 30 # 10 + 20 + + 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: Тест пройден (код {run.returncode})", file=sys.stderr) + return True + +def main(): + """Главная функция теста""" + print("DEBUG: Начало теста вызов_функции", file=sys.stderr) + + # Собираем программу + if not build(): + clean() + sys.exit(1) + + # Запускаем тест + if not test_call_return(): + clean() + sys.exit(1) + + # Очищаем артефакты + clean() + + print("✅ Все тесты пройдены!", file=sys.stderr) + sys.exit(0) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/тесты/вызов_функции/вызов_функции.квс b/тесты/вызов_функции/вызов_функции.квс new file mode 100644 index 0000000..7f637f5 --- /dev/null +++ b/тесты/вызов_функции/вызов_функции.квс @@ -0,0 +1,37 @@ +;./тесты/вызов_функции/вызов_функции.elf +;echo $? # должен быть 30 + +; ============================================================ +; вызов_функции.квс - тест вызова функций и возврата +; ============================================================ + +.текст +.глобал _start + +_start: + ; Вызов функции с двумя аргументами + переместить_имм рдиай, 10 ; первый аргумент = 10 + переместить_имм рсиай, 20 ; второй аргумент = 20 + вызвать сложить_два_числа + + ; Результат в RAX — используем как код возврата + переместить рдиай, раикс ; первый аргумент sys_exit = результат + переместить_имм раикс, 60 ; sys_exit + вызов_системы + +сложить_два_числа: + ; Пролог + втолкнуть рбипи + переместить рбипи, рсипи + + ; Тело функции: сложить аргументы + прибавить рдиай, рсиай ; RDI += RSI + переместить раикс, рдиай ; результат в RAX + + ; Эпилог + переместить рсипи, рбипи + вытолкнуть рбипи + вернуться + +.данные +тестовая_переменная: .байт 0 \ No newline at end of file diff --git a/тесты/черновик/черновик.квс b/тесты/черновик/черновик.квс index 5bf4f44..10d313c 100644 --- a/тесты/черновик/черновик.квс +++ b/тесты/черновик/черновик.квс @@ -1,29 +1,30 @@ -;./тесты/тест_адресации_р11.elf "A" -;echo $? # должен быть 65 - -; ============================================================ -; тест_адресации_r11.квс - тест косвенной адресации через R11 -; ============================================================ - .текст .глобал _start _start: - ; Получаем argv[1] - вытолкнуть рсикс ; argc - вытолкнуть рсиай ; argv[0] - вытолкнуть р12 ; argv[1] в R12 - - ; Загружаем первый байт из argv[1] через R12 - загрузить ал, [р12] - - ; Сохраняем в переменную (не обязательно, но для проверки) - сохранить [байт], ал - - ; Выход с кодом = загруженный байт - переместить_имм раикс, 60 - загрузить рдиай, [байт] + ; Вызов функции с двумя аргументами + переместить_имм рдиай, 10 ; первый аргумент = 10 + переместить_имм рсиай, 20 ; второй аргумент = 20 + вызвать сложить_два_числа + + ; Результат в RAX — используем как код возврата + переместить рдиай, раикс ; первый аргумент sys_exit = результат + переместить_имм раикс, 60 ; sys_exit вызов_системы +сложить_два_числа: + ; Пролог + втолкнуть рбипи + переместить рбипи, рсипи + + ; Тело функции: сложить аргументы + прибавить рдиай, рсиай ; RDI += RSI + переместить раикс, рдиай ; результат в RAX + + ; Эпилог + переместить рсипи, рбипи + вытолкнуть рбипи + вернуться + .данные -байт: .байт 0 \ No newline at end of file +тестовая_переменная: .байт 0 \ No newline at end of file