прототип стандартной библиотеки
This commit is contained in:
parent
353ecb363d
commit
3ce19efae6
|
|
@ -32,6 +32,7 @@ if __name__ == "__main__":
|
||||||
("kvs_parser.py", [tokens_file, ast_file], "Парсинг"),
|
("kvs_parser.py", [tokens_file, ast_file], "Парсинг"),
|
||||||
("kvs_pass1.py", [ast_file, pass1_file], "Первый проход"),
|
("kvs_pass1.py", [ast_file, pass1_file], "Первый проход"),
|
||||||
("kvs_pass2.py", [ast_file, pass1_file, csv_file], "Второй проход и генерация CSV"),
|
("kvs_pass2.py", [ast_file, pass1_file, csv_file], "Второй проход и генерация CSV"),
|
||||||
|
("kvs_verify.py", [pass1_file, csv_file], "Проверка размеров инструкций"),
|
||||||
("kvs_builder.py", [csv_file, pass1_file, elf_file], "Сборка ELF"),
|
("kvs_builder.py", [csv_file, pass1_file, elf_file], "Сборка ELF"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -43,8 +44,12 @@ if __name__ == "__main__":
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
print(f"ОШИБКА на этапе '{description}':")
|
print(f"ОШИБКА на этапе '{description}':")
|
||||||
print(result.stderr)
|
print(result.stderr)
|
||||||
|
if result.stdout:
|
||||||
|
print(result.stdout)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Для верификатора показываем stdout (там детали проверки)
|
||||||
|
if result.stdout:
|
||||||
print(result.stdout)
|
print(result.stdout)
|
||||||
|
|
||||||
print(f"\n=== Компиляция успешно завершена ===")
|
print(f"\n=== Компиляция успешно завершена ===")
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ def read_csv(input_file, vaddr_text, vaddr_data, text_size, data_size):
|
||||||
data_bytes = bytearray(data_size)
|
data_bytes = bytearray(data_size)
|
||||||
|
|
||||||
with open(input_file, 'r', encoding='utf-8') as f:
|
with open(input_file, 'r', encoding='utf-8') as f:
|
||||||
next(f) # Пропускаем заголовок
|
next(f)
|
||||||
for line in f:
|
for line in f:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if not line:
|
if not line:
|
||||||
|
|
@ -34,7 +34,6 @@ def read_csv(input_file, vaddr_text, vaddr_data, text_size, data_size):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Определяем секцию по адресу
|
|
||||||
if addr >= vaddr_data:
|
if addr >= vaddr_data:
|
||||||
offset = addr - vaddr_data
|
offset = addr - vaddr_data
|
||||||
if 0 <= offset < data_size:
|
if 0 <= offset < data_size:
|
||||||
|
|
@ -44,6 +43,18 @@ def read_csv(input_file, vaddr_text, vaddr_data, text_size, data_size):
|
||||||
if 0 <= offset < text_size:
|
if 0 <= offset < text_size:
|
||||||
text_bytes[offset] = byte_val
|
text_bytes[offset] = byte_val
|
||||||
|
|
||||||
|
# Заменяем хвостовые нули на NOP'ы (0x90)
|
||||||
|
# Находим последний ненулевой байт
|
||||||
|
last_nonzero = -1
|
||||||
|
for i in range(len(text_bytes) - 1, -1, -1):
|
||||||
|
if text_bytes[i] != 0:
|
||||||
|
last_nonzero = i
|
||||||
|
break
|
||||||
|
|
||||||
|
if last_nonzero >= 0 and last_nonzero < len(text_bytes) - 1:
|
||||||
|
for i in range(last_nonzero + 1, len(text_bytes)):
|
||||||
|
text_bytes[i] = 0x90
|
||||||
|
|
||||||
return text_bytes, data_bytes
|
return text_bytes, data_bytes
|
||||||
|
|
||||||
def read_pass1(input_file):
|
def read_pass1(input_file):
|
||||||
|
|
|
||||||
77
kvs_data.py
77
kvs_data.py
|
|
@ -238,11 +238,31 @@ INSTRUCTIONS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Размеры инструкций в байтах (для первого прохода)
|
# ========== РАЗМЕРЫ ИНСТРУКЦИЙ ДЛЯ ПЕРВОГО ПРОХОДА ==========
|
||||||
INSTRUCTION_SIZES = {
|
|
||||||
"переместить_имм": 10,
|
# Инструкции с ФИКСИРОВАННЫМ размером (не зависят от операндов)
|
||||||
"сравнить_с": 7,
|
FIXED_SIZE_INSTRUCTIONS = {
|
||||||
|
"переместить": 3,
|
||||||
|
"сравнить": 3,
|
||||||
|
"сравнить_байт": 3,
|
||||||
|
"проверить": 3,
|
||||||
|
"прибавить": 3,
|
||||||
|
"прибавить_байт": 3,
|
||||||
|
"вычесть": 3,
|
||||||
|
"вычесть_байт": 3,
|
||||||
|
"увеличить": 3,
|
||||||
|
"уменьшить": 3,
|
||||||
|
"умножить": 3,
|
||||||
|
"умножить_знаковое": 3,
|
||||||
|
"разделить": 3,
|
||||||
|
"разделить_знаковое": 3,
|
||||||
|
"и": 3,
|
||||||
|
"или": 3,
|
||||||
|
"исключающее_или": 3,
|
||||||
|
"инвертировать": 3,
|
||||||
|
"отрицать": 3,
|
||||||
"переход": 5,
|
"переход": 5,
|
||||||
|
"короткий_переход": 2,
|
||||||
"переход_если_равно": 6,
|
"переход_если_равно": 6,
|
||||||
"переход_если_неравно": 6,
|
"переход_если_неравно": 6,
|
||||||
"переход_если_ноль": 6,
|
"переход_если_ноль": 6,
|
||||||
|
|
@ -253,9 +273,6 @@ INSTRUCTION_SIZES = {
|
||||||
"переход_если_больше_или_равно": 6,
|
"переход_если_больше_или_равно": 6,
|
||||||
"переход_если_перенос": 6,
|
"переход_если_перенос": 6,
|
||||||
"переход_если_нет_переноса": 6,
|
"переход_если_нет_переноса": 6,
|
||||||
"вызов_системы": 2,
|
|
||||||
"нет_операции": 1,
|
|
||||||
"короткий_переход": 2,
|
|
||||||
"короткий_переход_если_равно": 2,
|
"короткий_переход_если_равно": 2,
|
||||||
"короткий_переход_если_неравно": 2,
|
"короткий_переход_если_неравно": 2,
|
||||||
"короткий_переход_если_меньше": 2,
|
"короткий_переход_если_меньше": 2,
|
||||||
|
|
@ -266,31 +283,19 @@ INSTRUCTION_SIZES = {
|
||||||
"короткий_переход_если_нет_переноса": 2,
|
"короткий_переход_если_нет_переноса": 2,
|
||||||
"короткий_переход_если_ноль": 2,
|
"короткий_переход_если_ноль": 2,
|
||||||
"короткий_переход_если_не_ноль": 2,
|
"короткий_переход_если_не_ноль": 2,
|
||||||
"сравнить": 3,
|
"вызвать": 5,
|
||||||
"проверить": 3,
|
"вернуться": 1,
|
||||||
"вычесть": 3,
|
"вызов_системы": 2,
|
||||||
"прибавить": 3,
|
"нет_операции": 1,
|
||||||
"увеличить": 3,
|
"остановить": 1,
|
||||||
"уменьшить": 3,
|
"отладка": 1,
|
||||||
"и": 3,
|
"цикл": 2,
|
||||||
"или": 3,
|
"обменять": 4,
|
||||||
"исключающее_или": 3,
|
|
||||||
"инвертировать": 3,
|
|
||||||
"отрицать": 3,
|
|
||||||
"втолкнуть": 2,
|
|
||||||
"вытолкнуть": 2,
|
|
||||||
"втолкнуть_непосредственно": 5,
|
|
||||||
"умножить": 3,
|
|
||||||
"умножить_знаковое": 3,
|
|
||||||
"разделить": 3,
|
|
||||||
"разделить_знаковое": 3,
|
|
||||||
"сдвиг_влево": 4,
|
"сдвиг_влево": 4,
|
||||||
"сдвиг_вправо": 4,
|
"сдвиг_вправо": 4,
|
||||||
"сдвиг_арифметический_вправо": 4,
|
"сдвиг_арифметический_вправо": 4,
|
||||||
"вращать_влево": 4,
|
"вращать_влево": 4,
|
||||||
"вращать_вправо": 4,
|
"вращать_вправо": 4,
|
||||||
"цикл": 2,
|
|
||||||
"обменять": 4,
|
|
||||||
"прервать": 2,
|
"прервать": 2,
|
||||||
"ввод_байта": 2,
|
"ввод_байта": 2,
|
||||||
"вывод_байта": 2,
|
"вывод_байта": 2,
|
||||||
|
|
@ -308,6 +313,24 @@ INSTRUCTION_SIZES = {
|
||||||
"прочитать_счётчик": 2,
|
"прочитать_счётчик": 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Инструкции с ПЕРЕМЕННЫМ размером (зависят от операндов)
|
||||||
|
# Для них pass1 должен анализировать операнды
|
||||||
|
VARIABLE_SIZE_INSTRUCTIONS = {
|
||||||
|
"переместить_имм", # зависит от размера регистра (5/10)
|
||||||
|
"загрузить_байт", # зависит от регистра (1/2)
|
||||||
|
"сравнить_с", # зависит от размера регистра (4/7)
|
||||||
|
"прибавить_непосредственно", # зависит от размера регистра и imm (4/7)
|
||||||
|
"вычесть_непосредственно", # зависит от размера регистра и imm (4/7)
|
||||||
|
"загрузить", # зависит от режима адресации (3/7)
|
||||||
|
"сохранить", # зависит от режима адресации (3/7)
|
||||||
|
"загрузить_адрес", # зависит от режима адресации (3/7)
|
||||||
|
"втолкнуть", # зависит от регистра (1/2)
|
||||||
|
"вытолкнуть", # зависит от регистра (1/2)
|
||||||
|
"втолкнуть_непосредственно", # зависит от imm (2/5)
|
||||||
|
"переместить_с_нулями", # зависит от размера регистра
|
||||||
|
"переместить_со_знаком", # зависит от размера регистра
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# === ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ===
|
# === ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ===
|
||||||
|
|
||||||
|
|
|
||||||
78
kvs_pass1.py
78
kvs_pass1.py
|
|
@ -8,7 +8,13 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
sys.path.insert(0, '.')
|
sys.path.insert(0, '.')
|
||||||
from kvs_data import PAGE_SIZE, text_vaddr_base, align_up, INSTRUCTIONS, INSTRUCTION_SIZES
|
from kvs_data import PAGE_SIZE, text_vaddr_base, align_up, INSTRUCTIONS
|
||||||
|
from kvs_data import FIXED_SIZE_INSTRUCTIONS, VARIABLE_SIZE_INSTRUCTIONS
|
||||||
|
|
||||||
|
# ========== РЕЖИМ ОЦЕНКИ РАЗМЕРОВ ==========
|
||||||
|
# True — пессимистичный: все неизвестные инструкции = 10 байт (максимум)
|
||||||
|
# False — оптимистичный: использовать точный анализ операндов
|
||||||
|
PESSIMISTIC_SIZE_ESTIMATE = False
|
||||||
|
|
||||||
def unescape_string(s):
|
def unescape_string(s):
|
||||||
"""Преобразует escape-последовательности в реальные символы"""
|
"""Преобразует escape-последовательности в реальные символы"""
|
||||||
|
|
@ -91,15 +97,7 @@ def split_by_operators(content):
|
||||||
def parse_memory_operand(operand_str):
|
def parse_memory_operand(operand_str):
|
||||||
"""
|
"""
|
||||||
Анализирует операнд памяти вида [reg + reg*scale + disp]
|
Анализирует операнд памяти вида [reg + reg*scale + disp]
|
||||||
Возвращает словарь с информацией:
|
Возвращает словарь с информацией.
|
||||||
- has_base: bool
|
|
||||||
- base_reg: str or None
|
|
||||||
- has_index: bool
|
|
||||||
- index_reg: str or None
|
|
||||||
- scale: int (1,2,4,8)
|
|
||||||
- has_disp: bool
|
|
||||||
- disp_value: int (если есть)
|
|
||||||
- disp_size: 1 или 4
|
|
||||||
"""
|
"""
|
||||||
if not operand_str.startswith('[') or not operand_str.endswith(']'):
|
if not operand_str.startswith('[') or not operand_str.endswith(']'):
|
||||||
return None
|
return None
|
||||||
|
|
@ -119,7 +117,6 @@ def parse_memory_operand(operand_str):
|
||||||
'disp_size': 0
|
'disp_size': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# Проверяем, не является ли содержимое просто числом (абсолютный адрес)
|
|
||||||
if is_dec_number(content) or is_hex_number(content):
|
if is_dec_number(content) or is_hex_number(content):
|
||||||
result['has_disp'] = True
|
result['has_disp'] = True
|
||||||
if content.startswith('0x') or content.startswith('0X'):
|
if content.startswith('0x') or content.startswith('0X'):
|
||||||
|
|
@ -129,13 +126,11 @@ def parse_memory_operand(operand_str):
|
||||||
result['disp_size'] = 4
|
result['disp_size'] = 4
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Простой регистр без смещения
|
|
||||||
if is_register(content):
|
if is_register(content):
|
||||||
result['has_base'] = True
|
result['has_base'] = True
|
||||||
result['base_reg'] = content
|
result['base_reg'] = content
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Разбираем выражение: регистр [+- регистр[*масштаб] [+- смещение]]
|
|
||||||
parts = split_by_operators(content)
|
parts = split_by_operators(content)
|
||||||
|
|
||||||
for part in parts:
|
for part in parts:
|
||||||
|
|
@ -235,26 +230,20 @@ class Pass1:
|
||||||
elif directive == '.байт':
|
elif directive == '.байт':
|
||||||
sec = parts[2]
|
sec = parts[2]
|
||||||
if len(parts) > 3 and parts[3]:
|
if len(parts) > 3 and parts[3]:
|
||||||
# Считаем количество значений, разделённых запятыми
|
|
||||||
num_bytes = 1
|
num_bytes = 1
|
||||||
for ch in parts[3]:
|
for ch in parts[3]:
|
||||||
if ch == ',':
|
if ch == ',':
|
||||||
num_bytes += 1
|
num_bytes += 1
|
||||||
self.position[sec] += num_bytes
|
self.position[sec] += num_bytes
|
||||||
|
|
||||||
# Директивы резервирования в .бнд
|
|
||||||
elif directive == '.резб':
|
elif directive == '.резб':
|
||||||
count = int(parts[3])
|
count = int(parts[3])
|
||||||
self.position['.бнд'] += count * 1
|
self.position['.бнд'] += count * 1
|
||||||
|
|
||||||
elif directive == '.резс':
|
elif directive == '.резс':
|
||||||
count = int(parts[3])
|
count = int(parts[3])
|
||||||
self.position['.бнд'] += count * 2
|
self.position['.бнд'] += count * 2
|
||||||
|
|
||||||
elif directive == '.рездс':
|
elif directive == '.рездс':
|
||||||
count = int(parts[3])
|
count = int(parts[3])
|
||||||
self.position['.бнд'] += count * 4
|
self.position['.бнд'] += count * 4
|
||||||
|
|
||||||
elif directive == '.резкс':
|
elif directive == '.резкс':
|
||||||
count = int(parts[3])
|
count = int(parts[3])
|
||||||
self.position['.бнд'] += count * 8
|
self.position['.бнд'] += count * 8
|
||||||
|
|
@ -271,7 +260,6 @@ class Pass1:
|
||||||
operands_str = parts[3] if len(parts) > 3 else ""
|
operands_str = parts[3] if len(parts) > 3 else ""
|
||||||
operands = []
|
operands = []
|
||||||
if operands_str:
|
if operands_str:
|
||||||
# Разбиваем по запятым
|
|
||||||
current = ''
|
current = ''
|
||||||
for ch in operands_str:
|
for ch in operands_str:
|
||||||
if ch == ',':
|
if ch == ',':
|
||||||
|
|
@ -287,20 +275,44 @@ class Pass1:
|
||||||
def estimate_size(self, mnemonic, operands):
|
def estimate_size(self, mnemonic, operands):
|
||||||
"""Динамический расчёт размера инструкции"""
|
"""Динамический расчёт размера инструкции"""
|
||||||
|
|
||||||
# Инструкции с памятью (загрузить, сохранить, загрузить_адрес)
|
# Инструкции с фиксированным размером
|
||||||
|
if mnemonic in FIXED_SIZE_INSTRUCTIONS:
|
||||||
|
return FIXED_SIZE_INSTRUCTIONS[mnemonic]
|
||||||
|
|
||||||
|
# Инструкции с переменным размером — анализируем операнды
|
||||||
if mnemonic in ("загрузить", "сохранить", "загрузить_адрес"):
|
if mnemonic in ("загрузить", "сохранить", "загрузить_адрес"):
|
||||||
# RIP-relative: REX (1) + opcode (1) + ModR/M (1) + disp32 (4) = 7
|
for op in operands:
|
||||||
return 7
|
if op.startswith('MEM:reg_indirect:'):
|
||||||
|
return 3 # косвенная: REX + opcode + ModR/M
|
||||||
|
return 7 # абсолютная: REX + opcode + ModR/M + disp32
|
||||||
|
|
||||||
# Инструкции без операндов — размер из INSTRUCTIONS
|
if mnemonic in ("втолкнуть", "вытолкнуть"):
|
||||||
if mnemonic in ("вызов_системы", "нет_операции", "вернуться", "остановить", "отладка"):
|
if operands:
|
||||||
instr = INSTRUCTIONS.get(mnemonic)
|
reg = operands[0]
|
||||||
if instr and "opcode" in instr:
|
if reg in ('р8', 'р9', 'р10', 'р11', 'р12', 'р13', 'р14', 'р15'):
|
||||||
return len(instr["opcode"])
|
return 2 # нужен REX-префикс
|
||||||
return 2
|
return 1 # без REX
|
||||||
|
|
||||||
# Фиксированные размеры из общей таблицы
|
if mnemonic in ("прибавить_непосредственно", "вычесть_непосредственно", "сравнить_с"):
|
||||||
return INSTRUCTION_SIZES.get(mnemonic, 3)
|
return 7 # пессимистично: REX + opcode + ModR/M + imm32
|
||||||
|
|
||||||
|
if mnemonic == "переместить_имм":
|
||||||
|
return 10 # пессимистично: mov reg64, imm64
|
||||||
|
|
||||||
|
if mnemonic in ("переместить_с_нулями", "переместить_со_знаком"):
|
||||||
|
return 8 # REX + 3-байтный opcode + ModR/M + disp32
|
||||||
|
|
||||||
|
if mnemonic == "загрузить_байт":
|
||||||
|
return 2 # opcode + imm8
|
||||||
|
|
||||||
|
if mnemonic == "втолкнуть_непосредственно":
|
||||||
|
return 5 # пессимистично: opcode + imm32
|
||||||
|
|
||||||
|
# Неизвестная инструкция
|
||||||
|
if PESSIMISTIC_SIZE_ESTIMATE:
|
||||||
|
return 10
|
||||||
|
else:
|
||||||
|
return 3
|
||||||
|
|
||||||
def calculate_layout(self):
|
def calculate_layout(self):
|
||||||
text_size = self.position[".text"]
|
text_size = self.position[".text"]
|
||||||
|
|
@ -316,13 +328,11 @@ class Pass1:
|
||||||
offset_data = align_up(offset_text + text_size, PAGE_SIZE)
|
offset_data = align_up(offset_text + text_size, PAGE_SIZE)
|
||||||
vaddr_text = text_vaddr_base
|
vaddr_text = text_vaddr_base
|
||||||
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE)
|
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE)
|
||||||
# .бнд всегда на следующей странице после .data
|
|
||||||
vaddr_bnd = vaddr_data + PAGE_SIZE
|
vaddr_bnd = vaddr_data + PAGE_SIZE
|
||||||
|
|
||||||
comment_size = len("Сборщик КВС".encode('utf-8')) + 1
|
comment_size = len("Сборщик КВС".encode('utf-8')) + 1
|
||||||
offset_comment = align_up(offset_data + data_size, 1)
|
offset_comment = align_up(offset_data + data_size, 1)
|
||||||
|
|
||||||
# shstrtab теперь включает ".bss"
|
|
||||||
if bnd_size > 0:
|
if bnd_size > 0:
|
||||||
shstrtab_content = b"\x00.text\x00.data\x00.bss\x00.comment\x00.shstrtab\x00"
|
shstrtab_content = b"\x00.text\x00.data\x00.bss\x00.comment\x00.shstrtab\x00"
|
||||||
else:
|
else:
|
||||||
|
|
@ -371,7 +381,7 @@ if __name__ == "__main__":
|
||||||
layout = pass1.calculate_layout()
|
layout = pass1.calculate_layout()
|
||||||
write_pass1(layout, pass1.labels, pass1.label_sections, pass1.symbols, sys.argv[2])
|
write_pass1(layout, pass1.labels, pass1.label_sections, pass1.symbols, sys.argv[2])
|
||||||
|
|
||||||
print(f"Проход 1:")
|
print(f"Проход 1 (режим: {'пессимистичный' if PESSIMISTIC_SIZE_ESTIMATE else 'оптимистичный'}):")
|
||||||
print(f" .text: размер={layout['text_size']} байт, смещение_в_файле=0x{layout['offset_text']:x}, виртуальный_адрес=0x{layout['vaddr_text']:x}")
|
print(f" .text: размер={layout['text_size']} байт, смещение_в_файле=0x{layout['offset_text']:x}, виртуальный_адрес=0x{layout['vaddr_text']:x}")
|
||||||
print(f" .data: размер={layout['data_size']} байт, смещение_в_файле=0x{layout['offset_data']:x}, виртуальный_адрес=0x{layout['vaddr_data']:x}")
|
print(f" .data: размер={layout['data_size']} байт, смещение_в_файле=0x{layout['offset_data']:x}, виртуальный_адрес=0x{layout['vaddr_data']:x}")
|
||||||
print(f" .бнд: размер={layout['bnd_size']} байт, виртуальный_адрес=0x{layout['vaddr_bnd']:x}")
|
print(f" .бнд: размер={layout['bnd_size']} байт, виртуальный_адрес=0x{layout['vaddr_bnd']:x}")
|
||||||
|
|
|
||||||
|
|
@ -734,14 +734,26 @@ def encode_add_sub_reg_reg(mnemonic, operands): # ДУБЛИКАТ
|
||||||
return code
|
return code
|
||||||
|
|
||||||
|
|
||||||
def encode_muldiv(mnemonic): # ДУБЛИКАТ
|
def encode_muldiv(mnemonic, operands): # ДУБЛИКАТ
|
||||||
"""MUL/IMUL/DIV/IDIV"""
|
"""MUL/IMUL/DIV/IDIV"""
|
||||||
code = bytearray()
|
code = bytearray()
|
||||||
instr = INSTRUCTIONS[mnemonic]
|
instr = INSTRUCTIONS[mnemonic]
|
||||||
subop = instr["subop"]
|
subop = instr["subop"]
|
||||||
code.append(0x48)
|
|
||||||
|
# Получаем индекс регистра-операнда
|
||||||
|
if operands:
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
reg = reg_info["index"]
|
||||||
|
else:
|
||||||
|
reg = 0 # по умолчанию rax
|
||||||
|
|
||||||
|
rex = 0x48
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01 # REX.B
|
||||||
|
|
||||||
|
code.append(rex)
|
||||||
code.extend(instr["opcode"])
|
code.extend(instr["opcode"])
|
||||||
modrm = 0xC0 | (subop << 3) | 0
|
modrm = 0xC0 | (subop << 3) | (reg & 7)
|
||||||
code.append(modrm)
|
code.append(modrm)
|
||||||
return code
|
return code
|
||||||
|
|
||||||
|
|
@ -1073,7 +1085,7 @@ def encode_instruction(mnemonic, operands, labels, label_sections, symbols, vadd
|
||||||
|
|
||||||
# ----- MUL/DIV -----
|
# ----- MUL/DIV -----
|
||||||
elif mnemonic in ("умножить", "умножить_знаковое", "разделить", "разделить_знаковое"):
|
elif mnemonic in ("умножить", "умножить_знаковое", "разделить", "разделить_знаковое"):
|
||||||
return encode_muldiv(mnemonic)
|
return encode_muldiv(mnemonic, operands)
|
||||||
|
|
||||||
# ----- AND/OR/XOR -----
|
# ----- AND/OR/XOR -----
|
||||||
elif mnemonic in ("и", "или", "исключающее_или"):
|
elif mnemonic in ("и", "или", "исключающее_или"):
|
||||||
|
|
|
||||||
247
kvs_verify.py
Normal file
247
kvs_verify.py
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Верификатор КВС
|
||||||
|
Сравнивает размеры инструкций из pass1 с реальными размерами из CSV.
|
||||||
|
Выводит расхождения и останавливает сборку при ошибках.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Если True — разрешает сборку, когда единственная ошибка это общий размер .text
|
||||||
|
# (расхождение до 16 байт считается допустимым)
|
||||||
|
ALLOW_TEXT_SIZE_MISMATCH = True
|
||||||
|
MAX_TEXT_SIZE_MISMATCH = 25
|
||||||
|
|
||||||
|
|
||||||
|
def read_pass1(input_file):
|
||||||
|
"""Читает pass1-файл: PARAM и LABEL"""
|
||||||
|
params = {}
|
||||||
|
labels = {}
|
||||||
|
label_sections = {}
|
||||||
|
|
||||||
|
with open(input_file, 'r', encoding='utf-8') as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
parts = line.split(':')
|
||||||
|
if parts[0] == "PARAM":
|
||||||
|
key = parts[1]
|
||||||
|
value = parts[2]
|
||||||
|
if value.isdigit() or (value.startswith('-') and value[1:].isdigit()):
|
||||||
|
value = int(value)
|
||||||
|
params[key] = value
|
||||||
|
elif parts[0] == "LABEL":
|
||||||
|
label = parts[1]
|
||||||
|
sec = parts[2]
|
||||||
|
pos = int(parts[3])
|
||||||
|
labels[label] = pos
|
||||||
|
label_sections[label] = sec
|
||||||
|
|
||||||
|
return params, labels, label_sections
|
||||||
|
|
||||||
|
|
||||||
|
def read_csv(input_file):
|
||||||
|
"""
|
||||||
|
Читает CSV-файл.
|
||||||
|
Возвращает:
|
||||||
|
- instr_list: список инструкций с адресами и размерами
|
||||||
|
"""
|
||||||
|
instr_list = []
|
||||||
|
current_cmd = None
|
||||||
|
current_start = None
|
||||||
|
current_size = 0
|
||||||
|
|
||||||
|
with open(input_file, 'r', encoding='utf-8') as f:
|
||||||
|
header = f.readline()
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
parts = line.split(';')
|
||||||
|
if len(parts) < 2:
|
||||||
|
continue
|
||||||
|
|
||||||
|
addr_str = parts[0]
|
||||||
|
byte_str = parts[1]
|
||||||
|
cmd_str = parts[3] if len(parts) > 3 else ""
|
||||||
|
|
||||||
|
try:
|
||||||
|
addr = int(addr_str, 16)
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if addr >= 0x402000:
|
||||||
|
break
|
||||||
|
|
||||||
|
if cmd_str:
|
||||||
|
if current_cmd is not None:
|
||||||
|
instr_list.append({
|
||||||
|
'cmd': current_cmd,
|
||||||
|
'start': current_start,
|
||||||
|
'size': current_size
|
||||||
|
})
|
||||||
|
current_cmd = cmd_str
|
||||||
|
current_start = addr
|
||||||
|
current_size = 1
|
||||||
|
else:
|
||||||
|
current_size += 1
|
||||||
|
|
||||||
|
if current_cmd is not None:
|
||||||
|
instr_list.append({
|
||||||
|
'cmd': current_cmd,
|
||||||
|
'start': current_start,
|
||||||
|
'size': current_size
|
||||||
|
})
|
||||||
|
|
||||||
|
return instr_list
|
||||||
|
|
||||||
|
|
||||||
|
def verify(pass1_file, csv_file):
|
||||||
|
"""Сравнивает pass1 и pass2, возвращает список ошибок"""
|
||||||
|
from kvs_data import FIXED_SIZE_INSTRUCTIONS, INSTRUCTIONS
|
||||||
|
|
||||||
|
params, labels, label_sections = read_pass1(pass1_file)
|
||||||
|
instr_list = read_csv(csv_file)
|
||||||
|
|
||||||
|
vaddr_text = params.get("vaddr_text", 0x401000)
|
||||||
|
text_size_pass1 = params.get("text_size", 0)
|
||||||
|
text_size_pass2 = sum(instr['size'] for instr in instr_list)
|
||||||
|
|
||||||
|
errors = []
|
||||||
|
warnings = []
|
||||||
|
|
||||||
|
print(f"Pass1 .text: {text_size_pass1} байт")
|
||||||
|
print(f"Pass2 .text: {text_size_pass2} байт")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Проверка общего размера
|
||||||
|
text_size_error = None
|
||||||
|
if text_size_pass1 != text_size_pass2:
|
||||||
|
diff = text_size_pass2 - text_size_pass1
|
||||||
|
text_size_error = f"Общий размер .text: pass1={text_size_pass1}, pass2={text_size_pass2} (разница {diff:+d} байт)"
|
||||||
|
if ALLOW_TEXT_SIZE_MISMATCH and abs(diff) <= MAX_TEXT_SIZE_MISMATCH:
|
||||||
|
warnings.append(text_size_error + " — допустимо, сборка продолжена")
|
||||||
|
else:
|
||||||
|
errors.append(text_size_error)
|
||||||
|
|
||||||
|
# Проверка позиций меток
|
||||||
|
print("Проверка позиций меток (.text):")
|
||||||
|
for label, pass1_offset in labels.items():
|
||||||
|
if label_sections.get(label) != ".text":
|
||||||
|
continue
|
||||||
|
|
||||||
|
pass1_addr = vaddr_text + pass1_offset
|
||||||
|
|
||||||
|
found = False
|
||||||
|
for instr in instr_list:
|
||||||
|
if instr['start'] == pass1_addr:
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if found:
|
||||||
|
print(f" [✓] {label} — 0x{pass1_addr:x}")
|
||||||
|
else:
|
||||||
|
closest = None
|
||||||
|
for instr in instr_list:
|
||||||
|
if instr['start'] <= pass1_addr:
|
||||||
|
closest = instr
|
||||||
|
|
||||||
|
if closest:
|
||||||
|
real_addr = closest['start']
|
||||||
|
shift = real_addr - pass1_addr
|
||||||
|
if shift != 0:
|
||||||
|
errors.append(f"Метка '{label}': pass1=0x{pass1_addr:x}, pass2=0x{real_addr:x} (сдвиг {shift:+d} байт)")
|
||||||
|
print(f" [✗] {label} — pass1: 0x{pass1_addr:x}, pass2: 0x{real_addr:x} (сдвиг {shift:+d})")
|
||||||
|
else:
|
||||||
|
print(f" [✓] {label} — 0x{pass1_addr:x}")
|
||||||
|
else:
|
||||||
|
warnings.append(f"Метка '{label}' не найдена в CSV")
|
||||||
|
print(f" [?] {label} — не найдена в CSV")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Сравнение размеров инструкций
|
||||||
|
print("Проверка размеров инструкций:")
|
||||||
|
|
||||||
|
for instr in instr_list:
|
||||||
|
cmd = instr['cmd']
|
||||||
|
real_size = instr['size']
|
||||||
|
real_addr = instr['start']
|
||||||
|
|
||||||
|
mnemonic = cmd.split()[0] if cmd else ""
|
||||||
|
|
||||||
|
if mnemonic in FIXED_SIZE_INSTRUCTIONS:
|
||||||
|
pass1_size = FIXED_SIZE_INSTRUCTIONS[mnemonic]
|
||||||
|
elif mnemonic in ("загрузить", "сохранить", "загрузить_адрес"):
|
||||||
|
if 'MEM:reg_indirect:' in cmd:
|
||||||
|
pass1_size = 3
|
||||||
|
else:
|
||||||
|
pass1_size = 7
|
||||||
|
elif mnemonic in ("втолкнуть", "вытолкнуть"):
|
||||||
|
parts = cmd.split()
|
||||||
|
if len(parts) >= 2:
|
||||||
|
reg = parts[1]
|
||||||
|
if reg in ('р8', 'р9', 'р10', 'р11', 'р12', 'р13', 'р14', 'р15'):
|
||||||
|
pass1_size = 2
|
||||||
|
else:
|
||||||
|
pass1_size = 1
|
||||||
|
else:
|
||||||
|
pass1_size = 1
|
||||||
|
elif mnemonic in ("прибавить_непосредственно", "вычесть_непосредственно", "сравнить_с"):
|
||||||
|
pass1_size = 7
|
||||||
|
elif mnemonic == "переместить_имм":
|
||||||
|
pass1_size = 10
|
||||||
|
elif mnemonic in ("переместить_с_нулями", "переместить_со_знаком"):
|
||||||
|
pass1_size = 8
|
||||||
|
elif mnemonic == "загрузить_байт":
|
||||||
|
pass1_size = 2
|
||||||
|
elif mnemonic == "втолкнуть_непосредственно":
|
||||||
|
pass1_size = 5
|
||||||
|
else:
|
||||||
|
instr_info = INSTRUCTIONS.get(mnemonic)
|
||||||
|
if instr_info and "opcode" in instr_info and instr_info["opcode"] is not None:
|
||||||
|
pass1_size = len(instr_info["opcode"])
|
||||||
|
else:
|
||||||
|
pass1_size = 3
|
||||||
|
|
||||||
|
status = "✓" if pass1_size == real_size else "✗"
|
||||||
|
if pass1_size != real_size:
|
||||||
|
diff = real_size - pass1_size
|
||||||
|
errors.append(f"Инструкция '{cmd}' на 0x{real_addr:x}: pass1={pass1_size}, pass2={real_size} (ошибка {diff:+d})")
|
||||||
|
|
||||||
|
print(f" [{status}] 0x{real_addr:x} {cmd} — pass1: {pass1_size}, pass2: {real_size}" +
|
||||||
|
(f" (ошибка {real_size - pass1_size:+d})" if pass1_size != real_size else ""))
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
return errors, warnings
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("Использование: python kvs_verify.py <вход.проход1> <вход.csv>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
pass1_file = sys.argv[1]
|
||||||
|
csv_file = sys.argv[2]
|
||||||
|
|
||||||
|
errors, warnings = verify(pass1_file, csv_file)
|
||||||
|
|
||||||
|
if warnings:
|
||||||
|
print(f"Предупреждений: {len(warnings)}")
|
||||||
|
for w in warnings:
|
||||||
|
print(f" ⚠ {w}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
print(f"ОШИБОК: {len(errors)}")
|
||||||
|
for e in errors:
|
||||||
|
print(f" ❌ {e}")
|
||||||
|
print("\nСборка остановлена. Исправьте расхождения в размерах инструкций.")
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
print("Все размеры инструкций совпадают. Можно собирать.")
|
||||||
|
sys.exit(0)
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -248,3 +248,6 @@ Pass2 (шаг 5):
|
||||||
|
|
||||||
тестировать все директивы бнд
|
тестировать все директивы бнд
|
||||||
изучить работу с кучей
|
изучить работу с кучей
|
||||||
|
|
||||||
|
|
||||||
|
сохранить_байт и загрузить_байт_из_памяти есть в INSTRUCTIONS, но не реализованы в диспетчере encode_instruction
|
||||||
67
тесты/itoa0.квс
Normal file
67
тесты/itoa0.квс
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Число для преобразования
|
||||||
|
переместить_имм раикс, 73
|
||||||
|
|
||||||
|
; Сохраняем число в .бнд
|
||||||
|
сохранить [число], раикс
|
||||||
|
|
||||||
|
; Загружаем обратно
|
||||||
|
загрузить раикс, [число]
|
||||||
|
|
||||||
|
; Делим на 10
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс ; rax = 7 (частное), rdx = 3 (остаток)
|
||||||
|
|
||||||
|
; Сохраняем остаток в .бнд
|
||||||
|
сохранить [остаток], рдикс
|
||||||
|
|
||||||
|
; Частное (rax) — в цифру и выводим
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Загружаем остаток из .бнд
|
||||||
|
загрузить раикс, [остаток]
|
||||||
|
|
||||||
|
; Остаток — в цифру и выводим
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
буфер:
|
||||||
|
.байт 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
|
|
||||||
|
.бнд
|
||||||
|
число:
|
||||||
|
.резб 8
|
||||||
|
остаток:
|
||||||
|
.резб 8
|
||||||
80
тесты/itoa1.квс
Normal file
80
тесты/itoa1.квс
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Конвертируем 1034
|
||||||
|
переместить_имм раикс, 1034
|
||||||
|
|
||||||
|
; 1234 / 10 = 123, остаток 4
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра3], рдикс
|
||||||
|
|
||||||
|
; 123 / 10 = 12, остаток 3
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
разделить рсикс
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра2], рдикс
|
||||||
|
|
||||||
|
; 12 / 10 = 1, остаток 2
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
разделить рсикс
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра1], рдикс
|
||||||
|
|
||||||
|
; Частное 1 → последняя цифра
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [цифра0], раикс
|
||||||
|
|
||||||
|
; Выводим 4 цифры по одной
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра0
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра1
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра2
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра3
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
|
|
||||||
|
.бнд
|
||||||
|
цифра0:
|
||||||
|
.резб 8
|
||||||
|
цифра1:
|
||||||
|
.резб 8
|
||||||
|
цифра2:
|
||||||
|
.резб 8
|
||||||
|
цифра3:
|
||||||
|
.резб 8
|
||||||
94
тесты/itoa2.квс
Normal file
94
тесты/itoa2.квс
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; МЕНЯЙ ЧИСЛО:
|
||||||
|
переместить_имм раикс, 57321
|
||||||
|
|
||||||
|
; 1-й разряд (единицы): число / 10
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс ; rax = 5432, rdx = 1
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра4], рдикс
|
||||||
|
|
||||||
|
; 2-й разряд (десятки): частное / 10
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
разделить рсикс ; rax = 543, rdx = 2
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра3], рдикс
|
||||||
|
|
||||||
|
; 3-й разряд (сотни)
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
разделить рсикс ; rax = 54, rdx = 3
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра2], рдикс
|
||||||
|
|
||||||
|
; 4-й разряд (тысячи)
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
разделить рсикс ; rax = 5, rdx = 4
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра1], рдикс
|
||||||
|
|
||||||
|
; 5-й разряд (десятки тысяч)
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [цифра0], раикс
|
||||||
|
|
||||||
|
; Выводим 5 цифр по одной
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра0
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра1
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра2
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра3
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра4
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
|
|
||||||
|
.бнд
|
||||||
|
цифра0:
|
||||||
|
.резб 8
|
||||||
|
цифра1:
|
||||||
|
.резб 8
|
||||||
|
цифра2:
|
||||||
|
.резб 8
|
||||||
|
цифра3:
|
||||||
|
.резб 8
|
||||||
|
цифра4:
|
||||||
|
.резб 8
|
||||||
94
тесты/itoa3.квс
Normal file
94
тесты/itoa3.квс
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; МЕНЯЙ ЧИСЛО:
|
||||||
|
переместить_имм раикс, 59321
|
||||||
|
|
||||||
|
; 1-й разряд (единицы): число / 10
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс ; rax = 5432, rdx = 1
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра4], рдикс
|
||||||
|
|
||||||
|
; 2-й разряд (десятки): частное / 10
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
разделить рсикс ; rax = 543, rdx = 2
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра3], рдикс
|
||||||
|
|
||||||
|
; 3-й разряд (сотни)
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
разделить рсикс ; rax = 54, rdx = 3
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра2], рдикс
|
||||||
|
|
||||||
|
; 4-й разряд (тысячи)
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
разделить рсикс ; rax = 5, rdx = 4
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [цифра1], рдикс
|
||||||
|
|
||||||
|
; 5-й разряд (десятки тысяч)
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [цифра0], раикс
|
||||||
|
|
||||||
|
; Выводим 5 цифр по одной
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра0
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра1
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра2
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра3
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, цифра4
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
|
|
||||||
|
.бнд
|
||||||
|
цифра0:
|
||||||
|
.резб 8
|
||||||
|
цифра1:
|
||||||
|
.резб 8
|
||||||
|
цифра2:
|
||||||
|
.резб 8
|
||||||
|
цифра3:
|
||||||
|
.резб 8
|
||||||
|
цифра4:
|
||||||
|
.резб 8
|
||||||
73
тесты/длина_числа.квс
Normal file
73
тесты/длина_числа.квс
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Тест: длина числа 1234
|
||||||
|
переместить_имм раикс, 1234
|
||||||
|
вызвать длина_числа ; rax = количество цифр
|
||||||
|
|
||||||
|
; Выводим результат как цифру
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; =============================================
|
||||||
|
; длина_числа: количество десятичных цифр в rax
|
||||||
|
; Вход: rax = число
|
||||||
|
; Выход: rax = количество цифр (1..20)
|
||||||
|
; =============================================
|
||||||
|
длина_числа:
|
||||||
|
втолкнуть р8
|
||||||
|
втолкнуть р9
|
||||||
|
|
||||||
|
переместить р8, раикс ; р8 = число
|
||||||
|
переместить_имм р9, 0 ; счётчик = 0
|
||||||
|
|
||||||
|
; Проверка на 0
|
||||||
|
сравнить_с р8, 0
|
||||||
|
короткий_переход_если_неравно длина_цикл
|
||||||
|
переместить_имм раикс, 1 ; 0 — это 1 цифра
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
длина_цикл:
|
||||||
|
увеличить р9 ; счётчик++
|
||||||
|
|
||||||
|
; Делим на 10
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс
|
||||||
|
переместить р8, раикс ; частное
|
||||||
|
|
||||||
|
сравнить_с р8, 0
|
||||||
|
короткий_переход_если_неравно длина_цикл
|
||||||
|
|
||||||
|
переместить раикс, р9 ; результат
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
.данные
|
||||||
|
буфер:
|
||||||
|
.байт 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
27
тесты/циклы.квс
Normal file
27
тесты/циклы.квс
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Счётчик циклов = 5
|
||||||
|
переместить_имм р8, 5
|
||||||
|
|
||||||
|
цикл:
|
||||||
|
; Выводим сообщение
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg
|
||||||
|
переместить_имм рдикс, 21
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Счётчик--
|
||||||
|
уменьшить р8
|
||||||
|
сравнить_с р8, 0
|
||||||
|
короткий_переход_если_неравно цикл
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
msg: .строка "Привет мир!\n"
|
||||||
40
тесты/циклы2.квс
Normal file
40
тесты/циклы2.квс
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
переместить_имм р9, 1 ; счётчик = 1
|
||||||
|
|
||||||
|
цикл:
|
||||||
|
; Выводим счётчик как цифру
|
||||||
|
переместить раикс, р9
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Счётчик++
|
||||||
|
увеличить р9
|
||||||
|
сравнить_с р9, 7 ; до 7 (1..6)
|
||||||
|
короткий_переход_если_неравно цикл
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
буфер:
|
||||||
|
.байт 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
40
тесты/циклы3.квс
Normal file
40
тесты/циклы3.квс
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
переместить_имм р9, 6 ; счётчик = 6
|
||||||
|
|
||||||
|
цикл:
|
||||||
|
; Выводим счётчик как цифру
|
||||||
|
переместить раикс, р9
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Счётчик--
|
||||||
|
уменьшить р9
|
||||||
|
сравнить_с р9, 0 ; до 0
|
||||||
|
короткий_переход_если_неравно цикл
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
буфер:
|
||||||
|
.байт 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
45
тесты/циклы4.квс
Normal file
45
тесты/циклы4.квс
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
переместить_имм р8, 1 ; число = 1
|
||||||
|
|
||||||
|
цикл:
|
||||||
|
; Выводим число
|
||||||
|
переместить раикс, р8
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Умножаем на 2
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм р9, 2
|
||||||
|
умножить р9
|
||||||
|
переместить р8, раикс
|
||||||
|
|
||||||
|
; Продолжаем пока < 10
|
||||||
|
сравнить_с р8, 10
|
||||||
|
переход_если_меньше цикл ; длинный переход вместо короткого
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
буфер:
|
||||||
|
.байт 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
86
тесты/циклы5.квс
Normal file
86
тесты/циклы5.квс
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
переместить_имм р8, 2 ; число = 2
|
||||||
|
|
||||||
|
цикл:
|
||||||
|
; Если число < 10 — выводим как есть
|
||||||
|
сравнить_с р8, 10
|
||||||
|
переход_если_больше_или_равно двузначное
|
||||||
|
|
||||||
|
; Однозначное: просто цифра
|
||||||
|
переместить раикс, р8
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переход продолжение
|
||||||
|
|
||||||
|
двузначное:
|
||||||
|
; Делим на 10
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс ; rax = десятки, rdx = единицы
|
||||||
|
|
||||||
|
; Сохраняем единицы в .бнд (пока не испортились)
|
||||||
|
сохранить [остаток], рдикс
|
||||||
|
|
||||||
|
; Выводим десятки
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Загружаем единицы обратно
|
||||||
|
загрузить рдикс, [остаток]
|
||||||
|
|
||||||
|
; Выводим единицы
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [буфер], рдикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
продолжение:
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Прибавляем 2
|
||||||
|
прибавить_непосредственно р8, 2
|
||||||
|
|
||||||
|
; Продолжаем пока <= 99
|
||||||
|
сравнить_с р8, 99
|
||||||
|
переход_если_меньше цикл
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
буфер:
|
||||||
|
.байт 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
|
|
||||||
|
.бнд
|
||||||
|
остаток:
|
||||||
|
.резб 8
|
||||||
81
тесты/циклы6.квс
Normal file
81
тесты/циклы6.квс
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Тест: выводим длины чисел от 0 до 20
|
||||||
|
переместить_имм р8, 0 ; число = 0
|
||||||
|
|
||||||
|
цикл:
|
||||||
|
; Считаем длину числа
|
||||||
|
переместить раикс, р8
|
||||||
|
вызвать длина_числа
|
||||||
|
|
||||||
|
; Выводим длину как цифру
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Число++
|
||||||
|
увеличить р8
|
||||||
|
сравнить_с р8, 21 ; 0..20
|
||||||
|
переход_если_меньше цикл
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; =============================================
|
||||||
|
; длина_числа: количество десятичных цифр в rax
|
||||||
|
; Вход: rax = число
|
||||||
|
; Выход: rax = количество цифр
|
||||||
|
; =============================================
|
||||||
|
длина_числа:
|
||||||
|
втолкнуть р8
|
||||||
|
втолкнуть р9
|
||||||
|
|
||||||
|
переместить р8, раикс ; р8 = число
|
||||||
|
переместить_имм р9, 0 ; счётчик = 0
|
||||||
|
|
||||||
|
сравнить_с р8, 0
|
||||||
|
короткий_переход_если_неравно длина_цикл
|
||||||
|
|
||||||
|
переместить_имм раикс, 1 ; 0 = 1 цифра
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
длина_цикл:
|
||||||
|
увеличить р9
|
||||||
|
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс
|
||||||
|
переместить р8, раикс
|
||||||
|
|
||||||
|
сравнить_с р8, 0
|
||||||
|
короткий_переход_если_неравно длина_цикл
|
||||||
|
|
||||||
|
переместить раикс, р9
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
.данные
|
||||||
|
буфер:
|
||||||
|
.байт 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
138
тесты/циклы7.квс
Normal file
138
тесты/циклы7.квс
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
переместить_имм р8, 0 ; число = 0
|
||||||
|
|
||||||
|
цикл:
|
||||||
|
; Выводим число (костыльно: до 99)
|
||||||
|
сравнить_с р8, 10
|
||||||
|
переход_если_больше_или_равно двузначное
|
||||||
|
|
||||||
|
; Однозначное
|
||||||
|
переместить раикс, р8
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переход показать_длину
|
||||||
|
|
||||||
|
двузначное:
|
||||||
|
; Делим на 10
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс
|
||||||
|
|
||||||
|
сохранить [остаток], рдикс
|
||||||
|
|
||||||
|
; Десятки
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Единицы
|
||||||
|
загрузить рдикс, [остаток]
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
сохранить [буфер], рдикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
показать_длину:
|
||||||
|
; Разделитель: " -> "
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, стрелка
|
||||||
|
переместить_имм рдикс, 4
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Длина числа
|
||||||
|
переместить раикс, р8
|
||||||
|
вызвать длина_числа
|
||||||
|
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Число++
|
||||||
|
увеличить р8
|
||||||
|
сравнить_с р8, 9199
|
||||||
|
переход_если_меньше цикл
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; =============================================
|
||||||
|
; длина_числа
|
||||||
|
; =============================================
|
||||||
|
длина_числа:
|
||||||
|
втолкнуть р8
|
||||||
|
втолкнуть р9
|
||||||
|
|
||||||
|
переместить р8, раикс
|
||||||
|
переместить_имм р9, 0
|
||||||
|
|
||||||
|
сравнить_с р8, 0
|
||||||
|
короткий_переход_если_неравно длина_цикл
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
длина_цикл:
|
||||||
|
увеличить р9
|
||||||
|
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс
|
||||||
|
переместить р8, раикс
|
||||||
|
|
||||||
|
сравнить_с р8, 0
|
||||||
|
короткий_переход_если_неравно длина_цикл
|
||||||
|
|
||||||
|
переместить раикс, р9
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
.данные
|
||||||
|
буфер:
|
||||||
|
.байт 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
стрелка:
|
||||||
|
.строка " -> "
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
|
|
||||||
|
.бнд
|
||||||
|
остаток:
|
||||||
|
.резб 8
|
||||||
180
тесты/циклы8.квс
Normal file
180
тесты/циклы8.квс
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; МЕНЯЙ ЧИСЛО ЗДЕСЬ:
|
||||||
|
переместить_имм р8, 456777
|
||||||
|
|
||||||
|
; Выводим число через itoa3 (до 999!)
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдиай, буфер
|
||||||
|
вызвать itoa3
|
||||||
|
|
||||||
|
загрузить рсиай, [указатель]
|
||||||
|
загрузить рдикс, [длина]
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; " -> "
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, стрелка
|
||||||
|
переместить_имм рдикс, 4
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Длина числа
|
||||||
|
переместить раикс, р8
|
||||||
|
вызвать длина_числа
|
||||||
|
|
||||||
|
; Выводим длину
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; =============================================
|
||||||
|
; itoa3 — работает для чисел до 999
|
||||||
|
; =============================================
|
||||||
|
itoa3:
|
||||||
|
втолкнуть рбикс
|
||||||
|
втолкнуть р8
|
||||||
|
втолкнуть р9
|
||||||
|
|
||||||
|
переместить рбикс, рдиай
|
||||||
|
переместить р8, раикс
|
||||||
|
|
||||||
|
сравнить_с р8, 10
|
||||||
|
переход_если_меньше одна_цифра
|
||||||
|
сравнить_с р8, 100
|
||||||
|
переход_если_меньше две_цифры
|
||||||
|
|
||||||
|
; Три цифры
|
||||||
|
прибавить_непосредственно рбикс, 3
|
||||||
|
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм р9, 10
|
||||||
|
разделить р9
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
уменьшить рбикс
|
||||||
|
сохранить [рбикс], рдикс
|
||||||
|
|
||||||
|
переместить р8, раикс
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
разделить р9
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
уменьшить рбикс
|
||||||
|
сохранить [рбикс], рдикс
|
||||||
|
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
уменьшить рбикс
|
||||||
|
сохранить [рбикс], раикс
|
||||||
|
|
||||||
|
сохранить [указатель], рбикс
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
сохранить [длина], раикс
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вытолкнуть рбикс
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
две_цифры:
|
||||||
|
прибавить_непосредственно рбикс, 2
|
||||||
|
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм р9, 10
|
||||||
|
разделить р9
|
||||||
|
прибавить_непосредственно рдикс, 0x30
|
||||||
|
уменьшить рбикс
|
||||||
|
сохранить [рбикс], рдикс
|
||||||
|
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
уменьшить рбикс
|
||||||
|
сохранить [рбикс], раикс
|
||||||
|
|
||||||
|
сохранить [указатель], рбикс
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
сохранить [длина], раикс
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вытолкнуть рбикс
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
одна_цифра:
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [рбикс], раикс
|
||||||
|
сохранить [указатель], рбикс
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
сохранить [длина], раикс
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вытолкнуть рбикс
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
; =============================================
|
||||||
|
; длина_числа
|
||||||
|
; =============================================
|
||||||
|
длина_числа:
|
||||||
|
втолкнуть р8
|
||||||
|
втолкнуть р9
|
||||||
|
|
||||||
|
переместить р8, раикс
|
||||||
|
переместить_имм р9, 0
|
||||||
|
|
||||||
|
сравнить_с р8, 0
|
||||||
|
короткий_переход_если_неравно длина_цикл
|
||||||
|
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
длина_цикл:
|
||||||
|
увеличить р9
|
||||||
|
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс
|
||||||
|
переместить р8, раикс
|
||||||
|
|
||||||
|
сравнить_с р8, 0
|
||||||
|
короткий_переход_если_неравно длина_цикл
|
||||||
|
|
||||||
|
переместить раикс, р9
|
||||||
|
вытолкнуть р9
|
||||||
|
вытолкнуть р8
|
||||||
|
вернуться
|
||||||
|
|
||||||
|
.данные
|
||||||
|
буфер:
|
||||||
|
.байт 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
стрелка:
|
||||||
|
.строка " -> "
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
|
|
||||||
|
.бнд
|
||||||
|
указатель:
|
||||||
|
.резб 8
|
||||||
|
длина:
|
||||||
|
.резб 8
|
||||||
77
тесты/циклы9.квс
Normal file
77
тесты/циклы9.квс
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; МЕНЯЙ ЧИСЛО:
|
||||||
|
переместить_имм р8, 750
|
||||||
|
|
||||||
|
; Выводим число (костыльно: делим на 100, потом на 10)
|
||||||
|
сравнить_с р8, 100
|
||||||
|
переход_если_меньше меньше_100
|
||||||
|
|
||||||
|
; >= 100: делим на 100
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 100
|
||||||
|
разделить рсикс ; rax = сотни, rdx = остаток
|
||||||
|
|
||||||
|
; Выводим сотни
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Остаток — продолжаем
|
||||||
|
переместить р8, рдикс
|
||||||
|
|
||||||
|
меньше_100:
|
||||||
|
; Делим на 10
|
||||||
|
сравнить_с р8, 10
|
||||||
|
переход_если_меньше меньше_10
|
||||||
|
|
||||||
|
переместить раикс, р8
|
||||||
|
переместить_имм рдикс, 0
|
||||||
|
переместить_имм рсикс, 10
|
||||||
|
разделить рсикс
|
||||||
|
|
||||||
|
; Выводим десятки
|
||||||
|
прибавить_непосредственно раикс, 0x30
|
||||||
|
сохранить [буфер], раикс
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
переместить р8, рдикс
|
||||||
|
|
||||||
|
меньше_10:
|
||||||
|
; Выводим единицы
|
||||||
|
прибавить_непосредственно р8, 0x30
|
||||||
|
сохранить [буфер], р8
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, буфер
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Перевод строки
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, nl
|
||||||
|
переместить_имм рдикс, 1
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; exit(0)
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
буфер:
|
||||||
|
.байт 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
nl:
|
||||||
|
.байт 0x0A
|
||||||
Loading…
Reference in a new issue