ремонт регистров р9 - р11
This commit is contained in:
parent
50d9a5b7be
commit
ce1800f236
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
|||
__pycache__/
|
||||
.gigacode
|
||||
*.pyc
|
||||
*.pyo
|
||||
|
|
@ -186,44 +186,92 @@ def encode_mov_mem_reg_absolute(reg_info, mem_info, current_pos, vaddr_text):
|
|||
return code
|
||||
|
||||
|
||||
def encode_mov_reg_mem_indirect(reg_info, base_reg):
|
||||
def encode_mov_reg_mem_indirect(reg_info: dict, base_reg: str) -> bytearray:
|
||||
"""
|
||||
Кодирует MOV reg, [base_reg] — косвенная адресация.
|
||||
Пример: mov rax, [rbx] → 48 8B 03
|
||||
|
||||
Аргументы:
|
||||
- reg_info: словарь от get_reg_info() с ключами 'index' (int) и 'size' (int)
|
||||
- base_reg: строка с именем регистра, например 'рбикс'
|
||||
|
||||
REGISTERS[base_reg] возвращает число-индекс (int), НЕ словарь.
|
||||
Кодирует MOV reg, [base_reg] — косвенная адресация через регистр.
|
||||
"""
|
||||
code = bytearray()
|
||||
reg = reg_info['index']
|
||||
base = REGISTERS[base_reg] # REGISTERS возвращает int (индекс регистра)
|
||||
|
||||
rex = 0x48 if reg_info['size'] == 64 else 0x40
|
||||
if reg >= 8:
|
||||
rex |= 0x04 # REX.R
|
||||
if base >= 8:
|
||||
rex |= 0x01 # REX.B
|
||||
code.append(rex)
|
||||
code.append(0x8B) # MOV r64, r/m64
|
||||
# === 1. Получаем индексы регистров ===
|
||||
reg_index = reg_info['index']
|
||||
reg_size = reg_info['size']
|
||||
|
||||
# Особый случай: [rbp] или [r13] требует disp8=0 при mod=00
|
||||
# (mod=00 с r/m=101 означает RIP-relative, а не [rbp])
|
||||
if (base & 7) == 5:
|
||||
# mod=01 (disp8), reg, r/m=5
|
||||
modrm = 0x40 | ((reg & 7) << 3) | 5
|
||||
code.append(modrm)
|
||||
code.append(0x00) # disp8 = 0
|
||||
if base_reg not in REGISTERS:
|
||||
raise ValueError(f"Неизвестный базовый регистр: {base_reg}")
|
||||
base_index = REGISTERS[base_reg]
|
||||
|
||||
# === 2. Выбираем opcode и префиксы ===
|
||||
#
|
||||
# В x86-64 для MOV существуют разные opcodes:
|
||||
# - 8A /r — MOV r8, r/m8 (только 8-бит!)
|
||||
# - 8B /r — MOV r16/r32/r64, r/m16/r/m32/r/m64
|
||||
#
|
||||
# Для 16-бит нужен префикс 0x66
|
||||
# Для 64-бит нужен REX.W (бит 3 в REX)
|
||||
#
|
||||
if reg_size == 8:
|
||||
opcode = 0x8A # MOV r8, r/m8
|
||||
rex_base = 0x40 # Без REX.W
|
||||
need_prefix_66 = False
|
||||
elif reg_size == 16:
|
||||
opcode = 0x8B # MOV r16, r/m16
|
||||
rex_base = 0x40 # Без REX.W
|
||||
need_prefix_66 = True # ← ВАЖНО: префикс 0x66 для 16-бит!
|
||||
elif reg_size == 32:
|
||||
opcode = 0x8B # MOV r32, r/m32
|
||||
rex_base = 0x40 # Без REX.W
|
||||
need_prefix_66 = False
|
||||
elif reg_size == 64:
|
||||
opcode = 0x8B # MOV r64, r/m64
|
||||
rex_base = 0x48 # С REX.W (бит 3 = 1)
|
||||
need_prefix_66 = False
|
||||
else:
|
||||
# mod=00, reg, r/m=base
|
||||
modrm = ((reg & 7) << 3) | (base & 7)
|
||||
code.append(modrm)
|
||||
raise ValueError(f"Неподдерживаемый размер регистра: {reg_size} бит")
|
||||
|
||||
# === 3. Формируем REX-префикс ===
|
||||
rex = rex_base
|
||||
|
||||
# REX.R: для регистра-источника (reg) — нужен если индекс >= 8
|
||||
if reg_index >= 8:
|
||||
rex |= 0x04 # REX.R = 1
|
||||
|
||||
# REX.B: для базового регистра (base) — нужен если индекс >= 8
|
||||
if base_index >= 8:
|
||||
rex |= 0x01 # REX.B = 1
|
||||
|
||||
# === 4. Формируем ModR/M байт ===
|
||||
if (base_index & 7) == 5:
|
||||
# [rbp] или [r13] требуют disp8=0
|
||||
modrm = 0x40 | ((reg_index & 7) << 3) | 5
|
||||
modrm_byte = modrm
|
||||
disp8 = 0x00
|
||||
else:
|
||||
modrm = ((reg_index & 7) << 3) | (base_index & 7)
|
||||
modrm_byte = modrm
|
||||
disp8 = None
|
||||
|
||||
# === 5. Собираем инструкцию ===
|
||||
|
||||
# 5a. Префикс 0x66 для 16-битных операндов (ДО REX!)
|
||||
if need_prefix_66:
|
||||
code.append(0x66)
|
||||
|
||||
# 5b. REX-префикс (если не равен 0x40)
|
||||
if rex != 0x40:
|
||||
code.append(rex)
|
||||
|
||||
# 5c. Opcode
|
||||
code.append(opcode)
|
||||
|
||||
# 5d. ModR/M байт
|
||||
code.append(modrm_byte)
|
||||
|
||||
# 5e. Disp8 (если есть)
|
||||
if disp8 is not None:
|
||||
code.append(disp8)
|
||||
|
||||
return code
|
||||
|
||||
|
||||
def encode_mov_mem_reg_indirect(base_reg, reg_info):
|
||||
"""
|
||||
Кодирует MOV [base_reg], reg — косвенная адресация.
|
||||
|
|
|
|||
|
|
@ -14,3 +14,6 @@
|
|||
1;сложение;Тест сложения 40+2=42 (проверка через код возврата)
|
||||
0;сложение+;Тест сложения 40+2=42 (проверка через код возврата+)
|
||||
1;вычитание;Тест вычитания 50-8=42
|
||||
1;тест_адресации_р9;Проверка косвенной адресации через R9 (ASCII код первого символа аргумента)
|
||||
1;тест_адресации_р10;Проверка косвенной адресации через R10 (ASCII код первого символа аргумента)
|
||||
1;тест_адресации_р11;Проверка косвенной адресации через R11 (ASCII код первого символа аргумента)
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 46.
|
|
|
@ -5,7 +5,7 @@ import csv
|
|||
from pathlib import Path
|
||||
|
||||
def main():
|
||||
# Диспетчер лежит в тесты/kvs_full_test.py
|
||||
# Диспетчер лежит в тесты/прогон_тестов.py
|
||||
# Значит, корень с табличкой — та же папка (тесты/)
|
||||
tests_dir = Path(__file__).parent
|
||||
csv_file = tests_dir / "kvs_full_test.csv"
|
||||
|
|
|
|||
140
тесты/тест_адресации_р10/тест_адресации_р10.py
Normal file
140
тесты/тест_адресации_р10/тест_адресации_р10.py
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Тест для проверки косвенной адресации через регистр R10
|
||||
Запускает скомпилированную программу с различными аргументами
|
||||
и проверяет код возврата (должен быть равен 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 / "тест_адресации_р10.квс"
|
||||
|
||||
def clean():
|
||||
"""Очищает артефакты сборки"""
|
||||
files = [
|
||||
"тест_адресации_р10.elf",
|
||||
"тест_адресации_р10.csv",
|
||||
"тест_адресации_р10.аст",
|
||||
"тест_адресации_р10.токены",
|
||||
"тест_адресации_р10.константа",
|
||||
"тест_адресации_р10_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 / "тест_адресации_р10.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: Начало теста тест_адресации_р10", 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), # Собака
|
||||
]
|
||||
|
||||
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()
|
||||
29
тесты/тест_адресации_р10/тест_адресации_р10.квс
Normal file
29
тесты/тест_адресации_р10/тест_адресации_р10.квс
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
;./тесты/тест_адресации_р10.elf "A"
|
||||
;echo $? # должен быть 65
|
||||
|
||||
; ============================================================
|
||||
; тест_адресации_r10.квс - тест косвенной адресации через R10
|
||||
; ============================================================
|
||||
|
||||
.текст
|
||||
.глобал _start
|
||||
|
||||
_start:
|
||||
; Получаем argv[1]
|
||||
вытолкнуть рсикс ; argc
|
||||
вытолкнуть рсиай ; argv[0]
|
||||
вытолкнуть р10 ; argv[1] в R10
|
||||
|
||||
; Загружаем первый байт из argv[1] через R10
|
||||
загрузить ал, [р10]
|
||||
|
||||
; Сохраняем в переменную (не обязательно, но для проверки)
|
||||
сохранить [байт], ал
|
||||
|
||||
; Выход с кодом = загруженный байт
|
||||
переместить_имм раикс, 60
|
||||
загрузить рдиай, [байт]
|
||||
вызов_системы
|
||||
|
||||
.данные
|
||||
байт: .байт 0
|
||||
142
тесты/тест_адресации_р11/тест_адресации_р11.py
Normal file
142
тесты/тест_адресации_р11/тест_адресации_р11.py
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Тест для проверки косвенной адресации через регистр R11
|
||||
Запускает скомпилированную программу с различными аргументами
|
||||
и проверяет код возврата (должен быть равен 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 / "тест_адресации_р11.квс"
|
||||
|
||||
def clean():
|
||||
"""Очищает артефакты сборки"""
|
||||
files = [
|
||||
"тест_адресации_р11.elf",
|
||||
"тест_адресации_р11.csv",
|
||||
"тест_адресации_р11.аст",
|
||||
"тест_адресации_р11.токены",
|
||||
"тест_адресации_р11.константа",
|
||||
"тест_адресации_р11_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 / "тест_адресации_р11.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: Начало теста тест_адресации_р11", 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()
|
||||
29
тесты/тест_адресации_р11/тест_адресации_р11.квс
Normal file
29
тесты/тест_адресации_р11/тест_адресации_р11.квс
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
;./тесты/тест_адресации_р11.elf "A"
|
||||
;echo $? # должен быть 65
|
||||
|
||||
; ============================================================
|
||||
; тест_адресации_r11.квс - тест косвенной адресации через R11
|
||||
; ============================================================
|
||||
|
||||
.текст
|
||||
.глобал _start
|
||||
|
||||
_start:
|
||||
; Получаем argv[1]
|
||||
вытолкнуть рсикс ; argc
|
||||
вытолкнуть рсиай ; argv[0]
|
||||
вытолкнуть р11 ; argv[1] в R11
|
||||
|
||||
; Загружаем первый байт из argv[1] через R11
|
||||
загрузить ал, [р11]
|
||||
|
||||
; Сохраняем в переменную (не обязательно, но для проверки)
|
||||
сохранить [байт], ал
|
||||
|
||||
; Выход с кодом = загруженный байт
|
||||
переместить_имм раикс, 60
|
||||
загрузить рдиай, [байт]
|
||||
вызов_системы
|
||||
|
||||
.данные
|
||||
байт: .байт 0
|
||||
138
тесты/тест_адресации_р9/тест_адресации_р9.py
Normal file
138
тесты/тест_адресации_р9/тест_адресации_р9.py
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Тест для проверки косвенной адресации через регистр R9
|
||||
Запускает скомпилированную программу с различными аргументами
|
||||
и проверяет код возврата (должен быть равен 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 / "тест_адресации_р9.квс"
|
||||
|
||||
def clean():
|
||||
"""Очищает артефакты сборки"""
|
||||
files = [
|
||||
"тест_адресации_р9.elf",
|
||||
"тест_адресации_р9.csv",
|
||||
"тест_адресации_р9.аст",
|
||||
"тест_адресации_р9.токены",
|
||||
"тест_адресации_р9.константа",
|
||||
"тест_адресации_р9_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 / "тест_адресации_р9.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: Начало теста тест_адресации_р9", 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), # Подчёркивание
|
||||
]
|
||||
|
||||
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()
|
||||
29
тесты/тест_адресации_р9/тест_адресации_р9.квс
Normal file
29
тесты/тест_адресации_р9/тест_адресации_р9.квс
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
;./тесты/тест_адресации_р9.elf "A"
|
||||
;echo $? # должен быть 65
|
||||
|
||||
; ============================================================
|
||||
; тест_адресации_r9.квс - тест косвенной адресации через R8
|
||||
; ============================================================
|
||||
|
||||
.текст
|
||||
.глобал _start
|
||||
|
||||
_start:
|
||||
; Получаем argv[1]
|
||||
вытолкнуть рсикс ; argc
|
||||
вытолкнуть рсиай ; argv[0]
|
||||
вытолкнуть р9 ; argv[1] в R9
|
||||
|
||||
; Загружаем первый байт из argv[1] через R9
|
||||
загрузить ал, [р9]
|
||||
|
||||
; Сохраняем в переменную (не обязательно, но для проверки)
|
||||
сохранить [байт], ал
|
||||
|
||||
; Выход с кодом = загруженный байт
|
||||
переместить_имм раикс, 60
|
||||
загрузить рдиай, [байт]
|
||||
вызов_системы
|
||||
|
||||
.данные
|
||||
байт: .байт 0
|
||||
Loading…
Reference in a new issue