починить р12 и sib-байт
This commit is contained in:
parent
1209ca732a
commit
3493d06200
|
|
@ -189,6 +189,10 @@ def encode_mov_mem_reg_absolute(reg_info, mem_info, current_pos, vaddr_text):
|
|||
def encode_mov_reg_mem_indirect(reg_info: dict, base_reg: str) -> bytearray:
|
||||
"""
|
||||
Кодирует MOV reg, [base_reg] — косвенная адресация через регистр.
|
||||
|
||||
Особые случаи x86-64:
|
||||
- [rsp] и [r12] (индексы 4 и 12) требуют SIB-байта при mod=00
|
||||
- [rbp] и [r13] (индексы 5 и 13) требуют disp8=0 при mod=00
|
||||
"""
|
||||
code = bytearray()
|
||||
|
||||
|
|
@ -239,16 +243,29 @@ def encode_mov_reg_mem_indirect(reg_info: dict, base_reg: str) -> bytearray:
|
|||
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
|
||||
# === 4. Формируем ModR/M и SIB байты ===
|
||||
base_low = base_index & 7 # младшие 3 бита индекса
|
||||
|
||||
if base_low == 4:
|
||||
# Особый случай: [rsp] или [r12] — требуется SIB-байт
|
||||
# В x86-64 mod=00 с r/m=4 означает [SIB] без смещения
|
||||
# SIB: base=4 (rsp/r12), index=4 (нет индексного регистра), scale=0
|
||||
modrm_byte = 0x00 | ((reg_index & 7) << 3) | 0x04
|
||||
sib_byte = 0x20 | (4 << 3) | 4 # scale=0, index=4(нет), base=4
|
||||
disp8 = None
|
||||
has_sib = True
|
||||
elif base_low == 5:
|
||||
# Особый случай: [rbp] или [r13] — требуется disp8=0
|
||||
# В x86-64 mod=00 с r/m=5 означает [RIP+disp32],
|
||||
# поэтому для [rbp]/[r13] используем mod=01 с disp8=0
|
||||
modrm_byte = 0x40 | ((reg_index & 7) << 3) | 0x05
|
||||
disp8 = 0x00
|
||||
has_sib = False
|
||||
else:
|
||||
# Обычный случай: [reg] — mod=00, без SIB, без смещения
|
||||
modrm_byte = ((reg_index & 7) << 3) | base_low
|
||||
disp8 = None
|
||||
has_sib = False
|
||||
|
||||
# === 5. Собираем инструкцию ===
|
||||
|
||||
|
|
@ -266,12 +283,17 @@ def encode_mov_reg_mem_indirect(reg_info: dict, base_reg: str) -> bytearray:
|
|||
# 5d. ModR/M байт
|
||||
code.append(modrm_byte)
|
||||
|
||||
# 5e. Disp8 (если есть)
|
||||
# 5e. SIB байт (только для RSP/R12)
|
||||
if has_sib:
|
||||
code.append(sib_byte)
|
||||
|
||||
# 5f. Disp8 (только для RBP/R13)
|
||||
if disp8 is not None:
|
||||
code.append(disp8)
|
||||
|
||||
return code
|
||||
|
||||
|
||||
def encode_mov_mem_reg_indirect(base_reg, reg_info):
|
||||
"""
|
||||
Кодирует MOV [base_reg], reg — косвенная адресация.
|
||||
|
|
|
|||
|
|
@ -20,4 +20,5 @@
|
|||
1;тест_адресации_р13;Проверка косвенной адресации через R13 (ASCII код первого символа аргумента)
|
||||
1;тест_адресации_р14;Проверка косвенной адресации через R14 (ASCII код первого символа аргумента)
|
||||
1;тест_адресации_р15;Проверка косвенной адресации через R15 (ASCII код первого символа аргумента)
|
||||
1;двоеточие_в_строке;Проверка обработки строк с двоеточием внутри
|
||||
1;двоеточие_в_строке;Проверка обработки строк с двоеточием внутри
|
||||
1;тест_адресации_р12;Проверка косвенной адресации через R12 (ASCII код первого символа аргумента)
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 46.
|
145
тесты/тест_адресации_р12/тест_адресации_р12.py
Normal file
145
тесты/тест_адресации_р12/тест_адресации_р12.py
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Тест для проверки косвенной адресации через регистр R12
|
||||
Запускает скомпилированную программу с различными аргументами
|
||||
и проверяет код возврата (должен быть равен 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 / "тест_адресации_р12.квс"
|
||||
|
||||
def clean():
|
||||
"""Очищает артефакты сборки"""
|
||||
files = [
|
||||
"тест_адресации_р12.elf",
|
||||
"тест_адресации_р12.csv",
|
||||
"тест_адресации_р12.аст",
|
||||
"тест_адресации_р12.токены",
|
||||
"тест_адресации_р12.константа",
|
||||
"тест_адресации_р12_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 / "тест_адресации_р12.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), # Звёздочка
|
||||
('~', 126), # Тильда
|
||||
(' ', 32), # Пробел
|
||||
('\t', 9), # Табуляция (может не сработать из-за экранирования)
|
||||
]
|
||||
|
||||
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
тесты/тест_адресации_р12/тест_адресации_р12.квс
Normal file
29
тесты/тест_адресации_р12/тест_адресации_р12.квс
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
;./тесты/тест_адресации_р12.elf "A"
|
||||
;echo $? # должен быть 65
|
||||
|
||||
; ============================================================
|
||||
; тест_адресации_r12.квс - тест косвенной адресации через R12
|
||||
; ============================================================
|
||||
|
||||
.текст
|
||||
.глобал _start
|
||||
|
||||
_start:
|
||||
; Получаем argv[1]
|
||||
вытолкнуть рсикс ; argc
|
||||
вытолкнуть рсиай ; argv[0]
|
||||
вытолкнуть р12 ; argv[1] в R12
|
||||
|
||||
; Загружаем первый байт из argv[1] через R12
|
||||
загрузить ал, [р12]
|
||||
|
||||
; Сохраняем в переменную (не обязательно, но для проверки)
|
||||
сохранить [байт], ал
|
||||
|
||||
; Выход с кодом = загруженный байт
|
||||
переместить_имм раикс, 60
|
||||
загрузить рдиай, [байт]
|
||||
вызов_системы
|
||||
|
||||
.данные
|
||||
байт: .байт 0
|
||||
|
|
@ -1,18 +1,29 @@
|
|||
;./тесты/тест_адресации_р11.elf "A"
|
||||
;echo $? # должен быть 65
|
||||
|
||||
; ============================================================
|
||||
; тест_адресации_r11.квс - тест косвенной адресации через R11
|
||||
; ============================================================
|
||||
|
||||
.текст
|
||||
.глобал _start
|
||||
|
||||
_start:
|
||||
; Системный вызов write(1, msg, len)
|
||||
переместить_имм раикс, 1 ; номер syscall write = 1
|
||||
переместить_имм рдиай, 1 ; stdout = 1
|
||||
переместить_имм рсиай, msg ; указатель на строку
|
||||
переместить_имм рдикс, 21 ; длина строки
|
||||
вызов_системы
|
||||
; Получаем argv[1]
|
||||
вытолкнуть рсикс ; argc
|
||||
вытолкнуть рсиай ; argv[0]
|
||||
вытолкнуть р12 ; argv[1] в R12
|
||||
|
||||
; Системный вызов: exit(0)
|
||||
переместить_имм раикс, 60 ; номер syscall exit = 60
|
||||
переместить_имм рдиай, 0 ; код возврата
|
||||
; Загружаем первый байт из argv[1] через R12
|
||||
загрузить ал, [р12]
|
||||
|
||||
; Сохраняем в переменную (не обязательно, но для проверки)
|
||||
сохранить [байт], ал
|
||||
|
||||
; Выход с кодом = загруженный байт
|
||||
переместить_имм раикс, 60
|
||||
загрузить рдиай, [байт]
|
||||
вызов_системы
|
||||
|
||||
.данные
|
||||
msg: .строка "Приве : мир!\n"
|
||||
байт: .байт 0
|
||||
Loading…
Reference in a new issue