Add files via upload
This commit is contained in:
parent
9b7fe09c76
commit
d8184def66
160
jumps/csvhtml.py
Normal file
160
jumps/csvhtml.py
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import filedialog, messagebox
|
||||||
|
import csv
|
||||||
|
import os
|
||||||
|
|
||||||
|
# --- Основная функция конвертации ---
|
||||||
|
def convert_csv_to_html(csv_file_path, html_file_path):
|
||||||
|
"""
|
||||||
|
Читает semicolon-separated CSV файл и создает красивую HTML-страницу.
|
||||||
|
Возвращает (True, сообщение) в случае успеха или (False, сообщение) в случае ошибки.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with open(csv_file_path, 'r', encoding='utf-8') as f:
|
||||||
|
reader = csv.DictReader(f, delimiter=';')
|
||||||
|
headers = reader.fieldnames
|
||||||
|
if not headers:
|
||||||
|
return False, "CSV-файл пуст или не имеет заголовков."
|
||||||
|
|
||||||
|
rows = list(reader)
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
return False, f"Файл не найден: {csv_file_path}"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"Ошибка при чтении CSV: {e}"
|
||||||
|
|
||||||
|
# CSS для красивого оформления
|
||||||
|
css_style = """
|
||||||
|
<style>
|
||||||
|
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background-color: #f4f7f6; color: #333; margin: 0; padding: 20px; }
|
||||||
|
.container { max-width: 1400px; margin: 20px auto; background-color: #fff; padding: 25px; border-radius: 8px; box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); }
|
||||||
|
h1 { color: #2c3e50; text-align: center; margin-bottom: 25px; }
|
||||||
|
table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
||||||
|
th, td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #e0e0e0; vertical-align: top; word-wrap: break-word; }
|
||||||
|
th { background-color: #34495e; color: #ffffff; font-weight: 600; text-transform: uppercase; font-size: 13px; }
|
||||||
|
tr:nth-child(even) { background-color: #f8f9fa; }
|
||||||
|
tr:hover { background-color: #e9ecef; }
|
||||||
|
a { color: #3498db; text-decoration: none; font-weight: bold; }
|
||||||
|
a:hover { text-decoration: underline; color: #2980b9; }
|
||||||
|
.mono { font-family: 'Courier New', Courier, monospace; font-size: 13px; white-space: pre-wrap; }
|
||||||
|
tr:target { background-color: #fff3cd !important; border: 2px solid #ffeaa7; animation: highlight 2s ease-in-out; }
|
||||||
|
@keyframes highlight { from { background-color: #ffeaa7; } to { background-color: #fff3cd; } }
|
||||||
|
</style>
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Начало HTML-документа
|
||||||
|
html_content = f"""
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{os.path.basename(html_file_path)}</title>
|
||||||
|
{css_style}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Анализ дизассемблерного листинга: {os.path.basename(csv_file_path)}</h1>
|
||||||
|
<table>
|
||||||
|
<thead><tr>
|
||||||
|
"""
|
||||||
|
for header in headers:
|
||||||
|
html_content += f"<th>{header}</th>\n"
|
||||||
|
|
||||||
|
html_content += "</tr></thead><tbody>\n"
|
||||||
|
|
||||||
|
# Добавляем строки таблицы
|
||||||
|
for row in rows:
|
||||||
|
address = row.get('адрес', '').strip()
|
||||||
|
target_address = row.get('целевой_адрес', '').strip()
|
||||||
|
|
||||||
|
link_html = target_address
|
||||||
|
if target_address:
|
||||||
|
link_html = f'<a href="#{target_address}">{target_address}</a>'
|
||||||
|
|
||||||
|
# Присваиваем id каждой строке на основе ее адреса
|
||||||
|
row_id = address if address else ''
|
||||||
|
|
||||||
|
html_content += f'<tr id="{row_id}">\n'
|
||||||
|
html_content += f'<td class="mono">{address}</td>\n'
|
||||||
|
html_content += f'<td class="mono">{row.get("байт", "")}</td>\n'
|
||||||
|
html_content += f'<td class="mono">{link_html}</td>\n'
|
||||||
|
html_content += f'<td>{row.get("исходная_команда", "")}</td>\n'
|
||||||
|
html_content += "</tr>\n"
|
||||||
|
|
||||||
|
html_content += "</tbody></table></div></body></html>"
|
||||||
|
|
||||||
|
# Запись HTML в файл
|
||||||
|
try:
|
||||||
|
with open(html_file_path, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(html_content)
|
||||||
|
return True, f"Успешно! Файл сохранен как:\n{html_file_path}"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"Ошибка при записи HTML файла: {e}"
|
||||||
|
|
||||||
|
|
||||||
|
# --- Функция-обработчик нажатия на кнопку ---
|
||||||
|
def open_file_and_convert():
|
||||||
|
# Открываем диалог выбора файла
|
||||||
|
file_path = filedialog.askopenfilename(
|
||||||
|
title="Выберите CSV-файл для конвертации",
|
||||||
|
filetypes=(("CSV файлы", "*.csv"), ("Все файлы", "*.*"))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Если пользователь не выбрал файл, выходим
|
||||||
|
if not file_path:
|
||||||
|
status_label.config(text="Операция отменена.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Формируем имя для выходного HTML-файла
|
||||||
|
base_name = os.path.splitext(file_path)[0]
|
||||||
|
output_path = f"{base_name}.html"
|
||||||
|
|
||||||
|
# Обновляем статус
|
||||||
|
status_label.config(text="Обработка файла...")
|
||||||
|
root.update_idletasks() # Принудительно обновляем интерфейс
|
||||||
|
|
||||||
|
# Вызываем функцию конвертации
|
||||||
|
success, message = convert_csv_to_html(file_path, output_path)
|
||||||
|
|
||||||
|
# Показываем результат
|
||||||
|
if success:
|
||||||
|
status_label.config(text="Готово!")
|
||||||
|
messagebox.showinfo("Успех", message)
|
||||||
|
else:
|
||||||
|
status_label.config(text="Произошла ошибка.")
|
||||||
|
messagebox.showerror("Ошибка", message)
|
||||||
|
|
||||||
|
|
||||||
|
# --- Создание графического интерфейса ---
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("CSV в HTML Конвертер")
|
||||||
|
root.geometry("450x200") # Размер окна
|
||||||
|
root.resizable(False, False) # Запрещаем изменять размер
|
||||||
|
|
||||||
|
# Создаем фрейм для лучшего расположения элементов
|
||||||
|
main_frame = tk.Frame(root, padx=20, pady=20)
|
||||||
|
main_frame.pack(expand=True, fill=tk.BOTH)
|
||||||
|
|
||||||
|
# Кнопка "Открыть"
|
||||||
|
open_button = tk.Button(
|
||||||
|
main_frame,
|
||||||
|
text="Открыть CSV-файл",
|
||||||
|
command=open_file_and_convert,
|
||||||
|
width=20,
|
||||||
|
height=2,
|
||||||
|
font=("Helvetica", 12)
|
||||||
|
)
|
||||||
|
open_button.pack(pady=10)
|
||||||
|
|
||||||
|
# Метка для отображения статуса
|
||||||
|
status_label = tk.Label(
|
||||||
|
main_frame,
|
||||||
|
text="Нажмите кнопку, чтобы выбрать файл",
|
||||||
|
wraplength=400, # Перенос длинных строк
|
||||||
|
justify=tk.CENTER
|
||||||
|
)
|
||||||
|
status_label.pack(pady=10)
|
||||||
|
|
||||||
|
# Запускаем главный цикл приложения
|
||||||
|
root.mainloop()
|
||||||
149
jumps/disassembler_skip_zero2.py
Normal file
149
jumps/disassembler_skip_zero2.py
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import filedialog, messagebox
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def binary_to_disasm(input_file, output_file=None, skip_zeros=True):
|
||||||
|
"""Конвертирует бинарный файл в дизассемблированный код с помощью ndisasm."""
|
||||||
|
try:
|
||||||
|
# Если выходной файл не указан, создаём рядом с оригиналом
|
||||||
|
if not output_file:
|
||||||
|
base_name = os.path.splitext(input_file)[0]
|
||||||
|
output_file = f"{base_name}_disasm.txt"
|
||||||
|
|
||||||
|
# Вызываем ndisasm для дизассемблирования
|
||||||
|
result = subprocess.run(
|
||||||
|
['ndisasm', '-b64', input_file],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Проверяем наличие ошибок от ndisasm
|
||||||
|
if result.returncode != 0:
|
||||||
|
error_msg = result.stderr.strip()
|
||||||
|
return False, f"Ошибка ndisasm: {error_msg}"
|
||||||
|
|
||||||
|
# Получаем текущую дату и время
|
||||||
|
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
# Фильтруем строки в зависимости от настройки
|
||||||
|
lines = result.stdout.splitlines()
|
||||||
|
if skip_zeros:
|
||||||
|
filtered_lines = [line for line in lines if 'add [rax],al' not in line]
|
||||||
|
filter_status = "Нули (add [rax],al) пропущены"
|
||||||
|
else:
|
||||||
|
filtered_lines = lines
|
||||||
|
filter_status = "Нули (add [rax],al) не пропущены"
|
||||||
|
|
||||||
|
# Записываем отфильтрованные строки в файл с заголовком
|
||||||
|
with open(output_file, 'w', encoding='utf-8') as out_file:
|
||||||
|
# Добавляем заголовок с информацией
|
||||||
|
out_file.write("=" * 60 + "\n")
|
||||||
|
out_file.write(f"Дизассемблированный код сгенерирован с помощью ndisasm\n")
|
||||||
|
out_file.write(f"Исходный файл: {os.path.basename(input_file)}\n")
|
||||||
|
out_file.write(f"Дата создания: {current_time}\n")
|
||||||
|
out_file.write(f"Статус фильтра: {filter_status}\n")
|
||||||
|
out_file.write("=" * 60 + "\n\n")
|
||||||
|
|
||||||
|
for line in filtered_lines:
|
||||||
|
out_file.write(line + '\n')
|
||||||
|
|
||||||
|
return True, output_file
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
return False, "ndisasm не найден. Убедитесь, что NASM установлен и доступен в PATH"
|
||||||
|
except Exception as e:
|
||||||
|
return False, str(e)
|
||||||
|
|
||||||
|
def select_and_convert():
|
||||||
|
"""Открывает диалог выбора файла и конвертирует"""
|
||||||
|
input_file = filedialog.askopenfilename(
|
||||||
|
title="Выберите бинарный файл",
|
||||||
|
filetypes=(("Бинарные файлы", "*.bin *.elf *.o"), ("Все файлы", "*.*"))
|
||||||
|
)
|
||||||
|
|
||||||
|
if not input_file:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Получаем состояние галочки
|
||||||
|
skip_zeros = skip_zeros_var.get()
|
||||||
|
|
||||||
|
success, result = binary_to_disasm(input_file, skip_zeros=skip_zeros)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
messagebox.showinfo(
|
||||||
|
"Готово",
|
||||||
|
f"Файл успешно дизассемблирован!\n"
|
||||||
|
f"Пропуск нулей: {'ВКЛ' if skip_zeros else 'ВЫКЛ'}\n"
|
||||||
|
f"Результат сохранён как:\n{result}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
messagebox.showerror(
|
||||||
|
"Ошибка",
|
||||||
|
f"Не удалось дизассемблировать файл:\n{result}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Создаём графический интерфейс"""
|
||||||
|
global skip_zeros_var
|
||||||
|
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("Дизассемблер бинарных файлов")
|
||||||
|
root.geometry("500x250")
|
||||||
|
|
||||||
|
# Центрируем окно
|
||||||
|
root.eval('tk::PlaceWindow . center')
|
||||||
|
|
||||||
|
# Переменная для хранения состояния галочки
|
||||||
|
skip_zeros_var = tk.BooleanVar(value=True) # По умолчанию включено
|
||||||
|
|
||||||
|
# Создаём элементы интерфейса
|
||||||
|
label = tk.Label(
|
||||||
|
root,
|
||||||
|
text="Дизассемблер бинарных файлов (ndisasm)",
|
||||||
|
font=('Arial', 14),
|
||||||
|
pady=20
|
||||||
|
)
|
||||||
|
label.pack()
|
||||||
|
|
||||||
|
# Фрейм для галочки
|
||||||
|
checkbox_frame = tk.Frame(root)
|
||||||
|
checkbox_frame.pack(pady=10)
|
||||||
|
|
||||||
|
# Галочка для пропуска нулей
|
||||||
|
skip_zeros_check = tk.Checkbutton(
|
||||||
|
checkbox_frame,
|
||||||
|
text="Пропускать нули (add [rax],al)",
|
||||||
|
variable=skip_zeros_var,
|
||||||
|
font=('Arial', 10)
|
||||||
|
)
|
||||||
|
skip_zeros_check.pack()
|
||||||
|
|
||||||
|
# Кнопка конвертации
|
||||||
|
btn_convert = tk.Button(
|
||||||
|
root,
|
||||||
|
text="Выбрать файл и дизассемблировать",
|
||||||
|
command=select_and_convert,
|
||||||
|
font=('Arial', 12),
|
||||||
|
padx=20,
|
||||||
|
pady=10
|
||||||
|
)
|
||||||
|
btn_convert.pack(pady=10)
|
||||||
|
|
||||||
|
# Кнопка выхода
|
||||||
|
btn_exit = tk.Button(
|
||||||
|
root,
|
||||||
|
text="Выход",
|
||||||
|
command=root.quit,
|
||||||
|
font=('Arial', 10),
|
||||||
|
padx=20,
|
||||||
|
pady=5
|
||||||
|
)
|
||||||
|
btn_exit.pack(pady=10)
|
||||||
|
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
653
jumps/kvs_5.py
Normal file
653
jumps/kvs_5.py
Normal file
|
|
@ -0,0 +1,653 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
kvs_5.py
|
||||||
|
КВС - язык программирования
|
||||||
|
без использования re
|
||||||
|
(расширенная версия с короткими переходами и полными регистрами)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# Глобальная переменная для имени исходного файла
|
||||||
|
source_filename = ""
|
||||||
|
|
||||||
|
def safe_close(f):
|
||||||
|
if f is not None:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# === Глобальные данные ===
|
||||||
|
INSTRUCTIONS = {
|
||||||
|
"переместить_имм": {"code": None, "type": "reg_imm"},
|
||||||
|
"сравнить_с": {"code": None, "type": "cmp_reg_imm"},
|
||||||
|
"переход_если_неравно": {"code": b"\x0F\x85", "type": "jcc"},
|
||||||
|
"вызов_системы": {"code": b"\x0F\x05", "type": "none"},
|
||||||
|
"переход": {"code": b"\xE9", "type": "jmp"},
|
||||||
|
# === Короткие переходы (добавлено) ===
|
||||||
|
"короткий_переход": {"code": b"\xEB", "type": "short_jmp"},
|
||||||
|
"короткий_переход_если_равно" : {"code": b"\x74", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_неравно" : {"code": b"\x75", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_меньше" : {"code": b"\x7C", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_больше" : {"code": b"\x7F", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_меньше_или_равно": {"code": b"\x7E", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_больше_или_равно": {"code": b"\x7D", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_перенос" : {"code": b"\x72", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_нет_переноса" : {"code": b"\x73", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_ноль" : {"code": b"\x74", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_не_ноль" : {"code": b"\x75", "type": "short_jcc"},
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTERS = {
|
||||||
|
# 64-битные
|
||||||
|
"раикс": 0, "рсикс": 1, "рдикс": 2, "рбикс": 3,
|
||||||
|
"рсипи": 4, "рбипи": 5, "рсиай": 6, "рдиай": 7,
|
||||||
|
"р8": 8, "р9": 9, "р10": 10, "р11": 11,
|
||||||
|
"р12": 12, "р13": 13, "р14": 14, "р15": 15,
|
||||||
|
# 32-битные
|
||||||
|
"еаикс": 0, "есикс": 1, "едикс": 2, "ебикс": 3,
|
||||||
|
"есипи": 4, "ебипи": 5, "есиай": 6, "едиай": 7,
|
||||||
|
"р8д": 8, "р9д": 9, "р10д": 10, "р11д": 11,
|
||||||
|
"р12д": 12, "р13д": 13, "р14д": 14, "р15д": 15,
|
||||||
|
# 16-битные
|
||||||
|
"аикс": 0, "сикс": 1, "дикс": 2, "бикс": 3,
|
||||||
|
"эсп": 4, "бипи": 5, "эс": 6, "ди": 7,
|
||||||
|
"р8в": 8, "р9в": 9, "р10в": 10, "р11в": 11,
|
||||||
|
"р12в": 12, "р13в": 13, "р14в": 14, "р15в": 15,
|
||||||
|
# 8-битные младшие
|
||||||
|
"ал": 0, "кл": 1, "дл": 2, "бл": 3,
|
||||||
|
"спл": 4, "бпл": 5, "сил": 6, "дил": 7,
|
||||||
|
"р8б": 8, "р9б": 9, "р10б": 10, "р11б": 11,
|
||||||
|
"р12б": 12, "р13б": 13, "р14б": 14, "р15б": 15,
|
||||||
|
# 8-битные старшие (только первые 4)
|
||||||
|
"аш": 0, "чш": 1, "дш": 2, "бш": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Глобальное состояние ассемблера
|
||||||
|
labels = {}
|
||||||
|
label_sections = {}
|
||||||
|
symbols = {}
|
||||||
|
sections = {".text": bytearray(), ".data": bytearray()}
|
||||||
|
current_section = ".text"
|
||||||
|
entry_point = "_start"
|
||||||
|
position = {".text": 0, ".data": 0}
|
||||||
|
pass_num = 0
|
||||||
|
|
||||||
|
# === Для логирования ===
|
||||||
|
log_entries = []
|
||||||
|
|
||||||
|
# === ELF layout ===
|
||||||
|
PAGE_SIZE = 0x1000
|
||||||
|
elf_base_vaddr = 0x400000
|
||||||
|
text_vaddr_base = 0x401000
|
||||||
|
data_vaddr_base = 0x402000
|
||||||
|
|
||||||
|
text_size = 0
|
||||||
|
data_size = 0
|
||||||
|
comment_size = 0
|
||||||
|
offset_text = 0
|
||||||
|
offset_data = 0
|
||||||
|
offset_comment = 0
|
||||||
|
shstrtab_offset = 0
|
||||||
|
shdr_offset = 0
|
||||||
|
vaddr_text = 0
|
||||||
|
vaddr_data = 0
|
||||||
|
|
||||||
|
def align_up(x, align):
|
||||||
|
return (x + align - 1) & ~(align - 1)
|
||||||
|
|
||||||
|
def get_reg_info(reg_name):
|
||||||
|
if reg_name in ["аш", "чш", "дш", "бш"]:
|
||||||
|
return {"size": 8, "index": REGISTERS[reg_name], "high8": True}
|
||||||
|
elif reg_name.endswith(("б", "л")) or reg_name in ["ал", "кл", "дл", "бл", "спл", "бпл", "сил", "дил"]:
|
||||||
|
return {"size": 8, "index": REGISTERS[reg_name], "high8": False}
|
||||||
|
elif reg_name.endswith("в") or reg_name in ["аикс", "сикс", "дикс", "бикс", "эсп", "бипи", "эс", "ди"]:
|
||||||
|
return {"size": 16, "index": REGISTERS[reg_name]}
|
||||||
|
elif reg_name.endswith("д") or reg_name in ["еаикс", "есикс", "едикс", "ебикс", "есипи", "ебипи", "есиай", "едиай"]:
|
||||||
|
return {"size": 32, "index": REGISTERS[reg_name]}
|
||||||
|
else:
|
||||||
|
return {"size": 64, "index": REGISTERS[reg_name]}
|
||||||
|
|
||||||
|
# === Функции формирования ошибок ===
|
||||||
|
def make_error_msg(line_num, line_text, detail):
|
||||||
|
return "Ошибка в файле " + source_filename + ", строка " + str(line_num) + ":\n " + line_text + "\n" + detail
|
||||||
|
|
||||||
|
def error_invalid_operand_count(mnemonic, expected, got):
|
||||||
|
return "Инструкция '" + mnemonic + "':\n ожидается " + str(expected) + " операнд(а/ов), получено: " + str(got)
|
||||||
|
|
||||||
|
def error_unknown_mnemonic(mnemonic):
|
||||||
|
return "Неизвестная инструкция: '" + mnemonic + "'"
|
||||||
|
|
||||||
|
def error_invalid_register(op_name, reg_name, mnemonic):
|
||||||
|
return ("Инструкция '" + mnemonic + "':\n операнд '" + op_name + "' = '" + reg_name +
|
||||||
|
"' не является допустимым регистром.\n Допустимые регистры: " + ", ".join(list(REGISTERS.keys())))
|
||||||
|
|
||||||
|
def error_invalid_number_format(s):
|
||||||
|
return "Недопустимый формат числа: '" + s + "'"
|
||||||
|
|
||||||
|
def error_unknown_directive(word):
|
||||||
|
return "Неизвестная директива: '" + word + "'"
|
||||||
|
|
||||||
|
def error_missing_label(label):
|
||||||
|
return "Метка не найдена: '" + label + "'"
|
||||||
|
|
||||||
|
def error_unexpected_string_in_byte():
|
||||||
|
return ".байт требует числовые значения, не строки"
|
||||||
|
|
||||||
|
def error_unterminated_string():
|
||||||
|
return "Незакрытая кавычка в строке"
|
||||||
|
|
||||||
|
# === Лексер ===
|
||||||
|
def tokenize_line(line):
|
||||||
|
semi = line.find(';')
|
||||||
|
if semi != -1:
|
||||||
|
line = line[:semi]
|
||||||
|
line = line.rstrip()
|
||||||
|
if not line:
|
||||||
|
return []
|
||||||
|
tokens = []
|
||||||
|
i = 0
|
||||||
|
n = len(line)
|
||||||
|
while i < n:
|
||||||
|
ch = line[i]
|
||||||
|
if ch.isspace():
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if ch == '"':
|
||||||
|
i += 1
|
||||||
|
s = ''
|
||||||
|
while i < n and line[i] != '"':
|
||||||
|
if line[i] == '\\' and i + 1 < n:
|
||||||
|
i += 1
|
||||||
|
esc = line[i]
|
||||||
|
if esc == 'n':
|
||||||
|
s += '\n'
|
||||||
|
elif esc == 't':
|
||||||
|
s += '\t'
|
||||||
|
elif esc == '"':
|
||||||
|
s += '"'
|
||||||
|
elif esc == '\\':
|
||||||
|
s += '\\'
|
||||||
|
else:
|
||||||
|
s += '\\' + esc
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
s += line[i]
|
||||||
|
i += 1
|
||||||
|
if i >= n:
|
||||||
|
raise ValueError(error_unterminated_string())
|
||||||
|
i += 1
|
||||||
|
tokens.append(('string', s))
|
||||||
|
continue
|
||||||
|
if ch == ',':
|
||||||
|
tokens.append(('comma', ','))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if ch == ':':
|
||||||
|
tokens.append(('colon', ':'))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
j = i
|
||||||
|
while j < n and not (line[j].isspace() or line[j] in ',:;'):
|
||||||
|
j += 1
|
||||||
|
word = line[i:j]
|
||||||
|
if word:
|
||||||
|
tokens.append(('word', word))
|
||||||
|
i = j
|
||||||
|
return tokens
|
||||||
|
|
||||||
|
# === Парсинг ===
|
||||||
|
def parse_operand(operand):
|
||||||
|
if operand.isdigit():
|
||||||
|
return int(operand)
|
||||||
|
if operand.startswith("0x"):
|
||||||
|
return int(operand, 16)
|
||||||
|
if operand in labels:
|
||||||
|
section = label_sections[operand]
|
||||||
|
if pass_num == 2:
|
||||||
|
base = vaddr_text if section == ".text" else vaddr_data
|
||||||
|
return labels[operand] + base
|
||||||
|
else:
|
||||||
|
return labels[operand]
|
||||||
|
if operand in symbols:
|
||||||
|
return symbols[operand]
|
||||||
|
raise ValueError("Неизвестный операнд: " + operand)
|
||||||
|
|
||||||
|
def encode_instruction(mnemonic, operands, line_num, line_text):
|
||||||
|
instr = INSTRUCTIONS[mnemonic]
|
||||||
|
code = bytearray()
|
||||||
|
itype = instr["type"]
|
||||||
|
|
||||||
|
if itype == "none":
|
||||||
|
code.extend(instr["code"])
|
||||||
|
|
||||||
|
elif itype == "reg_imm":
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("назначения", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
imm = parse_operand(operands[1])
|
||||||
|
|
||||||
|
if 0 <= reg <= 7:
|
||||||
|
code.extend(b'\x48')
|
||||||
|
code.append(0xB8 + reg)
|
||||||
|
code.extend(struct.pack('<Q', imm))
|
||||||
|
elif 8 <= reg <= 15:
|
||||||
|
code.extend(b'\x49')
|
||||||
|
code.append(0xB8 + (reg - 8))
|
||||||
|
code.extend(struct.pack('<Q', imm))
|
||||||
|
else:
|
||||||
|
raise ValueError("Недопустимый регистр в '" + mnemonic + "'")
|
||||||
|
|
||||||
|
elif itype == "cmp_reg_imm":
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("регистра", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
imm = parse_operand(operands[1])
|
||||||
|
|
||||||
|
if -0x80000000 <= imm <= 0x7FFFFFFF:
|
||||||
|
rex = 0x48
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x81)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.extend(struct.pack('<i', imm))
|
||||||
|
else:
|
||||||
|
raise ValueError("Непосредственное значение слишком велико для сравнения: " + str(imm))
|
||||||
|
|
||||||
|
elif itype == "jmp":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 5)
|
||||||
|
if offset < -0x80000000 or offset > 0x7FFFFFFF:
|
||||||
|
raise ValueError("Цель слишком далеко для 32-битного смещения в инструкции '" + mnemonic + "': " + str(offset))
|
||||||
|
code.extend(struct.pack('<i', offset))
|
||||||
|
|
||||||
|
elif itype == "jcc":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 6)
|
||||||
|
if offset < -0x80000000 or offset > 0x7FFFFFFF:
|
||||||
|
raise ValueError("Цель условного перехода слишком далеко: " + str(offset))
|
||||||
|
code.extend(struct.pack('<i', offset))
|
||||||
|
|
||||||
|
# === НОВОЕ: короткие переходы ===
|
||||||
|
elif itype == "short_jmp":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 2)
|
||||||
|
if offset < -128 or offset > 127:
|
||||||
|
raise ValueError("Цель слишком далеко для короткого перехода: " + str(offset))
|
||||||
|
code.append(0xEB)
|
||||||
|
code.append(offset & 0xFF)
|
||||||
|
|
||||||
|
elif itype == "short_jcc":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 2)
|
||||||
|
if offset < -128 or offset > 127:
|
||||||
|
raise ValueError("Цель слишком далеко для короткого условного перехода: " + str(offset))
|
||||||
|
code.append(offset & 0xFF)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError("Неизвестный тип инструкции: " + itype)
|
||||||
|
|
||||||
|
return bytes(code)
|
||||||
|
|
||||||
|
def parse_instruction_or_directive(tokens, line_num, line_text):
|
||||||
|
global current_section, entry_point
|
||||||
|
first = tokens[0]
|
||||||
|
if first[0] != 'word':
|
||||||
|
raise ValueError("Ожидалось слово, получено: " + str(first))
|
||||||
|
word = first[1]
|
||||||
|
if word.startswith('.'):
|
||||||
|
if word == '.текст':
|
||||||
|
current_section = ".text"
|
||||||
|
elif word == '.данные':
|
||||||
|
current_section = ".data"
|
||||||
|
elif word == '.глобал':
|
||||||
|
if len(tokens) < 2 or tokens[1][0] != 'word':
|
||||||
|
raise ValueError(".глобал требует имя метки")
|
||||||
|
entry_point = tokens[1][1]
|
||||||
|
elif word == '.строка_нуль' or word == '.строка':
|
||||||
|
if len(tokens) < 2 or tokens[1][0] != 'string':
|
||||||
|
raise ValueError(word + " требует строку в кавычках")
|
||||||
|
if current_section != ".data":
|
||||||
|
raise ValueError("Строки разрешены только в секции .data")
|
||||||
|
s = tokens[1][1]
|
||||||
|
bstring = s.encode('utf-8')
|
||||||
|
add_null = (word == '.строка_нуль')
|
||||||
|
size = len(bstring) + (1 if add_null else 0)
|
||||||
|
if pass_num == 1:
|
||||||
|
position[".data"] += size
|
||||||
|
elif pass_num == 2:
|
||||||
|
sections[".data"] += bstring
|
||||||
|
if add_null:
|
||||||
|
sections[".data"] += b'\x00'
|
||||||
|
position[".data"] += size
|
||||||
|
else:
|
||||||
|
raise ValueError(error_unknown_directive(word))
|
||||||
|
return
|
||||||
|
|
||||||
|
mnemonic = word
|
||||||
|
if mnemonic not in INSTRUCTIONS:
|
||||||
|
raise ValueError(error_unknown_mnemonic(mnemonic))
|
||||||
|
|
||||||
|
operands = []
|
||||||
|
for tok in tokens[1:]:
|
||||||
|
if tok[0] == 'word':
|
||||||
|
operands.append(tok[1])
|
||||||
|
elif tok[0] == 'comma':
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raise ValueError("Недопустимый токен в операндах: " + str(tok))
|
||||||
|
|
||||||
|
if pass_num == 2:
|
||||||
|
instr_info = INSTRUCTIONS[mnemonic]
|
||||||
|
itype = instr_info["type"]
|
||||||
|
code = encode_instruction(mnemonic, operands, line_num, line_text)
|
||||||
|
start_pos = position[current_section]
|
||||||
|
|
||||||
|
if current_section == ".text":
|
||||||
|
start_vaddr = vaddr_text + start_pos
|
||||||
|
target_addr = ""
|
||||||
|
try:
|
||||||
|
if itype in ("jmp", "jcc", "short_jmp", "short_jcc"):
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
target_addr = hex(target)
|
||||||
|
elif itype == "reg_imm":
|
||||||
|
op_str = operands[1]
|
||||||
|
if op_str in labels:
|
||||||
|
sec = label_sections[op_str]
|
||||||
|
addr = labels[op_str] + (vaddr_text if sec == ".text" else vaddr_data)
|
||||||
|
target_addr = hex(addr)
|
||||||
|
except Exception:
|
||||||
|
target_addr = "ошибка"
|
||||||
|
|
||||||
|
original_cmd = line_text.split(';')[0].strip()
|
||||||
|
for i, byte in enumerate(code):
|
||||||
|
addr = start_vaddr + i
|
||||||
|
byte_hex = "{:02X}".format(byte)
|
||||||
|
cmd_to_log = original_cmd if i == 0 else ""
|
||||||
|
log_entries.append((hex(addr), byte_hex, target_addr if i == 0 else "", cmd_to_log))
|
||||||
|
|
||||||
|
sections[current_section] += code
|
||||||
|
position[current_section] += len(code)
|
||||||
|
else:
|
||||||
|
instr_info = INSTRUCTIONS[mnemonic]
|
||||||
|
itype = instr_info["type"]
|
||||||
|
size_map = {
|
||||||
|
"reg_imm": 10,
|
||||||
|
"cmp_reg_imm": 7,
|
||||||
|
"jmp": 5,
|
||||||
|
"jcc": 6,
|
||||||
|
"none": lambda: len(instr_info["code"]),
|
||||||
|
"short_jmp": 2,
|
||||||
|
"short_jcc": 2,
|
||||||
|
}
|
||||||
|
if itype in size_map:
|
||||||
|
sz = size_map[itype]
|
||||||
|
position[current_section] += sz() if callable(sz) else sz
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый тип инструкции при подсчёте размера: " + itype)
|
||||||
|
|
||||||
|
def parse_tokens(tokens, line_num, line_text):
|
||||||
|
if not tokens:
|
||||||
|
return
|
||||||
|
if len(tokens) >= 2 and tokens[0][0] == 'word' and tokens[1][0] == 'colon':
|
||||||
|
label = tokens[0][1]
|
||||||
|
labels[label] = position[current_section]
|
||||||
|
label_sections[label] = current_section
|
||||||
|
rest = tokens[2:]
|
||||||
|
if rest:
|
||||||
|
parse_instruction_or_directive(rest, line_num, line_text)
|
||||||
|
return
|
||||||
|
parse_instruction_or_directive(tokens, line_num, line_text)
|
||||||
|
|
||||||
|
def parse(source):
|
||||||
|
global pass_num, text_size, data_size, comment_size
|
||||||
|
global offset_text, offset_data, offset_comment, shstrtab_offset, shdr_offset
|
||||||
|
global vaddr_text, vaddr_data
|
||||||
|
global sections, position, log_entries
|
||||||
|
|
||||||
|
log_entries = []
|
||||||
|
lines = source.split('\n')
|
||||||
|
|
||||||
|
# ПРОХОД 1
|
||||||
|
pass_num = 1
|
||||||
|
position[".text"] = 0
|
||||||
|
position[".data"] = 0
|
||||||
|
labels.clear()
|
||||||
|
label_sections.clear()
|
||||||
|
|
||||||
|
for line_num, line in enumerate(lines, start=1):
|
||||||
|
original_line = line.rstrip()
|
||||||
|
try:
|
||||||
|
tokens = tokenize_line(line)
|
||||||
|
parse_tokens(tokens, line_num, original_line)
|
||||||
|
except Exception as e:
|
||||||
|
error_full = make_error_msg(line_num, original_line, str(e))
|
||||||
|
print(error_full, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
text_size_pass1 = position[".text"]
|
||||||
|
data_size_pass1 = position[".data"]
|
||||||
|
print("ПРОХОД 1: text_size=" + str(text_size_pass1) + " bytes, data_size=" + str(data_size_pass1) + " bytes")
|
||||||
|
|
||||||
|
# РАЗМЕЩЕНИЕ
|
||||||
|
elf_header_size = 64
|
||||||
|
ph_size = 56
|
||||||
|
ph_num = 3
|
||||||
|
ph_table_size = ph_num * ph_size
|
||||||
|
|
||||||
|
offset_text = align_up(elf_header_size + ph_table_size, PAGE_SIZE)
|
||||||
|
offset_data = align_up(offset_text + text_size_pass1, PAGE_SIZE)
|
||||||
|
vaddr_text = text_vaddr_base
|
||||||
|
vaddr_data = align_up(vaddr_text + text_size_pass1, PAGE_SIZE)
|
||||||
|
|
||||||
|
comment_content = "Сборщик КВС".encode('utf-8') + b'\x00'
|
||||||
|
comment_size = len(comment_content)
|
||||||
|
offset_comment = align_up(offset_data + data_size_pass1, 1)
|
||||||
|
|
||||||
|
shstrtab_content = b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00"
|
||||||
|
shstrtab_size = len(shstrtab_content)
|
||||||
|
shstrtab_offset = align_up(offset_comment + comment_size, 8)
|
||||||
|
shdr_size = 64
|
||||||
|
shdr_num = 5
|
||||||
|
shdr_offset = align_up(shstrtab_offset + shstrtab_size, 16)
|
||||||
|
|
||||||
|
print("РАЗМЕЩЕНИЕ: .text at offset=" + hex(offset_text) + ", .data at offset=" + hex(offset_data))
|
||||||
|
print("ВИРТУАЛЬНЫЕ АДРЕСА: .text at " + hex(vaddr_text) + ", .data at " + hex(vaddr_data))
|
||||||
|
print("РАССТОЯНИЕ МЕЖДУ СЕКЦИЯМИ: " + hex(vaddr_data - vaddr_text) + " bytes")
|
||||||
|
|
||||||
|
sections[".comment"] = comment_content
|
||||||
|
|
||||||
|
# ПРОХОД 2
|
||||||
|
pass_num = 2
|
||||||
|
position[".text"] = 0
|
||||||
|
position[".data"] = 0
|
||||||
|
sections[".text"] = bytearray()
|
||||||
|
sections[".data"] = bytearray()
|
||||||
|
|
||||||
|
for line_num, line in enumerate(lines, start=1):
|
||||||
|
original_line = line.rstrip()
|
||||||
|
try:
|
||||||
|
tokens = tokenize_line(line)
|
||||||
|
parse_tokens(tokens, line_num, original_line)
|
||||||
|
except Exception as e:
|
||||||
|
error_full = make_error_msg(line_num, original_line, str(e))
|
||||||
|
print(error_full, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
text_size_pass2 = len(sections[".text"])
|
||||||
|
data_size_pass2 = len(sections[".data"])
|
||||||
|
print("ПРОХОД 2: text_size=" + str(text_size_pass2) + " bytes, data_size=" + str(data_size_pass2) + " bytes")
|
||||||
|
|
||||||
|
if text_size_pass1 != text_size_pass2:
|
||||||
|
print("ПРЕДУПРЕЖДЕНИЕ: Размер .text изменился между проходами: " + str(text_size_pass1) + " -> " + str(text_size_pass2))
|
||||||
|
if data_size_pass1 != data_size_pass2:
|
||||||
|
print("ПРЕДУПРЕЖДЕНИЕ: Размер .data изменился между проходами: " + str(data_size_pass1) + " -> " + str(data_size_pass2))
|
||||||
|
|
||||||
|
text_size = text_size_pass2
|
||||||
|
data_size = data_size_pass2
|
||||||
|
|
||||||
|
def create_elf(filename):
|
||||||
|
global sections, entry_point, labels, vaddr_text, vaddr_data
|
||||||
|
global offset_text, offset_data, offset_comment, shstrtab_offset, shdr_offset
|
||||||
|
|
||||||
|
text = sections[".text"]
|
||||||
|
data = sections[".data"]
|
||||||
|
comment = sections[".comment"]
|
||||||
|
|
||||||
|
actual_text_size = len(text)
|
||||||
|
actual_data_size = len(data)
|
||||||
|
expected_vaddr_data = align_up(vaddr_text + actual_text_size, PAGE_SIZE)
|
||||||
|
if vaddr_data != expected_vaddr_data:
|
||||||
|
print("КОРРЕКЦИЯ: vaddr_data исправлен с " + hex(vaddr_data) + " на " + hex(expected_vaddr_data))
|
||||||
|
vaddr_data = expected_vaddr_data
|
||||||
|
|
||||||
|
print("ФАКТИЧЕСКИЕ РАЗМЕРЫ: .text=" + str(actual_text_size) + ", .data=" + str(actual_data_size))
|
||||||
|
print("КОНЕЧНЫЕ АДРЕСА: .text ends at " + hex(vaddr_text + actual_text_size) + ", .data starts at " + hex(vaddr_data))
|
||||||
|
print("ПРОВЕРКА ПЕРЕКРЫТИЯ: " + ("ПЕРЕКРЫТИЕ!" if (vaddr_text + actual_text_size) > vaddr_data else "OK"))
|
||||||
|
|
||||||
|
entry_addr = vaddr_text + labels.get(entry_point, 0)
|
||||||
|
|
||||||
|
shstrtab_content = b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00"
|
||||||
|
shstrtab_size = len(shstrtab_content)
|
||||||
|
|
||||||
|
elf_header_size = 64
|
||||||
|
ph_size = 56
|
||||||
|
ph_num = 3
|
||||||
|
shdr_size = 64
|
||||||
|
shdr_num = 5
|
||||||
|
|
||||||
|
file_size = shdr_offset + shdr_num * shdr_size
|
||||||
|
elf_data = bytearray(file_size)
|
||||||
|
|
||||||
|
# ELF header
|
||||||
|
e_ident = b"\x7fELF\x02\x01\x01\x00" + b"\x00" * 8
|
||||||
|
elf_header = struct.pack(
|
||||||
|
'<16sHHIQQQIHHHHHH',
|
||||||
|
e_ident,
|
||||||
|
2,
|
||||||
|
0x3e,
|
||||||
|
1,
|
||||||
|
entry_addr,
|
||||||
|
elf_header_size,
|
||||||
|
shdr_offset,
|
||||||
|
0,
|
||||||
|
elf_header_size,
|
||||||
|
ph_size,
|
||||||
|
ph_num,
|
||||||
|
shdr_size,
|
||||||
|
shdr_num,
|
||||||
|
4
|
||||||
|
)
|
||||||
|
elf_data[0:64] = elf_header
|
||||||
|
|
||||||
|
def phdr(p_type, p_flags, p_offset, p_vaddr, p_filesz, p_memsz):
|
||||||
|
return struct.pack('<IIQQQQQQ',
|
||||||
|
p_type, p_flags,
|
||||||
|
p_offset, p_vaddr, p_vaddr,
|
||||||
|
p_filesz, p_memsz,
|
||||||
|
PAGE_SIZE
|
||||||
|
)
|
||||||
|
|
||||||
|
ph0 = phdr(1, 4, 0, elf_base_vaddr, elf_header_size + ph_num * ph_size, PAGE_SIZE)
|
||||||
|
ph1 = phdr(1, 5, offset_text, vaddr_text, len(text), align_up(len(text), PAGE_SIZE))
|
||||||
|
ph2 = phdr(1, 6, offset_data, vaddr_data, len(data), align_up(len(data), PAGE_SIZE))
|
||||||
|
|
||||||
|
phdrs = ph0 + ph1 + ph2
|
||||||
|
elf_data[elf_header_size : elf_header_size + len(phdrs)] = phdrs
|
||||||
|
|
||||||
|
elf_data[offset_text : offset_text + len(text)] = text
|
||||||
|
elf_data[offset_data : offset_data + len(data)] = data
|
||||||
|
elf_data[offset_comment : offset_comment + len(comment)] = comment
|
||||||
|
elf_data[shstrtab_offset : shstrtab_offset + shstrtab_size] = shstrtab_content
|
||||||
|
|
||||||
|
def shdr(name_idx, sh_type, flags, addr, offset, size, addralign=1):
|
||||||
|
return struct.pack('<IIQQQQIIQQ',
|
||||||
|
name_idx, sh_type, flags, addr, offset, size,
|
||||||
|
0, 0, addralign, 0
|
||||||
|
)
|
||||||
|
|
||||||
|
sh0 = shdr(0, 0, 0, 0, 0, 0)
|
||||||
|
sh1 = shdr(1, 1, 6, vaddr_text, offset_text, len(text), 16)
|
||||||
|
sh2 = shdr(7, 1, 3, vaddr_data, offset_data, len(data), 8)
|
||||||
|
sh3 = shdr(13, 1, 0, 0, offset_comment, len(comment), 1)
|
||||||
|
sh4 = shdr(22, 3, 0, 0, shstrtab_offset, shstrtab_size, 1)
|
||||||
|
|
||||||
|
shdrs = sh0 + sh1 + sh2 + sh3 + sh4
|
||||||
|
elf_data[shdr_offset : shdr_offset + len(shdrs)] = shdrs
|
||||||
|
|
||||||
|
with open(filename, "wb") as f:
|
||||||
|
f.write(elf_data)
|
||||||
|
|
||||||
|
import os
|
||||||
|
os.chmod(filename, 0o755)
|
||||||
|
|
||||||
|
# === Основной запуск ===
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("Использование: python kvs_4.py <файл.квс>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
source_file = sys.argv[1]
|
||||||
|
source_filename = source_file
|
||||||
|
if not source_file.endswith('.квс'):
|
||||||
|
print("Ошибка: файл должен иметь расширение .квс")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
f_in = None
|
||||||
|
try:
|
||||||
|
f_in = open(source_file, "r", encoding="utf-8")
|
||||||
|
source = f_in.read()
|
||||||
|
f_in.close()
|
||||||
|
except FileNotFoundError:
|
||||||
|
safe_close(f_in)
|
||||||
|
print("Ошибка: файл '" + source_file + "' не найден.")
|
||||||
|
sys.exit(1)
|
||||||
|
except UnicodeDecodeError as e:
|
||||||
|
safe_close(f_in)
|
||||||
|
print("Ошибка кодировки в файле '" + source_file + "': " + str(e))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
parse(source)
|
||||||
|
elf_file = source_file[:-4] + ".elf"
|
||||||
|
create_elf(elf_file)
|
||||||
|
|
||||||
|
log_file = source_file[:-4] + ".log.csv"
|
||||||
|
with open(log_file, "w", encoding="utf-8") as f_log:
|
||||||
|
f_log.write("адрес;байт;целевой_адрес;исходная_команда\n")
|
||||||
|
for addr, byte, target, cmd in log_entries:
|
||||||
|
if cmd and ('"' in cmd or ';' in cmd):
|
||||||
|
cmd = '"' + cmd.replace('"', '""') + '"'
|
||||||
|
f_log.write(addr + ";" + byte + ";" + target + ";" + cmd + "\n")
|
||||||
|
print("Лог создан: " + log_file)
|
||||||
|
|
||||||
|
print("ELF-файл создан: " + elf_file)
|
||||||
|
print("Запустить: ./" + elf_file)
|
||||||
|
except SystemExit:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
print("Внутренняя ошибка ассемблера: " + str(e), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
930
jumps/kvs_6.py
Normal file
930
jumps/kvs_6.py
Normal file
|
|
@ -0,0 +1,930 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
kvs_6.py
|
||||||
|
КВС - язык программирования
|
||||||
|
без использования re
|
||||||
|
(расширенная версия с короткими переходами и полными регистрами)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# Глобальная переменная для имени исходного файла
|
||||||
|
source_filename = ""
|
||||||
|
|
||||||
|
def safe_close(f):
|
||||||
|
if f is not None:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# === Глобальные данные ===
|
||||||
|
INSTRUCTIONS = {
|
||||||
|
"переместить_имм": {"code": None, "type": "reg_imm"},
|
||||||
|
"сравнить_с": {"code": None, "type": "cmp_reg_imm"},
|
||||||
|
"переход_если_неравно": {"code": b"\x0F\x85", "type": "jcc"},
|
||||||
|
"вызов_системы": {"code": b"\x0F\x05", "type": "none"},
|
||||||
|
"переход": {"code": b"\xE9", "type": "jmp"},
|
||||||
|
# === Короткие переходы ===
|
||||||
|
"короткий_переход": {"code": b"\xEB", "type": "short_jmp"},
|
||||||
|
"короткий_переход_если_равно" : {"code": b"\x74", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_неравно" : {"code": b"\x75", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_меньше" : {"code": b"\x7C", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_больше" : {"code": b"\x7F", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_меньше_или_равно": {"code": b"\x7E", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_больше_или_равно": {"code": b"\x7D", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_перенос" : {"code": b"\x72", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_нет_переноса" : {"code": b"\x73", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_ноль" : {"code": b"\x74", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_не_ноль" : {"code": b"\x75", "type": "short_jcc"},
|
||||||
|
# === Новые команды для флагов ===
|
||||||
|
"сравнить": {"code": b"\x48\x39", "type": "cmp_reg_reg"},
|
||||||
|
"проверить": {"code": b"\x48\x85", "type": "test_reg_reg"},
|
||||||
|
"вычесть": {"code": b"\x48\x29", "type": "sub_reg_reg"},
|
||||||
|
"прибавить": {"code": b"\x48\x01", "type": "add_reg_reg"},
|
||||||
|
"увеличить": {"code": b"\xFF", "subop": 0, "type": "incdec"},
|
||||||
|
"уменьшить": {"code": b"\xFF", "subop": 1, "type": "incdec"},
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTERS = {
|
||||||
|
# 64-битные
|
||||||
|
"раикс": 0, "рсикс": 1, "рдикс": 2, "рбикс": 3,
|
||||||
|
"рсипи": 4, "рбипи": 5, "рсиай": 6, "рдиай": 7,
|
||||||
|
"р8": 8, "р9": 9, "р10": 10, "р11": 11,
|
||||||
|
"р12": 12, "р13": 13, "р14": 14, "р15": 15,
|
||||||
|
# 32-битные
|
||||||
|
"еаикс": 0, "есикс": 1, "едикс": 2, "ебикс": 3,
|
||||||
|
"есипи": 4, "ебипи": 5, "есиай": 6, "едиай": 7,
|
||||||
|
"р8д": 8, "р9д": 9, "р10д": 10, "р11д": 11,
|
||||||
|
"р12д": 12, "р13д": 13, "р14д": 14, "р15д": 15,
|
||||||
|
# 16-битные
|
||||||
|
"аикс": 0, "сикс": 1, "дикс": 2, "бикс": 3,
|
||||||
|
"эсп": 4, "бипи": 5, "эс": 6, "ди": 7,
|
||||||
|
"р8в": 8, "р9в": 9, "р10в": 10, "р11в": 11,
|
||||||
|
"р12в": 12, "р13в": 13, "р14в": 14, "р15в": 15,
|
||||||
|
# 8-битные младшие
|
||||||
|
"ал": 0, "кл": 1, "дл": 2, "бл": 3,
|
||||||
|
"спл": 4, "бпл": 5, "сил": 6, "дил": 7,
|
||||||
|
"р8б": 8, "р9б": 9, "р10б": 10, "р11б": 11,
|
||||||
|
"р12б": 12, "р13б": 13, "р14б": 14, "р15б": 15,
|
||||||
|
# 8-битные старшие (только первые 4)
|
||||||
|
"аш": 0, "чш": 1, "дш": 2, "бш": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Глобальное состояние ассемблера
|
||||||
|
labels = {}
|
||||||
|
label_sections = {}
|
||||||
|
symbols = {}
|
||||||
|
sections = {".text": bytearray(), ".data": bytearray()}
|
||||||
|
current_section = ".text"
|
||||||
|
entry_point = "_start"
|
||||||
|
position = {".text": 0, ".data": 0}
|
||||||
|
pass_num = 0
|
||||||
|
|
||||||
|
# === Для логирования ===
|
||||||
|
log_entries = []
|
||||||
|
|
||||||
|
# === ELF layout ===
|
||||||
|
PAGE_SIZE = 0x1000
|
||||||
|
elf_base_vaddr = 0x400000
|
||||||
|
text_vaddr_base = 0x401000
|
||||||
|
data_vaddr_base = 0x402000
|
||||||
|
|
||||||
|
text_size = 0
|
||||||
|
data_size = 0
|
||||||
|
comment_size = 0
|
||||||
|
offset_text = 0
|
||||||
|
offset_data = 0
|
||||||
|
offset_comment = 0
|
||||||
|
shstrtab_offset = 0
|
||||||
|
shdr_offset = 0
|
||||||
|
vaddr_text = 0
|
||||||
|
vaddr_data = 0
|
||||||
|
|
||||||
|
def align_up(x, align):
|
||||||
|
return (x + align - 1) & ~(align - 1)
|
||||||
|
|
||||||
|
def get_reg_info(reg_name):
|
||||||
|
if reg_name in ["аш", "чш", "дш", "бш"]:
|
||||||
|
return {"size": 8, "index": REGISTERS[reg_name], "high8": True}
|
||||||
|
elif reg_name.endswith(("б", "л")) or reg_name in ["ал", "кл", "дл", "бл", "спл", "бпл", "сил", "дил"]:
|
||||||
|
return {"size": 8, "index": REGISTERS[reg_name], "high8": False}
|
||||||
|
elif reg_name.endswith("в") or reg_name in ["аикс", "сикс", "дикс", "бикс", "эсп", "бипи", "эс", "ди"]:
|
||||||
|
return {"size": 16, "index": REGISTERS[reg_name]}
|
||||||
|
elif reg_name.endswith("д") or reg_name in ["еаикс", "есикс", "едикс", "ебикс", "есипи", "ебипи", "есиай", "едиай"]:
|
||||||
|
return {"size": 32, "index": REGISTERS[reg_name]}
|
||||||
|
else:
|
||||||
|
return {"size": 64, "index": REGISTERS[reg_name]}
|
||||||
|
|
||||||
|
# === Функции формирования ошибок ===
|
||||||
|
def make_error_msg(line_num, line_text, detail):
|
||||||
|
return "Ошибка в файле " + source_filename + ", строка " + str(line_num) + ":\n " + line_text + "\n" + detail
|
||||||
|
|
||||||
|
def error_invalid_operand_count(mnemonic, expected, got):
|
||||||
|
return "Инструкция '" + mnemonic + "':\n ожидается " + str(expected) + " операнд(а/ов), получено: " + str(got)
|
||||||
|
|
||||||
|
def error_unknown_mnemonic(mnemonic):
|
||||||
|
return "Неизвестная инструкция: '" + mnemonic + "'"
|
||||||
|
|
||||||
|
def error_invalid_register(op_name, reg_name, mnemonic):
|
||||||
|
return ("Инструкция '" + mnemonic + "':\n операнд '" + op_name + "' = '" + reg_name +
|
||||||
|
"' не является допустимым регистром.\n Допустимые регистры: " + ", ".join(list(REGISTERS.keys())))
|
||||||
|
|
||||||
|
def error_invalid_number_format(s):
|
||||||
|
return "Недопустимый формат числа: '" + s + "'"
|
||||||
|
|
||||||
|
def error_unknown_directive(word):
|
||||||
|
return "Неизвестная директива: '" + word + "'"
|
||||||
|
|
||||||
|
def error_missing_label(label):
|
||||||
|
return "Метка не найдена: '" + label + "'"
|
||||||
|
|
||||||
|
def error_unexpected_string_in_byte():
|
||||||
|
return ".байт требует числовые значения, не строки"
|
||||||
|
|
||||||
|
def error_unterminated_string():
|
||||||
|
return "Незакрытая кавычка в строке"
|
||||||
|
|
||||||
|
# === Лексер ===
|
||||||
|
def tokenize_line(line):
|
||||||
|
semi = line.find(';')
|
||||||
|
if semi != -1:
|
||||||
|
line = line[:semi]
|
||||||
|
line = line.rstrip()
|
||||||
|
if not line:
|
||||||
|
return []
|
||||||
|
tokens = []
|
||||||
|
i = 0
|
||||||
|
n = len(line)
|
||||||
|
while i < n:
|
||||||
|
ch = line[i]
|
||||||
|
if ch.isspace():
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if ch == '"':
|
||||||
|
i += 1
|
||||||
|
s = ''
|
||||||
|
while i < n and line[i] != '"':
|
||||||
|
if line[i] == '\\' and i + 1 < n:
|
||||||
|
i += 1
|
||||||
|
esc = line[i]
|
||||||
|
if esc == 'n':
|
||||||
|
s += '\n'
|
||||||
|
elif esc == 't':
|
||||||
|
s += '\t'
|
||||||
|
elif esc == '"':
|
||||||
|
s += '"'
|
||||||
|
elif esc == '\\':
|
||||||
|
s += '\\'
|
||||||
|
else:
|
||||||
|
s += '\\' + esc
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
s += line[i]
|
||||||
|
i += 1
|
||||||
|
if i >= n:
|
||||||
|
raise ValueError(error_unterminated_string())
|
||||||
|
i += 1
|
||||||
|
tokens.append(('string', s))
|
||||||
|
continue
|
||||||
|
if ch == ',':
|
||||||
|
tokens.append(('comma', ','))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if ch == ':':
|
||||||
|
tokens.append(('colon', ':'))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
j = i
|
||||||
|
while j < n and not (line[j].isspace() or line[j] in ',:;'):
|
||||||
|
j += 1
|
||||||
|
word = line[i:j]
|
||||||
|
if word:
|
||||||
|
tokens.append(('word', word))
|
||||||
|
i = j
|
||||||
|
return tokens
|
||||||
|
|
||||||
|
# === Парсинг ===
|
||||||
|
def parse_operand(operand):
|
||||||
|
if operand.isdigit():
|
||||||
|
return int(operand)
|
||||||
|
if operand.startswith("0x"):
|
||||||
|
return int(operand, 16)
|
||||||
|
if operand in labels:
|
||||||
|
section = label_sections[operand]
|
||||||
|
if pass_num == 2:
|
||||||
|
base = vaddr_text if section == ".text" else vaddr_data
|
||||||
|
return labels[operand] + base
|
||||||
|
else:
|
||||||
|
return labels[operand]
|
||||||
|
if operand in symbols:
|
||||||
|
return symbols[operand]
|
||||||
|
raise ValueError("Неизвестный операнд: " + operand)
|
||||||
|
|
||||||
|
def encode_instruction(mnemonic, operands, line_num, line_text):
|
||||||
|
instr = INSTRUCTIONS[mnemonic]
|
||||||
|
code = bytearray()
|
||||||
|
itype = instr["type"]
|
||||||
|
|
||||||
|
if itype == "none":
|
||||||
|
code.extend(instr["code"])
|
||||||
|
|
||||||
|
elif itype == "reg_imm":
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("назначения", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
size = reg_info["size"]
|
||||||
|
imm = parse_operand(operands[1])
|
||||||
|
|
||||||
|
if size == 64:
|
||||||
|
if 0 <= reg <= 7:
|
||||||
|
code.extend(b'\x48')
|
||||||
|
code.append(0xB8 + reg)
|
||||||
|
code.extend(struct.pack('<Q', imm))
|
||||||
|
elif 8 <= reg <= 15:
|
||||||
|
code.extend(b'\x49')
|
||||||
|
code.append(0xB8 + (reg - 8))
|
||||||
|
code.extend(struct.pack('<Q', imm))
|
||||||
|
else:
|
||||||
|
raise ValueError("Недопустимый регистр в '" + mnemonic + "'")
|
||||||
|
elif size == 32:
|
||||||
|
if -0x80000000 <= imm <= 0x7FFFFFFF:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xC7)
|
||||||
|
modrm = 0xC0 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.extend(struct.pack('<I', imm & 0xFFFFFFFF))
|
||||||
|
else:
|
||||||
|
raise ValueError("32-битное значение вне диапазона")
|
||||||
|
elif size == 16:
|
||||||
|
if 0 <= imm <= 0xFFFF:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xC7)
|
||||||
|
modrm = 0xC0 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
code.append((imm >> 8) & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("16-битное значение вне диапазона")
|
||||||
|
elif size == 8:
|
||||||
|
if not (0 <= imm <= 255):
|
||||||
|
raise ValueError("8-битное значение вне диапазона 0–255")
|
||||||
|
if reg_info.get("high8"):
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xB0 + reg + 4)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Старшие байты только для первых 4 регистров")
|
||||||
|
else:
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xB0 + reg)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xB0 + (reg & 7))
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый размер регистра")
|
||||||
|
|
||||||
|
elif itype == "cmp_reg_imm":
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("регистра", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
size = reg_info["size"]
|
||||||
|
imm = parse_operand(operands[1])
|
||||||
|
|
||||||
|
if size == 64:
|
||||||
|
if -128 <= imm <= 127:
|
||||||
|
rex = 0x48
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x83)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
elif -0x80000000 <= imm <= 0x7FFFFFFF:
|
||||||
|
rex = 0x48
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x81)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.extend(struct.pack('<i', imm))
|
||||||
|
else:
|
||||||
|
raise ValueError("Непосредственное значение слишком велико для сравнения: " + str(imm))
|
||||||
|
elif size == 32:
|
||||||
|
if -128 <= imm <= 127:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x83)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
elif -0x80000000 <= imm <= 0x7FFFFFFF:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x81)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.extend(struct.pack('<I', imm & 0xFFFFFFFF))
|
||||||
|
else:
|
||||||
|
raise ValueError("32-битное непосредственное значение вне диапазона")
|
||||||
|
elif size == 16:
|
||||||
|
if -128 <= imm <= 127:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x83)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
elif 0 <= imm <= 0xFFFF:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x81)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
code.append((imm >> 8) & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("16-битное непосредственное значение вне диапазона")
|
||||||
|
elif size == 8:
|
||||||
|
if not (0 <= imm <= 255):
|
||||||
|
raise ValueError("8-битное значение вне диапазона 0–255")
|
||||||
|
if reg_info.get("high8"):
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0x80)
|
||||||
|
modrm = 0xF8 | reg
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Старшие байты только для первых 4 регистров")
|
||||||
|
else:
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0x80)
|
||||||
|
modrm = 0xF8 | reg
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x80)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый размер регистра")
|
||||||
|
|
||||||
|
elif itype == "jmp":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 5)
|
||||||
|
if offset < -0x80000000 or offset > 0x7FFFFFFF:
|
||||||
|
raise ValueError("Цель слишком далеко для 32-битного смещения в инструкции '" + mnemonic + "': " + str(offset))
|
||||||
|
code.extend(struct.pack('<i', offset))
|
||||||
|
|
||||||
|
elif itype == "jcc":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 6)
|
||||||
|
if offset < -0x80000000 or offset > 0x7FFFFFFF:
|
||||||
|
raise ValueError("Цель условного перехода слишком далеко: " + str(offset))
|
||||||
|
code.extend(struct.pack('<i', offset))
|
||||||
|
|
||||||
|
elif itype == "short_jmp":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 2)
|
||||||
|
if offset < -128 or offset > 127:
|
||||||
|
raise ValueError("Цель слишком далеко для короткого перехода: " + str(offset))
|
||||||
|
code.append(0xEB)
|
||||||
|
code.append(offset & 0xFF)
|
||||||
|
|
||||||
|
elif itype == "short_jcc":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 2)
|
||||||
|
if offset < -128 or offset > 127:
|
||||||
|
raise ValueError("Цель слишком далеко для короткого условного перехода: " + str(offset))
|
||||||
|
code.append(offset & 0xFF)
|
||||||
|
|
||||||
|
elif itype in ("cmp_reg_reg", "test_reg_reg", "add_reg_reg", "sub_reg_reg"):
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
dst_info = get_reg_info(operands[0])
|
||||||
|
src_info = get_reg_info(operands[1])
|
||||||
|
if dst_info is None:
|
||||||
|
raise ValueError(error_invalid_register("назначения", operands[0], mnemonic))
|
||||||
|
if src_info is None:
|
||||||
|
raise ValueError(error_invalid_register("источника", operands[1], mnemonic))
|
||||||
|
dst = dst_info["index"]
|
||||||
|
src = src_info["index"]
|
||||||
|
size = dst_info["size"]
|
||||||
|
if size != src_info["size"]:
|
||||||
|
raise ValueError("Размеры операндов не совпадают в инструкции '" + mnemonic + "'")
|
||||||
|
|
||||||
|
use_66 = (size == 16)
|
||||||
|
use_rex_w = (size == 64)
|
||||||
|
rex = 0x40
|
||||||
|
if use_rex_w:
|
||||||
|
rex |= 0x08
|
||||||
|
if src >= 8:
|
||||||
|
rex |= 0x04
|
||||||
|
if dst >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if dst_info.get("high8") or src_info.get("high8"):
|
||||||
|
if rex != 0x40:
|
||||||
|
raise ValueError("Старшие байты несовместимы с REX")
|
||||||
|
rex = 0
|
||||||
|
|
||||||
|
op_map = {
|
||||||
|
"cmp_reg_reg": 0x39,
|
||||||
|
"test_reg_reg": 0x85,
|
||||||
|
"add_reg_reg": 0x01,
|
||||||
|
"sub_reg_reg": 0x29,
|
||||||
|
}
|
||||||
|
op = op_map[itype]
|
||||||
|
|
||||||
|
if use_66:
|
||||||
|
code.append(0x66)
|
||||||
|
if rex != 0x40 or use_rex_w:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(op)
|
||||||
|
modrm = 0xC0 | ((src & 7) << 3) | (dst & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
|
||||||
|
elif itype == "incdec":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("регистра", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
size = reg_info["size"]
|
||||||
|
subop = instr["subop"]
|
||||||
|
|
||||||
|
if size == 64:
|
||||||
|
rex = 0x48
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFF)
|
||||||
|
elif size == 32:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFF)
|
||||||
|
elif size == 16:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFF)
|
||||||
|
elif size == 8:
|
||||||
|
if reg_info.get("high8"):
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xFE)
|
||||||
|
else:
|
||||||
|
raise ValueError("Старшие байты только для первых 4 регистров")
|
||||||
|
else:
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xFE)
|
||||||
|
else:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFE)
|
||||||
|
modrm = 0xC0 | (subop << 3) | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
return bytes(code)
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый размер регистра")
|
||||||
|
|
||||||
|
modrm = 0xC0 | (subop << 3) | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError("Неизвестный тип инструкции: " + itype)
|
||||||
|
|
||||||
|
return bytes(code)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parse_instruction_or_directive(tokens, line_num, line_text):
|
||||||
|
global current_section, entry_point, symbols # Не забудьте добавить symbols в global
|
||||||
|
first = tokens[0]
|
||||||
|
if first[0] != 'word':
|
||||||
|
raise ValueError("Ожидалось слово, получено: " + str(first))
|
||||||
|
word = first[1]
|
||||||
|
if word.startswith('.'):
|
||||||
|
if word == '.текст':
|
||||||
|
current_section = ".text"
|
||||||
|
elif word == '.данные':
|
||||||
|
current_section = ".data"
|
||||||
|
elif word == '.глобал':
|
||||||
|
if len(tokens) < 2 or tokens[1][0] != 'word':
|
||||||
|
raise ValueError(".глобал требует имя метки")
|
||||||
|
entry_point = tokens[1][1]
|
||||||
|
elif word == '.строка_нуль' or word == '.строка':
|
||||||
|
if len(tokens) < 2 or tokens[1][0] != 'string':
|
||||||
|
raise ValueError(word + " требует строку в кавычках")
|
||||||
|
if current_section != ".data":
|
||||||
|
raise ValueError("Строки разрешены только в секции .data")
|
||||||
|
s = tokens[1][1]
|
||||||
|
bstring = s.encode('utf-8')
|
||||||
|
add_null = (word == '.строка_нуль')
|
||||||
|
size = len(bstring) + (1 if add_null else 0)
|
||||||
|
if pass_num == 1:
|
||||||
|
position[".data"] += size
|
||||||
|
elif pass_num == 2:
|
||||||
|
sections[".data"] += bstring
|
||||||
|
if add_null:
|
||||||
|
sections[".data"] += b'\x00'
|
||||||
|
position[".data"] += size
|
||||||
|
# === НОВАЯ ДИРЕКТИВА .КОНСТАНТА ===
|
||||||
|
elif word == '.константа':
|
||||||
|
if len(tokens) < 3 or tokens[1][0] != 'word' or tokens[2][0] != 'word' or tokens[2][1] != '=' or len(tokens) < 4 or tokens[3][0] not in ('word', 'string'): # Проверяем формат: .константа имя = значение
|
||||||
|
raise ValueError(".константа требует формат: .константа <имя> = <значение>")
|
||||||
|
const_name = tokens[1][1]
|
||||||
|
const_value_str = tokens[3][1]
|
||||||
|
try:
|
||||||
|
# Попробуем распарсить значение как число или символ (если это метка)
|
||||||
|
const_value = parse_operand(const_value_str)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Невозможно распознать значение константы '" + const_value_str + "'")
|
||||||
|
|
||||||
|
# Записываем в глобальный словарь символов
|
||||||
|
symbols[const_name] = const_value
|
||||||
|
# Директива .константа не добавляет байты в секцию
|
||||||
|
return
|
||||||
|
# === КОНЕЦ НОВОЙ ДИРЕКТИВЫ ===
|
||||||
|
else:
|
||||||
|
raise ValueError(error_unknown_directive(word))
|
||||||
|
return
|
||||||
|
|
||||||
|
mnemonic = word
|
||||||
|
if mnemonic not in INSTRUCTIONS:
|
||||||
|
raise ValueError(error_unknown_mnemonic(mnemonic))
|
||||||
|
|
||||||
|
operands = []
|
||||||
|
for tok in tokens[1:]:
|
||||||
|
if tok[0] == 'word':
|
||||||
|
operands.append(tok[1])
|
||||||
|
elif tok[0] == 'comma':
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raise ValueError("Недопустимый токен в операндах: " + str(tok))
|
||||||
|
|
||||||
|
if pass_num == 2:
|
||||||
|
instr_info = INSTRUCTIONS[mnemonic]
|
||||||
|
itype = instr_info["type"]
|
||||||
|
code = encode_instruction(mnemonic, operands, line_num, line_text)
|
||||||
|
start_pos = position[current_section]
|
||||||
|
|
||||||
|
if current_section == ".text":
|
||||||
|
start_vaddr = vaddr_text + start_pos
|
||||||
|
target_addr = ""
|
||||||
|
try:
|
||||||
|
if itype in ("jmp", "jcc", "short_jmp", "short_jcc"):
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
target_addr = hex(target)
|
||||||
|
elif itype == "reg_imm":
|
||||||
|
op_str = operands[1]
|
||||||
|
if op_str in labels:
|
||||||
|
sec = label_sections[op_str]
|
||||||
|
addr = labels[op_str] + (vaddr_text if sec == ".text" else vaddr_data)
|
||||||
|
target_addr = hex(addr)
|
||||||
|
elif op_str in symbols: # Проверяем символы
|
||||||
|
target_addr = hex(symbols[op_str])
|
||||||
|
except Exception:
|
||||||
|
target_addr = "ошибка"
|
||||||
|
|
||||||
|
original_cmd = line_text.split(';')[0].strip()
|
||||||
|
for i, byte in enumerate(code):
|
||||||
|
addr = start_vaddr + i
|
||||||
|
byte_hex = "{:02X}".format(byte)
|
||||||
|
cmd_to_log = original_cmd if i == 0 else ""
|
||||||
|
log_entries.append((hex(addr), byte_hex, target_addr if i == 0 else "", cmd_to_log))
|
||||||
|
|
||||||
|
sections[current_section] += code
|
||||||
|
position[current_section] += len(code)
|
||||||
|
else:
|
||||||
|
instr_info = INSTRUCTIONS[mnemonic]
|
||||||
|
itype = instr_info["type"]
|
||||||
|
size_map = {
|
||||||
|
"reg_imm": 10,
|
||||||
|
"cmp_reg_imm": 7,
|
||||||
|
"jmp": 5,
|
||||||
|
"jcc": 6,
|
||||||
|
"none": lambda: len(instr_info["code"]),
|
||||||
|
"short_jmp": 2,
|
||||||
|
"short_jcc": 2,
|
||||||
|
"cmp_reg_reg": 3,
|
||||||
|
"test_reg_reg": 3,
|
||||||
|
"add_reg_reg": 3,
|
||||||
|
"sub_reg_reg": 3,
|
||||||
|
"incdec": 3,
|
||||||
|
}
|
||||||
|
if itype in size_map:
|
||||||
|
sz = size_map[itype]
|
||||||
|
position[current_section] += sz() if callable(sz) else sz
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый тип инструкции при подсчёте размера: " + itype)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parse_tokens(tokens, line_num, line_text):
|
||||||
|
if not tokens:
|
||||||
|
return
|
||||||
|
if len(tokens) >= 2 and tokens[0][0] == 'word' and tokens[1][0] == 'colon':
|
||||||
|
label = tokens[0][1]
|
||||||
|
labels[label] = position[current_section]
|
||||||
|
label_sections[label] = current_section
|
||||||
|
rest = tokens[2:]
|
||||||
|
if rest:
|
||||||
|
parse_instruction_or_directive(rest, line_num, line_text)
|
||||||
|
return
|
||||||
|
parse_instruction_or_directive(tokens, line_num, line_text)
|
||||||
|
|
||||||
|
def parse(source):
|
||||||
|
global pass_num, text_size, data_size, comment_size
|
||||||
|
global offset_text, offset_data, offset_comment, shstrtab_offset, shdr_offset
|
||||||
|
global vaddr_text, vaddr_data
|
||||||
|
global sections, position, log_entries
|
||||||
|
|
||||||
|
log_entries = []
|
||||||
|
lines = source.split('\n')
|
||||||
|
|
||||||
|
# ПРОХОД 1
|
||||||
|
pass_num = 1
|
||||||
|
position[".text"] = 0
|
||||||
|
position[".data"] = 0
|
||||||
|
labels.clear()
|
||||||
|
label_sections.clear()
|
||||||
|
|
||||||
|
for line_num, line in enumerate(lines, start=1):
|
||||||
|
original_line = line.rstrip()
|
||||||
|
try:
|
||||||
|
tokens = tokenize_line(line)
|
||||||
|
parse_tokens(tokens, line_num, original_line)
|
||||||
|
except Exception as e:
|
||||||
|
error_full = make_error_msg(line_num, original_line, str(e))
|
||||||
|
print(error_full, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
text_size_pass1 = position[".text"]
|
||||||
|
data_size_pass1 = position[".data"]
|
||||||
|
print("ПРОХОД 1: text_size=" + str(text_size_pass1) + " bytes, data_size=" + str(data_size_pass1) + " bytes")
|
||||||
|
|
||||||
|
# РАЗМЕЩЕНИЕ
|
||||||
|
elf_header_size = 64
|
||||||
|
ph_size = 56
|
||||||
|
ph_num = 3
|
||||||
|
ph_table_size = ph_num * ph_size
|
||||||
|
|
||||||
|
offset_text = align_up(elf_header_size + ph_table_size, PAGE_SIZE)
|
||||||
|
offset_data = align_up(offset_text + text_size_pass1, PAGE_SIZE)
|
||||||
|
vaddr_text = text_vaddr_base
|
||||||
|
vaddr_data = align_up(vaddr_text + text_size_pass1, PAGE_SIZE)
|
||||||
|
|
||||||
|
comment_content = "Сборщик КВС".encode('utf-8') + b'\x00'
|
||||||
|
comment_size = len(comment_content)
|
||||||
|
offset_comment = align_up(offset_data + data_size_pass1, 1)
|
||||||
|
|
||||||
|
shstrtab_content = b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00"
|
||||||
|
shstrtab_size = len(shstrtab_content)
|
||||||
|
shstrtab_offset = align_up(offset_comment + comment_size, 8)
|
||||||
|
shdr_size = 64
|
||||||
|
shdr_num = 5
|
||||||
|
shdr_offset = align_up(shstrtab_offset + shstrtab_size, 16)
|
||||||
|
|
||||||
|
print("РАЗМЕЩЕНИЕ: .text at offset=" + hex(offset_text) + ", .data at offset=" + hex(offset_data))
|
||||||
|
print("ВИРТУАЛЬНЫЕ АДРЕСА: .text at " + hex(vaddr_text) + ", .data at " + hex(vaddr_data))
|
||||||
|
print("РАССТОЯНИЕ МЕЖДУ СЕКЦИЯМИ: " + hex(vaddr_data - vaddr_text) + " bytes")
|
||||||
|
|
||||||
|
sections[".comment"] = comment_content
|
||||||
|
|
||||||
|
# ПРОХОД 2
|
||||||
|
pass_num = 2
|
||||||
|
position[".text"] = 0
|
||||||
|
position[".data"] = 0
|
||||||
|
sections[".text"] = bytearray()
|
||||||
|
sections[".data"] = bytearray()
|
||||||
|
|
||||||
|
for line_num, line in enumerate(lines, start=1):
|
||||||
|
original_line = line.rstrip()
|
||||||
|
try:
|
||||||
|
tokens = tokenize_line(line)
|
||||||
|
parse_tokens(tokens, line_num, original_line)
|
||||||
|
except Exception as e:
|
||||||
|
error_full = make_error_msg(line_num, original_line, str(e))
|
||||||
|
print(error_full, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
text_size_pass2 = len(sections[".text"])
|
||||||
|
data_size_pass2 = len(sections[".data"])
|
||||||
|
print("ПРОХОД 2: text_size=" + str(text_size_pass2) + " bytes, data_size=" + str(data_size_pass2) + " bytes")
|
||||||
|
|
||||||
|
if text_size_pass1 != text_size_pass2:
|
||||||
|
print("ПРЕДУПРЕЖДЕНИЕ: Размер .text изменился между проходами: " + str(text_size_pass1) + " -> " + str(text_size_pass2))
|
||||||
|
if data_size_pass1 != data_size_pass2:
|
||||||
|
print("ПРЕДУПРЕЖДЕНИЕ: Размер .data изменился между проходами: " + str(data_size_pass1) + " -> " + str(data_size_pass2))
|
||||||
|
|
||||||
|
text_size = text_size_pass2
|
||||||
|
data_size = data_size_pass2
|
||||||
|
|
||||||
|
def create_elf(filename):
|
||||||
|
global sections, entry_point, labels, vaddr_text, vaddr_data
|
||||||
|
global offset_text, offset_data, offset_comment, shstrtab_offset, shdr_offset
|
||||||
|
|
||||||
|
text = sections[".text"]
|
||||||
|
data = sections[".data"]
|
||||||
|
comment = sections[".comment"]
|
||||||
|
|
||||||
|
actual_text_size = len(text)
|
||||||
|
actual_data_size = len(data)
|
||||||
|
expected_vaddr_data = align_up(vaddr_text + actual_text_size, PAGE_SIZE)
|
||||||
|
if vaddr_data != expected_vaddr_data:
|
||||||
|
print("КОРРЕКЦИЯ: vaddr_data исправлен с " + hex(vaddr_data) + " на " + hex(expected_vaddr_data))
|
||||||
|
vaddr_data = expected_vaddr_data
|
||||||
|
|
||||||
|
print("ФАКТИЧЕСКИЕ РАЗМЕРЫ: .text=" + str(actual_text_size) + ", .data=" + str(actual_data_size))
|
||||||
|
print("КОНЕЧНЫЕ АДРЕСА: .text ends at " + hex(vaddr_text + actual_text_size) + ", .data starts at " + hex(vaddr_data))
|
||||||
|
print("ПРОВЕРКА ПЕРЕКРЫТИЯ: " + ("ПЕРЕКРЫТИЕ!" if (vaddr_text + actual_text_size) > vaddr_data else "OK"))
|
||||||
|
|
||||||
|
entry_addr = vaddr_text + labels.get(entry_point, 0)
|
||||||
|
|
||||||
|
shstrtab_content = b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00"
|
||||||
|
shstrtab_size = len(shstrtab_content)
|
||||||
|
|
||||||
|
elf_header_size = 64
|
||||||
|
ph_size = 56
|
||||||
|
ph_num = 3
|
||||||
|
shdr_size = 64
|
||||||
|
shdr_num = 5
|
||||||
|
|
||||||
|
file_size = shdr_offset + shdr_num * shdr_size
|
||||||
|
elf_data = bytearray(file_size)
|
||||||
|
|
||||||
|
# ELF header
|
||||||
|
e_ident = b"\x7fELF\x02\x01\x01\x00" + b"\x00" * 8
|
||||||
|
elf_header = struct.pack(
|
||||||
|
'<16sHHIQQQIHHHHHH',
|
||||||
|
e_ident,
|
||||||
|
2,
|
||||||
|
0x3e,
|
||||||
|
1,
|
||||||
|
entry_addr,
|
||||||
|
elf_header_size,
|
||||||
|
shdr_offset,
|
||||||
|
0,
|
||||||
|
elf_header_size,
|
||||||
|
ph_size,
|
||||||
|
ph_num,
|
||||||
|
shdr_size,
|
||||||
|
shdr_num,
|
||||||
|
4
|
||||||
|
)
|
||||||
|
elf_data[0:64] = elf_header
|
||||||
|
|
||||||
|
def phdr(p_type, p_flags, p_offset, p_vaddr, p_filesz, p_memsz):
|
||||||
|
return struct.pack('<IIQQQQQQ',
|
||||||
|
p_type, p_flags,
|
||||||
|
p_offset, p_vaddr, p_vaddr,
|
||||||
|
p_filesz, p_memsz,
|
||||||
|
PAGE_SIZE
|
||||||
|
)
|
||||||
|
|
||||||
|
ph0 = phdr(1, 4, 0, elf_base_vaddr, elf_header_size + ph_num * ph_size, PAGE_SIZE)
|
||||||
|
ph1 = phdr(1, 5, offset_text, vaddr_text, len(text), align_up(len(text), PAGE_SIZE))
|
||||||
|
ph2 = phdr(1, 6, offset_data, vaddr_data, len(data), align_up(len(data), PAGE_SIZE))
|
||||||
|
|
||||||
|
phdrs = ph0 + ph1 + ph2
|
||||||
|
elf_data[elf_header_size : elf_header_size + len(phdrs)] = phdrs
|
||||||
|
|
||||||
|
elf_data[offset_text : offset_text + len(text)] = text
|
||||||
|
elf_data[offset_data : offset_data + len(data)] = data
|
||||||
|
elf_data[offset_comment : offset_comment + len(comment)] = comment
|
||||||
|
elf_data[shstrtab_offset : shstrtab_offset + shstrtab_size] = shstrtab_content
|
||||||
|
|
||||||
|
def shdr(name_idx, sh_type, flags, addr, offset, size, addralign=1):
|
||||||
|
return struct.pack('<IIQQQQIIQQ',
|
||||||
|
name_idx, sh_type, flags, addr, offset, size,
|
||||||
|
0, 0, addralign, 0
|
||||||
|
)
|
||||||
|
|
||||||
|
sh0 = shdr(0, 0, 0, 0, 0, 0)
|
||||||
|
sh1 = shdr(1, 1, 6, vaddr_text, offset_text, len(text), 16)
|
||||||
|
sh2 = shdr(7, 1, 3, vaddr_data, offset_data, len(data), 8)
|
||||||
|
sh3 = shdr(13, 1, 0, 0, offset_comment, len(comment), 1)
|
||||||
|
sh4 = shdr(22, 3, 0, 0, shstrtab_offset, shstrtab_size, 1)
|
||||||
|
|
||||||
|
shdrs = sh0 + sh1 + sh2 + sh3 + sh4
|
||||||
|
elf_data[shdr_offset : shdr_offset + len(shdrs)] = shdrs
|
||||||
|
|
||||||
|
f_out = open(filename, "wb")
|
||||||
|
f_out.write(elf_data)
|
||||||
|
f_out.close()
|
||||||
|
|
||||||
|
import os
|
||||||
|
os.chmod(filename, 0o755)
|
||||||
|
|
||||||
|
# === Основной запуск ===
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("Использование: python kvs_5.py <файл.квс>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
source_file = sys.argv[1]
|
||||||
|
source_filename = source_file
|
||||||
|
if not source_file.endswith('.квс'):
|
||||||
|
print("Ошибка: файл должен иметь расширение .квс")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
f_in = None
|
||||||
|
try:
|
||||||
|
f_in = open(source_file, "r", encoding="utf-8")
|
||||||
|
source = f_in.read()
|
||||||
|
f_in.close()
|
||||||
|
except FileNotFoundError:
|
||||||
|
safe_close(f_in)
|
||||||
|
print("Ошибка: файл '" + source_file + "' не найден.")
|
||||||
|
sys.exit(1)
|
||||||
|
except UnicodeDecodeError as e:
|
||||||
|
safe_close(f_in)
|
||||||
|
print("Ошибка кодировки в файле '" + source_file + "': " + str(e))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
parse(source)
|
||||||
|
elf_file = source_file[:-4] + ".elf"
|
||||||
|
create_elf(elf_file)
|
||||||
|
|
||||||
|
log_file = source_file[:-4] + ".log.csv"
|
||||||
|
f_log = open(log_file, "w", encoding="utf-8")
|
||||||
|
f_log.write("адрес;байт;целевой_адрес;исходная_команда\n")
|
||||||
|
for addr, byte, target, cmd in log_entries:
|
||||||
|
if cmd and ('"' in cmd or ';' in cmd):
|
||||||
|
cmd = '"' + cmd.replace('"', '""') + '"'
|
||||||
|
f_log.write(addr + ";" + byte + ";" + target + ";" + cmd + "\n")
|
||||||
|
f_log.close()
|
||||||
|
print("Лог создан: " + log_file)
|
||||||
|
|
||||||
|
print("ELF-файл создан: " + elf_file)
|
||||||
|
print("Запустить: ./" + elf_file)
|
||||||
|
except SystemExit:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
print("Внутренняя ошибка ассемблера: " + str(e), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
933
jumps/kvs_7.py
Normal file
933
jumps/kvs_7.py
Normal file
|
|
@ -0,0 +1,933 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
kvs_7.py
|
||||||
|
КВС - язык программирования
|
||||||
|
без использования re
|
||||||
|
(расширенная версия с короткими и длинными переходами и полными регистрами)
|
||||||
|
(исправленная версия с использованием 32-битной формы для 64-битных регистров в cmp_reg_imm)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# Глобальная переменная для имени исходного файла
|
||||||
|
source_filename = ""
|
||||||
|
|
||||||
|
def safe_close(f):
|
||||||
|
if f is not None:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# === Глобальные данные ===
|
||||||
|
INSTRUCTIONS = {
|
||||||
|
"переместить_имм": {"code": None, "type": "reg_imm"},
|
||||||
|
"сравнить_с": {"code": None, "type": "cmp_reg_imm"},
|
||||||
|
"переход_если_неравно": {"code": b"\x0F\x85", "type": "jcc"},
|
||||||
|
"переход_если_равно": {"code": b"\x0F\x84", "type": "jcc"}, # je / jz
|
||||||
|
"переход_если_меньше": {"code": b"\x0F\x8C", "type": "jcc"}, # jl
|
||||||
|
"переход_если_больше": {"code": b"\x0F\x8F", "type": "jcc"}, # jg
|
||||||
|
"переход_если_меньше_или_равно": {"code": b"\x0F\x8E", "type": "jcc"}, # jle
|
||||||
|
"переход_если_больше_или_равно": {"code": b"\x0F\x8D", "type": "jcc"}, # jge
|
||||||
|
"переход_если_перенос": {"code": b"\x0F\x82", "type": "jcc"}, # jc
|
||||||
|
"переход_если_нет_переноса": {"code": b"\x0F\x83", "type": "jcc"}, # jnc
|
||||||
|
"переход_если_ноль": {"code": b"\x0F\x84", "type": "jcc"}, # jz (дубль JE)
|
||||||
|
"переход_если_не_ноль": {"code": b"\x0F\x85", "type": "jcc"}, # jnz (дубль JNE)
|
||||||
|
"вызов_системы": {"code": b"\x0F\x05", "type": "none"},
|
||||||
|
"переход": {"code": b"\xE9", "type": "jmp"},
|
||||||
|
# === Короткие переходы ===
|
||||||
|
"короткий_переход": {"code": b"\xEB", "type": "short_jmp"},
|
||||||
|
"короткий_переход_если_равно" : {"code": b"\x74", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_неравно" : {"code": b"\x75", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_меньше" : {"code": b"\x7C", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_больше" : {"code": b"\x7F", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_меньше_или_равно": {"code": b"\x7E", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_больше_или_равно": {"code": b"\x7D", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_перенос" : {"code": b"\x72", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_нет_переноса" : {"code": b"\x73", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_ноль" : {"code": b"\x74", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_не_ноль" : {"code": b"\x75", "type": "short_jcc"},
|
||||||
|
# === Новые команды для флагов ===
|
||||||
|
"сравнить": {"code": b"\x48\x39", "type": "cmp_reg_reg"},
|
||||||
|
"проверить": {"code": b"\x48\x85", "type": "test_reg_reg"},
|
||||||
|
"вычесть": {"code": b"\x48\x29", "type": "sub_reg_reg"},
|
||||||
|
"прибавить": {"code": b"\x48\x01", "type": "add_reg_reg"},
|
||||||
|
"увеличить": {"code": b"\xFF", "subop": 0, "type": "incdec"},
|
||||||
|
"уменьшить": {"code": b"\xFF", "subop": 1, "type": "incdec"},
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTERS = {
|
||||||
|
# 64-битные
|
||||||
|
"раикс": 0, "рсикс": 1, "рдикс": 2, "рбикс": 3,
|
||||||
|
"рсипи": 4, "рбипи": 5, "рсиай": 6, "рдиай": 7,
|
||||||
|
"р8": 8, "р9": 9, "р10": 10, "р11": 11,
|
||||||
|
"р12": 12, "р13": 13, "р14": 14, "р15": 15,
|
||||||
|
# 32-битные
|
||||||
|
"еаикс": 0, "есикс": 1, "едикс": 2, "ебикс": 3,
|
||||||
|
"есипи": 4, "ебипи": 5, "есиай": 6, "едиай": 7,
|
||||||
|
"р8д": 8, "р9д": 9, "р10д": 10, "р11д": 11,
|
||||||
|
"р12д": 12, "р13д": 13, "р14д": 14, "р15д": 15,
|
||||||
|
# 16-битные
|
||||||
|
"аикс": 0, "сикс": 1, "дикс": 2, "бикс": 3,
|
||||||
|
"эсп": 4, "бипи": 5, "эс": 6, "ди": 7,
|
||||||
|
"р8в": 8, "р9в": 9, "р10в": 10, "р11в": 11,
|
||||||
|
"р12в": 12, "р13в": 13, "р14в": 14, "р15в": 15,
|
||||||
|
# 8-битные младшие
|
||||||
|
"ал": 0, "кл": 1, "дл": 2, "бл": 3,
|
||||||
|
"спл": 4, "бпл": 5, "сил": 6, "дил": 7,
|
||||||
|
"р8б": 8, "р9б": 9, "р10б": 10, "р11б": 11,
|
||||||
|
"р12б": 12, "р13б": 13, "р14б": 14, "р15б": 15,
|
||||||
|
# 8-битные старшие (только первые 4)
|
||||||
|
"аш": 0, "чш": 1, "дш": 2, "бш": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Глобальное состояние ассемблера
|
||||||
|
labels = {}
|
||||||
|
label_sections = {}
|
||||||
|
symbols = {}
|
||||||
|
sections = {".text": bytearray(), ".data": bytearray()}
|
||||||
|
current_section = ".text"
|
||||||
|
entry_point = "_start"
|
||||||
|
position = {".text": 0, ".data": 0}
|
||||||
|
pass_num = 0
|
||||||
|
|
||||||
|
# === Для логирования ===
|
||||||
|
log_entries = []
|
||||||
|
|
||||||
|
# === ELF layout ===
|
||||||
|
PAGE_SIZE = 0x1000
|
||||||
|
elf_base_vaddr = 0x400000
|
||||||
|
text_vaddr_base = 0x401000
|
||||||
|
data_vaddr_base = 0x402000
|
||||||
|
|
||||||
|
text_size = 0
|
||||||
|
data_size = 0
|
||||||
|
comment_size = 0
|
||||||
|
offset_text = 0
|
||||||
|
offset_data = 0
|
||||||
|
offset_comment = 0
|
||||||
|
shstrtab_offset = 0
|
||||||
|
shdr_offset = 0
|
||||||
|
vaddr_text = 0
|
||||||
|
vaddr_data = 0
|
||||||
|
|
||||||
|
def align_up(x, align):
|
||||||
|
return (x + align - 1) & ~(align - 1)
|
||||||
|
|
||||||
|
def get_reg_info(reg_name):
|
||||||
|
if reg_name in ["аш", "чш", "дш", "бш"]:
|
||||||
|
return {"size": 8, "index": REGISTERS[reg_name], "high8": True}
|
||||||
|
elif reg_name.endswith(("б", "л")) or reg_name in ["ал", "кл", "дл", "бл", "спл", "бпл", "сил", "дил"]:
|
||||||
|
return {"size": 8, "index": REGISTERS[reg_name], "high8": False}
|
||||||
|
elif reg_name.endswith("в") or reg_name in ["аикс", "сикс", "дикс", "бикс", "эсп", "бипи", "эс", "ди"]:
|
||||||
|
return {"size": 16, "index": REGISTERS[reg_name]}
|
||||||
|
elif reg_name.endswith("д") or reg_name in ["еаикс", "есикс", "едикс", "ебикс", "есипи", "ебипи", "есиай", "едиай"]:
|
||||||
|
return {"size": 32, "index": REGISTERS[reg_name]}
|
||||||
|
else:
|
||||||
|
return {"size": 64, "index": REGISTERS[reg_name]}
|
||||||
|
|
||||||
|
# === Функции формирования ошибок ===
|
||||||
|
def make_error_msg(line_num, line_text, detail):
|
||||||
|
return "Ошибка в файле " + source_filename + ", строка " + str(line_num) + ":\n " + line_text + "\n" + detail
|
||||||
|
|
||||||
|
def error_invalid_operand_count(mnemonic, expected, got):
|
||||||
|
return "Инструкция '" + mnemonic + "':\n ожидается " + str(expected) + " операнд(а/ов), получено: " + str(got)
|
||||||
|
|
||||||
|
def error_unknown_mnemonic(mnemonic):
|
||||||
|
return "Неизвестная инструкция: '" + mnemonic + "'"
|
||||||
|
|
||||||
|
def error_invalid_register(op_name, reg_name, mnemonic):
|
||||||
|
return ("Инструкция '" + mnemonic + "':\n операнд '" + op_name + "' = '" + reg_name +
|
||||||
|
"' не является допустимым регистром.\n Допустимые регистры: " + ", ".join(list(REGISTERS.keys())))
|
||||||
|
|
||||||
|
def error_invalid_number_format(s):
|
||||||
|
return "Недопустимый формат числа: '" + s + "'"
|
||||||
|
|
||||||
|
def error_unknown_directive(word):
|
||||||
|
return "Неизвестная директива: '" + word + "'"
|
||||||
|
|
||||||
|
def error_missing_label(label):
|
||||||
|
return "Метка не найдена: '" + label + "'"
|
||||||
|
|
||||||
|
def error_unexpected_string_in_byte():
|
||||||
|
return ".байт требует числовые значения, не строки"
|
||||||
|
|
||||||
|
def error_unterminated_string():
|
||||||
|
return "Незакрытая кавычка в строке"
|
||||||
|
|
||||||
|
# === Лексер ===
|
||||||
|
def tokenize_line(line):
|
||||||
|
semi = line.find(';')
|
||||||
|
if semi != -1:
|
||||||
|
line = line[:semi]
|
||||||
|
line = line.rstrip()
|
||||||
|
if not line:
|
||||||
|
return []
|
||||||
|
tokens = []
|
||||||
|
i = 0
|
||||||
|
n = len(line)
|
||||||
|
while i < n:
|
||||||
|
ch = line[i]
|
||||||
|
if ch.isspace():
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if ch == '"':
|
||||||
|
i += 1
|
||||||
|
s = ''
|
||||||
|
while i < n and line[i] != '"':
|
||||||
|
if line[i] == '\\' and i + 1 < n:
|
||||||
|
i += 1
|
||||||
|
esc = line[i]
|
||||||
|
if esc == 'n':
|
||||||
|
s += '\n'
|
||||||
|
elif esc == 't':
|
||||||
|
s += '\t'
|
||||||
|
elif esc == '"':
|
||||||
|
s += '"'
|
||||||
|
elif esc == '\\':
|
||||||
|
s += '\\'
|
||||||
|
else:
|
||||||
|
s += '\\' + esc
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
s += line[i]
|
||||||
|
i += 1
|
||||||
|
if i >= n:
|
||||||
|
raise ValueError(error_unterminated_string())
|
||||||
|
i += 1
|
||||||
|
tokens.append(('string', s))
|
||||||
|
continue
|
||||||
|
if ch == ',':
|
||||||
|
tokens.append(('comma', ','))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if ch == ':':
|
||||||
|
tokens.append(('colon', ':'))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
j = i
|
||||||
|
while j < n and not (line[j].isspace() or line[j] in ',:;'):
|
||||||
|
j += 1
|
||||||
|
word = line[i:j]
|
||||||
|
if word:
|
||||||
|
tokens.append(('word', word))
|
||||||
|
i = j
|
||||||
|
return tokens
|
||||||
|
|
||||||
|
# === Парсинг ===
|
||||||
|
def parse_operand(operand):
|
||||||
|
if operand.isdigit():
|
||||||
|
return int(operand)
|
||||||
|
if operand.startswith("0x"):
|
||||||
|
return int(operand, 16)
|
||||||
|
if operand in labels:
|
||||||
|
section = label_sections[operand]
|
||||||
|
if pass_num == 2:
|
||||||
|
base = vaddr_text if section == ".text" else vaddr_data
|
||||||
|
return labels[operand] + base
|
||||||
|
else:
|
||||||
|
return labels[operand]
|
||||||
|
if operand in symbols:
|
||||||
|
return symbols[operand]
|
||||||
|
raise ValueError("Неизвестный операнд: " + operand)
|
||||||
|
|
||||||
|
def encode_instruction(mnemonic, operands, line_num, line_text):
|
||||||
|
instr = INSTRUCTIONS[mnemonic]
|
||||||
|
code = bytearray()
|
||||||
|
itype = instr["type"]
|
||||||
|
|
||||||
|
if itype == "none":
|
||||||
|
code.extend(instr["code"])
|
||||||
|
|
||||||
|
elif itype == "reg_imm":
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("назначения", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
size = reg_info["size"]
|
||||||
|
imm = parse_operand(operands[1])
|
||||||
|
|
||||||
|
if size == 64:
|
||||||
|
if 0 <= reg <= 7:
|
||||||
|
code.extend(b'\x48')
|
||||||
|
code.append(0xB8 + reg)
|
||||||
|
code.extend(struct.pack('<Q', imm))
|
||||||
|
elif 8 <= reg <= 15:
|
||||||
|
code.extend(b'\x49')
|
||||||
|
code.append(0xB8 + (reg - 8))
|
||||||
|
code.extend(struct.pack('<Q', imm))
|
||||||
|
else:
|
||||||
|
raise ValueError("Недопустимый регистр в '" + mnemonic + "'")
|
||||||
|
elif size == 32:
|
||||||
|
if -0x80000000 <= imm <= 0x7FFFFFFF:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xC7)
|
||||||
|
modrm = 0xC0 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.extend(struct.pack('<I', imm & 0xFFFFFFFF))
|
||||||
|
else:
|
||||||
|
raise ValueError("32-битное значение вне диапазона")
|
||||||
|
elif size == 16:
|
||||||
|
if 0 <= imm <= 0xFFFF:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xC7)
|
||||||
|
modrm = 0xC0 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
code.append((imm >> 8) & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("16-битное значение вне диапазона")
|
||||||
|
elif size == 8:
|
||||||
|
if not (0 <= imm <= 255):
|
||||||
|
raise ValueError("8-битное значение вне диапазона 0–255")
|
||||||
|
if reg_info.get("high8"):
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xB0 + reg + 4)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Старшие байты только для первых 4 регистров")
|
||||||
|
else:
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xB0 + reg)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xB0 + (reg & 7))
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый размер регистра")
|
||||||
|
|
||||||
|
elif itype == "cmp_reg_imm":
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("регистра", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
size = reg_info["size"]
|
||||||
|
imm = parse_operand(operands[1])
|
||||||
|
|
||||||
|
# --- ИЗМЕНЕНИЕ: Всегда используем 32-битную форму для 64-битных регистров, если imm помещается ---
|
||||||
|
if size == 64:
|
||||||
|
if -0x80000000 <= imm <= 0x7FFFFFFF:
|
||||||
|
# Используем 32-битное сравнение (с REX.W для 64-битного регистра)
|
||||||
|
rex = 0x48
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x81) # cmp r/m64, imm32
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.extend(struct.pack('<i', imm)) # imm32 sign-extended
|
||||||
|
else:
|
||||||
|
raise ValueError("Непосредственное значение слишком велико для сравнения: " + str(imm))
|
||||||
|
elif size == 32:
|
||||||
|
if -128 <= imm <= 127:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x83)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
elif -0x80000000 <= imm <= 0x7FFFFFFF:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x81)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.extend(struct.pack('<I', imm & 0xFFFFFFFF))
|
||||||
|
else:
|
||||||
|
raise ValueError("32-битное непосредственное значение вне диапазона")
|
||||||
|
elif size == 16:
|
||||||
|
if -128 <= imm <= 127:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x83)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
elif 0 <= imm <= 0xFFFF:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x81)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
code.append((imm >> 8) & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("16-битное непосредственное значение вне диапазона")
|
||||||
|
elif size == 8:
|
||||||
|
if not (0 <= imm <= 255):
|
||||||
|
raise ValueError("8-битное значение вне диапазона 0–255")
|
||||||
|
if reg_info.get("high8"):
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0x80)
|
||||||
|
modrm = 0xF8 | reg
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Старшие байты только для первых 4 регистров")
|
||||||
|
else:
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0x80)
|
||||||
|
modrm = 0xF8 | reg
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x80)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый размер регистра")
|
||||||
|
|
||||||
|
elif itype == "jmp":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 5)
|
||||||
|
if offset < -0x80000000 or offset > 0x7FFFFFFF:
|
||||||
|
raise ValueError("Цель слишком далеко для 32-битного смещения в инструкции '" + mnemonic + "': " + str(offset))
|
||||||
|
code.extend(struct.pack('<i', offset))
|
||||||
|
|
||||||
|
elif itype == "jcc":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 6)
|
||||||
|
if offset < -0x80000000 or offset > 0x7FFFFFFF:
|
||||||
|
raise ValueError("Цель условного перехода слишком далеко: " + str(offset))
|
||||||
|
code.extend(struct.pack('<i', offset))
|
||||||
|
|
||||||
|
elif itype == "short_jmp":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 2)
|
||||||
|
if offset < -128 or offset > 127:
|
||||||
|
raise ValueError("Цель слишком далеко для короткого перехода: " + str(offset))
|
||||||
|
code.append(0xEB)
|
||||||
|
code.append(offset & 0xFF)
|
||||||
|
|
||||||
|
elif itype == "short_jcc":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 2)
|
||||||
|
if offset < -128 or offset > 127:
|
||||||
|
raise ValueError("Цель слишком далеко для короткого условного перехода: " + str(offset))
|
||||||
|
code.append(offset & 0xFF)
|
||||||
|
|
||||||
|
elif itype in ("cmp_reg_reg", "test_reg_reg", "add_reg_reg", "sub_reg_reg"):
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
dst_info = get_reg_info(operands[0])
|
||||||
|
src_info = get_reg_info(operands[1])
|
||||||
|
if dst_info is None:
|
||||||
|
raise ValueError(error_invalid_register("назначения", operands[0], mnemonic))
|
||||||
|
if src_info is None:
|
||||||
|
raise ValueError(error_invalid_register("источника", operands[1], mnemonic))
|
||||||
|
dst = dst_info["index"]
|
||||||
|
src = src_info["index"]
|
||||||
|
size = dst_info["size"]
|
||||||
|
if size != src_info["size"]:
|
||||||
|
raise ValueError("Размеры операндов не совпадают в инструкции '" + mnemonic + "'")
|
||||||
|
|
||||||
|
use_66 = (size == 16)
|
||||||
|
use_rex_w = (size == 64)
|
||||||
|
rex = 0x40
|
||||||
|
if use_rex_w:
|
||||||
|
rex |= 0x08
|
||||||
|
if src >= 8:
|
||||||
|
rex |= 0x04
|
||||||
|
if dst >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if dst_info.get("high8") or src_info.get("high8"):
|
||||||
|
if rex != 0x40:
|
||||||
|
raise ValueError("Старшие байты несовместимы с REX")
|
||||||
|
rex = 0
|
||||||
|
|
||||||
|
op_map = {
|
||||||
|
"cmp_reg_reg": 0x39,
|
||||||
|
"test_reg_reg": 0x85,
|
||||||
|
"add_reg_reg": 0x01,
|
||||||
|
"sub_reg_reg": 0x29,
|
||||||
|
}
|
||||||
|
op = op_map[itype]
|
||||||
|
|
||||||
|
if use_66:
|
||||||
|
code.append(0x66)
|
||||||
|
if rex != 0x40 or use_rex_w:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(op)
|
||||||
|
modrm = 0xC0 | ((src & 7) << 3) | (dst & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
|
||||||
|
elif itype == "incdec":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("регистра", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
size = reg_info["size"]
|
||||||
|
subop = instr["subop"]
|
||||||
|
|
||||||
|
if size == 64:
|
||||||
|
rex = 0x48
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFF)
|
||||||
|
elif size == 32:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFF)
|
||||||
|
elif size == 16:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFF)
|
||||||
|
elif size == 8:
|
||||||
|
if reg_info.get("high8"):
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xFE)
|
||||||
|
else:
|
||||||
|
raise ValueError("Старшие байты только для первых 4 регистров")
|
||||||
|
else:
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xFE)
|
||||||
|
else:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFE)
|
||||||
|
modrm = 0xC0 | (subop << 3) | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
return bytes(code)
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый размер регистра")
|
||||||
|
|
||||||
|
modrm = 0xC0 | (subop << 3) | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError("Неизвестный тип инструкции: " + itype)
|
||||||
|
|
||||||
|
return bytes(code)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parse_instruction_or_directive(tokens, line_num, line_text):
|
||||||
|
global current_section, entry_point, symbols # Не забудьте добавить symbols в global
|
||||||
|
first = tokens[0]
|
||||||
|
if first[0] != 'word':
|
||||||
|
raise ValueError("Ожидалось слово, получено: " + str(first))
|
||||||
|
word = first[1]
|
||||||
|
if word.startswith('.'):
|
||||||
|
if word == '.текст':
|
||||||
|
current_section = ".text"
|
||||||
|
elif word == '.данные':
|
||||||
|
current_section = ".data"
|
||||||
|
elif word == '.глобал':
|
||||||
|
if len(tokens) < 2 or tokens[1][0] != 'word':
|
||||||
|
raise ValueError(".глобал требует имя метки")
|
||||||
|
entry_point = tokens[1][1]
|
||||||
|
elif word == '.строка_нуль' or word == '.строка':
|
||||||
|
if len(tokens) < 2 or tokens[1][0] != 'string':
|
||||||
|
raise ValueError(word + " требует строку в кавычках")
|
||||||
|
if current_section != ".data":
|
||||||
|
raise ValueError("Строки разрешены только в секции .data")
|
||||||
|
s = tokens[1][1]
|
||||||
|
bstring = s.encode('utf-8')
|
||||||
|
add_null = (word == '.строка_нуль')
|
||||||
|
size = len(bstring) + (1 if add_null else 0)
|
||||||
|
if pass_num == 1:
|
||||||
|
position[".data"] += size
|
||||||
|
elif pass_num == 2:
|
||||||
|
sections[".data"] += bstring
|
||||||
|
if add_null:
|
||||||
|
sections[".data"] += b'\x00'
|
||||||
|
position[".data"] += size
|
||||||
|
# === НОВАЯ ДИРЕКТИВА .КОНСТАНТА ===
|
||||||
|
elif word == '.константа':
|
||||||
|
if len(tokens) < 3 or tokens[1][0] != 'word' or tokens[2][0] != 'word' or tokens[2][1] != '=' or len(tokens) < 4 or tokens[3][0] not in ('word', 'string'): # Проверяем формат: .константа имя = значение
|
||||||
|
raise ValueError(".константа требует формат: .константа <имя> = <значение>")
|
||||||
|
const_name = tokens[1][1]
|
||||||
|
const_value_str = tokens[3][1]
|
||||||
|
try:
|
||||||
|
# Попробуем распарсить значение как число или символ (если это метка)
|
||||||
|
const_value = parse_operand(const_value_str)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Невозможно распознать значение константы '" + const_value_str + "'")
|
||||||
|
|
||||||
|
# Записываем в глобальный словарь символов
|
||||||
|
symbols[const_name] = const_value
|
||||||
|
# Директива .константа не добавляет байты в секцию
|
||||||
|
return
|
||||||
|
# === КОНЕЦ НОВОЙ ДИРЕКТИВЫ ===
|
||||||
|
else:
|
||||||
|
raise ValueError(error_unknown_directive(word))
|
||||||
|
return
|
||||||
|
|
||||||
|
mnemonic = word
|
||||||
|
if mnemonic not in INSTRUCTIONS:
|
||||||
|
raise ValueError(error_unknown_mnemonic(mnemonic))
|
||||||
|
|
||||||
|
operands = []
|
||||||
|
for tok in tokens[1:]:
|
||||||
|
if tok[0] == 'word':
|
||||||
|
operands.append(tok[1])
|
||||||
|
elif tok[0] == 'comma':
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raise ValueError("Недопустимый токен в операндах: " + str(tok))
|
||||||
|
|
||||||
|
if pass_num == 2:
|
||||||
|
instr_info = INSTRUCTIONS[mnemonic]
|
||||||
|
itype = instr_info["type"]
|
||||||
|
code = encode_instruction(mnemonic, operands, line_num, line_text)
|
||||||
|
start_pos = position[current_section]
|
||||||
|
|
||||||
|
if current_section == ".text":
|
||||||
|
start_vaddr = vaddr_text + start_pos
|
||||||
|
target_addr = ""
|
||||||
|
try:
|
||||||
|
if itype in ("jmp", "jcc", "short_jmp", "short_jcc"):
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
target_addr = hex(target)
|
||||||
|
elif itype == "reg_imm":
|
||||||
|
op_str = operands[1]
|
||||||
|
if op_str in labels:
|
||||||
|
sec = label_sections[op_str]
|
||||||
|
addr = labels[op_str] + (vaddr_text if sec == ".text" else vaddr_data)
|
||||||
|
target_addr = hex(addr)
|
||||||
|
elif op_str in symbols: # Проверяем символы
|
||||||
|
target_addr = hex(symbols[op_str])
|
||||||
|
except Exception:
|
||||||
|
target_addr = "ошибка"
|
||||||
|
|
||||||
|
original_cmd = line_text.split(';')[0].strip()
|
||||||
|
for i, byte in enumerate(code):
|
||||||
|
addr = start_vaddr + i
|
||||||
|
byte_hex = "{:02X}".format(byte)
|
||||||
|
cmd_to_log = original_cmd if i == 0 else ""
|
||||||
|
log_entries.append((hex(addr), byte_hex, target_addr if i == 0 else "", cmd_to_log))
|
||||||
|
|
||||||
|
sections[current_section] += code
|
||||||
|
position[current_section] += len(code)
|
||||||
|
else:
|
||||||
|
instr_info = INSTRUCTIONS[mnemonic]
|
||||||
|
itype = instr_info["type"]
|
||||||
|
size_map = {
|
||||||
|
"reg_imm": 10,
|
||||||
|
"cmp_reg_imm": 7, # 6 байт для REX.W + 0x81 + ModR/M + imm32
|
||||||
|
"jmp": 5,
|
||||||
|
"jcc": 6,
|
||||||
|
"none": lambda: len(instr_info["code"]),
|
||||||
|
"short_jmp": 2,
|
||||||
|
"short_jcc": 2,
|
||||||
|
"cmp_reg_reg": 3,
|
||||||
|
"test_reg_reg": 3,
|
||||||
|
"add_reg_reg": 3,
|
||||||
|
"sub_reg_reg": 3,
|
||||||
|
"incdec": 3,
|
||||||
|
}
|
||||||
|
if itype in size_map:
|
||||||
|
sz = size_map[itype]
|
||||||
|
position[current_section] += sz() if callable(sz) else sz
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый тип инструкции при подсчёте размера: " + itype)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parse_tokens(tokens, line_num, line_text):
|
||||||
|
if not tokens:
|
||||||
|
return
|
||||||
|
if len(tokens) >= 2 and tokens[0][0] == 'word' and tokens[1][0] == 'colon':
|
||||||
|
label = tokens[0][1]
|
||||||
|
labels[label] = position[current_section]
|
||||||
|
label_sections[label] = current_section
|
||||||
|
rest = tokens[2:]
|
||||||
|
if rest:
|
||||||
|
parse_instruction_or_directive(rest, line_num, line_text)
|
||||||
|
return
|
||||||
|
parse_instruction_or_directive(tokens, line_num, line_text)
|
||||||
|
|
||||||
|
def parse(source):
|
||||||
|
global pass_num, text_size, data_size, comment_size
|
||||||
|
global offset_text, offset_data, offset_comment, shstrtab_offset, shdr_offset
|
||||||
|
global vaddr_text, vaddr_data
|
||||||
|
global sections, position, log_entries
|
||||||
|
|
||||||
|
log_entries = []
|
||||||
|
lines = source.split('\n')
|
||||||
|
|
||||||
|
# ПРОХОД 1
|
||||||
|
pass_num = 1
|
||||||
|
position[".text"] = 0
|
||||||
|
position[".data"] = 0
|
||||||
|
labels.clear()
|
||||||
|
label_sections.clear()
|
||||||
|
|
||||||
|
for line_num, line in enumerate(lines, start=1):
|
||||||
|
original_line = line.rstrip()
|
||||||
|
try:
|
||||||
|
tokens = tokenize_line(line)
|
||||||
|
parse_tokens(tokens, line_num, original_line)
|
||||||
|
except Exception as e:
|
||||||
|
error_full = make_error_msg(line_num, original_line, str(e))
|
||||||
|
print(error_full, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
text_size_pass1 = position[".text"]
|
||||||
|
data_size_pass1 = position[".data"]
|
||||||
|
print("ПРОХОД 1: text_size=" + str(text_size_pass1) + " bytes, data_size=" + str(data_size_pass1) + " bytes")
|
||||||
|
|
||||||
|
# РАЗМЕЩЕНИЕ
|
||||||
|
elf_header_size = 64
|
||||||
|
ph_size = 56
|
||||||
|
ph_num = 3
|
||||||
|
ph_table_size = ph_num * ph_size
|
||||||
|
|
||||||
|
offset_text = align_up(elf_header_size + ph_table_size, PAGE_SIZE)
|
||||||
|
offset_data = align_up(offset_text + text_size_pass1, PAGE_SIZE)
|
||||||
|
vaddr_text = text_vaddr_base
|
||||||
|
vaddr_data = align_up(vaddr_text + text_size_pass1, PAGE_SIZE)
|
||||||
|
|
||||||
|
comment_content = "Сборщик КВС".encode('utf-8') + b'\x00'
|
||||||
|
comment_size = len(comment_content)
|
||||||
|
offset_comment = align_up(offset_data + data_size_pass1, 1)
|
||||||
|
|
||||||
|
shstrtab_content = b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00"
|
||||||
|
shstrtab_size = len(shstrtab_content)
|
||||||
|
shstrtab_offset = align_up(offset_comment + comment_size, 8)
|
||||||
|
shdr_size = 64
|
||||||
|
shdr_num = 5
|
||||||
|
shdr_offset = align_up(shstrtab_offset + shstrtab_size, 16)
|
||||||
|
|
||||||
|
print("РАЗМЕЩЕНИЕ: .text at offset=" + hex(offset_text) + ", .data at offset=" + hex(offset_data))
|
||||||
|
print("ВИРТУАЛЬНЫЕ АДРЕСА: .text at " + hex(vaddr_text) + ", .data at " + hex(vaddr_data))
|
||||||
|
print("РАССТОЯНИЕ МЕЖДУ СЕКЦИЯМИ: " + hex(vaddr_data - vaddr_text) + " bytes")
|
||||||
|
|
||||||
|
sections[".comment"] = comment_content
|
||||||
|
|
||||||
|
# ПРОХОД 2
|
||||||
|
pass_num = 2
|
||||||
|
position[".text"] = 0
|
||||||
|
position[".data"] = 0
|
||||||
|
sections[".text"] = bytearray()
|
||||||
|
sections[".data"] = bytearray()
|
||||||
|
|
||||||
|
for line_num, line in enumerate(lines, start=1):
|
||||||
|
original_line = line.rstrip()
|
||||||
|
try:
|
||||||
|
tokens = tokenize_line(line)
|
||||||
|
parse_tokens(tokens, line_num, original_line)
|
||||||
|
except Exception as e:
|
||||||
|
error_full = make_error_msg(line_num, original_line, str(e))
|
||||||
|
print(error_full, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
text_size_pass2 = len(sections[".text"])
|
||||||
|
data_size_pass2 = len(sections[".data"])
|
||||||
|
print("ПРОХОД 2: text_size=" + str(text_size_pass2) + " bytes, data_size=" + str(data_size_pass2) + " bytes")
|
||||||
|
|
||||||
|
if text_size_pass1 != text_size_pass2:
|
||||||
|
print("ПРЕДУПРЕЖДЕНИЕ: Размер .text изменился между проходами: " + str(text_size_pass1) + " -> " + str(text_size_pass2))
|
||||||
|
if data_size_pass1 != data_size_pass2:
|
||||||
|
print("ПРЕДУПРЕЖДЕНИЕ: Размер .data изменился между проходами: " + str(data_size_pass1) + " -> " + str(data_size_pass2))
|
||||||
|
|
||||||
|
text_size = text_size_pass2
|
||||||
|
data_size = data_size_pass2
|
||||||
|
|
||||||
|
def create_elf(filename):
|
||||||
|
global sections, entry_point, labels, vaddr_text, vaddr_data
|
||||||
|
global offset_text, offset_data, offset_comment, shstrtab_offset, shdr_offset
|
||||||
|
|
||||||
|
text = sections[".text"]
|
||||||
|
data = sections[".data"]
|
||||||
|
comment = sections[".comment"]
|
||||||
|
|
||||||
|
actual_text_size = len(text)
|
||||||
|
actual_data_size = len(data)
|
||||||
|
expected_vaddr_data = align_up(vaddr_text + actual_text_size, PAGE_SIZE)
|
||||||
|
if vaddr_data != expected_vaddr_data:
|
||||||
|
print("КОРРЕКЦИЯ: vaddr_data исправлен с " + hex(vaddr_data) + " на " + hex(expected_vaddr_data))
|
||||||
|
vaddr_data = expected_vaddr_data
|
||||||
|
|
||||||
|
print("ФАКТИЧЕСКИЕ РАЗМЕРЫ: .text=" + str(actual_text_size) + ", .data=" + str(actual_data_size))
|
||||||
|
print("КОНЕЧНЫЕ АДРЕСА: .text ends at " + hex(vaddr_text + actual_text_size) + ", .data starts at " + hex(vaddr_data))
|
||||||
|
print("ПРОВЕРКА ПЕРЕКРЫТИЯ: " + ("ПЕРЕКРЫТИЕ!" if (vaddr_text + actual_text_size) > vaddr_data else "OK"))
|
||||||
|
|
||||||
|
entry_addr = vaddr_text + labels.get(entry_point, 0)
|
||||||
|
|
||||||
|
shstrtab_content = b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00"
|
||||||
|
shstrtab_size = len(shstrtab_content)
|
||||||
|
|
||||||
|
elf_header_size = 64
|
||||||
|
ph_size = 56
|
||||||
|
ph_num = 3
|
||||||
|
shdr_size = 64
|
||||||
|
shdr_num = 5
|
||||||
|
|
||||||
|
file_size = shdr_offset + shdr_num * shdr_size
|
||||||
|
elf_data = bytearray(file_size)
|
||||||
|
|
||||||
|
# ELF header
|
||||||
|
e_ident = b"\x7fELF\x02\x01\x01\x00" + b"\x00" * 8
|
||||||
|
elf_header = struct.pack(
|
||||||
|
'<16sHHIQQQIHHHHHH',
|
||||||
|
e_ident,
|
||||||
|
2,
|
||||||
|
0x3e,
|
||||||
|
1,
|
||||||
|
entry_addr,
|
||||||
|
elf_header_size,
|
||||||
|
shdr_offset,
|
||||||
|
0,
|
||||||
|
elf_header_size,
|
||||||
|
ph_size,
|
||||||
|
ph_num,
|
||||||
|
shdr_size,
|
||||||
|
shdr_num,
|
||||||
|
4
|
||||||
|
)
|
||||||
|
elf_data[0:64] = elf_header
|
||||||
|
|
||||||
|
def phdr(p_type, p_flags, p_offset, p_vaddr, p_filesz, p_memsz):
|
||||||
|
return struct.pack('<IIQQQQQQ',
|
||||||
|
p_type, p_flags,
|
||||||
|
p_offset, p_vaddr, p_vaddr,
|
||||||
|
p_filesz, p_memsz,
|
||||||
|
PAGE_SIZE
|
||||||
|
)
|
||||||
|
|
||||||
|
ph0 = phdr(1, 4, 0, elf_base_vaddr, elf_header_size + ph_num * ph_size, PAGE_SIZE)
|
||||||
|
ph1 = phdr(1, 5, offset_text, vaddr_text, len(text), align_up(len(text), PAGE_SIZE))
|
||||||
|
ph2 = phdr(1, 6, offset_data, vaddr_data, len(data), align_up(len(data), PAGE_SIZE))
|
||||||
|
|
||||||
|
phdrs = ph0 + ph1 + ph2
|
||||||
|
elf_data[elf_header_size : elf_header_size + len(phdrs)] = phdrs
|
||||||
|
|
||||||
|
elf_data[offset_text : offset_text + len(text)] = text
|
||||||
|
elf_data[offset_data : offset_data + len(data)] = data
|
||||||
|
elf_data[offset_comment : offset_comment + len(comment)] = comment
|
||||||
|
elf_data[shstrtab_offset : shstrtab_offset + shstrtab_size] = shstrtab_content
|
||||||
|
|
||||||
|
def shdr(name_idx, sh_type, flags, addr, offset, size, addralign=1):
|
||||||
|
return struct.pack('<IIQQQQIIQQ',
|
||||||
|
name_idx, sh_type, flags, addr, offset, size,
|
||||||
|
0, 0, addralign, 0
|
||||||
|
)
|
||||||
|
|
||||||
|
sh0 = shdr(0, 0, 0, 0, 0, 0)
|
||||||
|
sh1 = shdr(1, 1, 6, vaddr_text, offset_text, len(text), 16)
|
||||||
|
sh2 = shdr(7, 1, 3, vaddr_data, offset_data, len(data), 8)
|
||||||
|
sh3 = shdr(13, 1, 0, 0, offset_comment, len(comment), 1)
|
||||||
|
sh4 = shdr(22, 3, 0, 0, shstrtab_offset, shstrtab_size, 1)
|
||||||
|
|
||||||
|
shdrs = sh0 + sh1 + sh2 + sh3 + sh4
|
||||||
|
elf_data[shdr_offset : shdr_offset + len(shdrs)] = shdrs
|
||||||
|
|
||||||
|
f_out = open(filename, "wb")
|
||||||
|
f_out.write(elf_data)
|
||||||
|
f_out.close()
|
||||||
|
|
||||||
|
import os
|
||||||
|
os.chmod(filename, 0o755)
|
||||||
|
|
||||||
|
# === Основной запуск ===
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("Использование: python kvs_7.py <файл.квс>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
source_file = sys.argv[1]
|
||||||
|
source_filename = source_file
|
||||||
|
if not source_file.endswith('.квс'):
|
||||||
|
print("Ошибка: файл должен иметь расширение .квс")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
f_in = None
|
||||||
|
try:
|
||||||
|
f_in = open(source_file, "r", encoding="utf-8")
|
||||||
|
source = f_in.read()
|
||||||
|
f_in.close()
|
||||||
|
except FileNotFoundError:
|
||||||
|
safe_close(f_in)
|
||||||
|
print("Ошибка: файл '" + source_file + "' не найден.")
|
||||||
|
sys.exit(1)
|
||||||
|
except UnicodeDecodeError as e:
|
||||||
|
safe_close(f_in)
|
||||||
|
print("Ошибка кодировки в файле '" + source_file + "': " + str(e))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
parse(source)
|
||||||
|
elf_file = source_file[:-4] + ".elf"
|
||||||
|
create_elf(elf_file)
|
||||||
|
|
||||||
|
log_file = source_file[:-4] + ".log.csv"
|
||||||
|
f_log = open(log_file, "w", encoding="utf-8")
|
||||||
|
f_log.write("адрес;байт;целевой_адрес;исходная_команда\n")
|
||||||
|
for addr, byte, target, cmd in log_entries:
|
||||||
|
if cmd and ('"' in cmd or ';' in cmd):
|
||||||
|
cmd = '"' + cmd.replace('"', '""') + '"'
|
||||||
|
f_log.write(addr + ";" + byte + ";" + target + ";" + cmd + "\n")
|
||||||
|
f_log.close()
|
||||||
|
print("Лог создан: " + log_file)
|
||||||
|
|
||||||
|
print("ELF-файл создан: " + elf_file)
|
||||||
|
print("Запустить: ./" + elf_file)
|
||||||
|
except SystemExit:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
print("Внутренняя ошибка ассемблера: " + str(e), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
936
jumps/kvs_8.py
Normal file
936
jumps/kvs_8.py
Normal file
|
|
@ -0,0 +1,936 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
kvs_8.py
|
||||||
|
КВС - язык программирования
|
||||||
|
без использования re
|
||||||
|
(расширенная версия с короткими и длинными переходами и полными регистрами)
|
||||||
|
(исправленная версия с использованием 32-битной формы для 64-битных регистров в cmp_reg_imm)
|
||||||
|
(добавлена команда нет_операции)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# Глобальная переменная для имени исходного файла
|
||||||
|
source_filename = ""
|
||||||
|
|
||||||
|
def safe_close(f):
|
||||||
|
if f is not None:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# === Глобальные данные ===
|
||||||
|
INSTRUCTIONS = {
|
||||||
|
"переместить_имм": {"code": None, "type": "reg_imm"},
|
||||||
|
"сравнить_с": {"code": None, "type": "cmp_reg_imm"},
|
||||||
|
"переход_если_неравно": {"code": b"\x0F\x85", "type": "jcc"},
|
||||||
|
"переход_если_равно": {"code": b"\x0F\x84", "type": "jcc"}, # je / jz
|
||||||
|
"переход_если_меньше": {"code": b"\x0F\x8C", "type": "jcc"}, # jl
|
||||||
|
"переход_если_больше": {"code": b"\x0F\x8F", "type": "jcc"}, # jg
|
||||||
|
"переход_если_меньше_или_равно": {"code": b"\x0F\x8E", "type": "jcc"}, # jle
|
||||||
|
"переход_если_больше_или_равно": {"code": b"\x0F\x8D", "type": "jcc"}, # jge
|
||||||
|
"переход_если_перенос": {"code": b"\x0F\x82", "type": "jcc"}, # jc
|
||||||
|
"переход_если_нет_переноса": {"code": b"\x0F\x83", "type": "jcc"}, # jnc
|
||||||
|
"переход_если_ноль": {"code": b"\x0F\x84", "type": "jcc"}, # jz (дубль JE)
|
||||||
|
"переход_если_не_ноль": {"code": b"\x0F\x85", "type": "jcc"}, # jnz (дубль JNE)
|
||||||
|
"вызов_системы": {"code": b"\x0F\x05", "type": "none"},
|
||||||
|
"переход": {"code": b"\xE9", "type": "jmp"},
|
||||||
|
# === Команда нет_операции ===
|
||||||
|
"нет_операции": {"code": b"\x90", "type": "none"},
|
||||||
|
# === Короткие переходы ===
|
||||||
|
"короткий_переход": {"code": b"\xEB", "type": "short_jmp"},
|
||||||
|
"короткий_переход_если_равно" : {"code": b"\x74", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_неравно" : {"code": b"\x75", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_меньше" : {"code": b"\x7C", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_больше" : {"code": b"\x7F", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_меньше_или_равно": {"code": b"\x7E", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_больше_или_равно": {"code": b"\x7D", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_перенос" : {"code": b"\x72", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_нет_переноса" : {"code": b"\x73", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_ноль" : {"code": b"\x74", "type": "short_jcc"},
|
||||||
|
"короткий_переход_если_не_ноль" : {"code": b"\x75", "type": "short_jcc"},
|
||||||
|
# === Новые команды для флагов ===
|
||||||
|
"сравнить": {"code": b"\x48\x39", "type": "cmp_reg_reg"},
|
||||||
|
"проверить": {"code": b"\x48\x85", "type": "test_reg_reg"},
|
||||||
|
"вычесть": {"code": b"\x48\x29", "type": "sub_reg_reg"},
|
||||||
|
"прибавить": {"code": b"\x48\x01", "type": "add_reg_reg"},
|
||||||
|
"увеличить": {"code": b"\xFF", "subop": 0, "type": "incdec"},
|
||||||
|
"уменьшить": {"code": b"\xFF", "subop": 1, "type": "incdec"},
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTERS = {
|
||||||
|
# 64-битные
|
||||||
|
"раикс": 0, "рсикс": 1, "рдикс": 2, "рбикс": 3,
|
||||||
|
"рсипи": 4, "рбипи": 5, "рсиай": 6, "рдиай": 7,
|
||||||
|
"р8": 8, "р9": 9, "р10": 10, "р11": 11,
|
||||||
|
"р12": 12, "р13": 13, "р14": 14, "р15": 15,
|
||||||
|
# 32-битные
|
||||||
|
"еаикс": 0, "есикс": 1, "едикс": 2, "ебикс": 3,
|
||||||
|
"есипи": 4, "ебипи": 5, "есиай": 6, "едиай": 7,
|
||||||
|
"р8д": 8, "р9д": 9, "р10д": 10, "р11д": 11,
|
||||||
|
"р12д": 12, "р13д": 13, "р14д": 14, "р15д": 15,
|
||||||
|
# 16-битные
|
||||||
|
"аикс": 0, "сикс": 1, "дикс": 2, "бикс": 3,
|
||||||
|
"эсп": 4, "бипи": 5, "эс": 6, "ди": 7,
|
||||||
|
"р8в": 8, "р9в": 9, "р10в": 10, "р11в": 11,
|
||||||
|
"р12в": 12, "р13в": 13, "р14в": 14, "р15в": 15,
|
||||||
|
# 8-битные младшие
|
||||||
|
"ал": 0, "кл": 1, "дл": 2, "бл": 3,
|
||||||
|
"спл": 4, "бпл": 5, "сил": 6, "дил": 7,
|
||||||
|
"р8б": 8, "р9б": 9, "р10б": 10, "р11б": 11,
|
||||||
|
"р12б": 12, "р13б": 13, "р14б": 14, "р15б": 15,
|
||||||
|
# 8-битные старшие (только первые 4)
|
||||||
|
"аш": 0, "чш": 1, "дш": 2, "бш": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Глобальное состояние ассемблера
|
||||||
|
labels = {}
|
||||||
|
label_sections = {}
|
||||||
|
symbols = {}
|
||||||
|
sections = {".text": bytearray(), ".data": bytearray()}
|
||||||
|
current_section = ".text"
|
||||||
|
entry_point = "_start"
|
||||||
|
position = {".text": 0, ".data": 0}
|
||||||
|
pass_num = 0
|
||||||
|
|
||||||
|
# === Для логирования ===
|
||||||
|
log_entries = []
|
||||||
|
|
||||||
|
# === ELF layout ===
|
||||||
|
PAGE_SIZE = 0x1000
|
||||||
|
elf_base_vaddr = 0x400000
|
||||||
|
text_vaddr_base = 0x401000
|
||||||
|
data_vaddr_base = 0x402000
|
||||||
|
|
||||||
|
text_size = 0
|
||||||
|
data_size = 0
|
||||||
|
comment_size = 0
|
||||||
|
offset_text = 0
|
||||||
|
offset_data = 0
|
||||||
|
offset_comment = 0
|
||||||
|
shstrtab_offset = 0
|
||||||
|
shdr_offset = 0
|
||||||
|
vaddr_text = 0
|
||||||
|
vaddr_data = 0
|
||||||
|
|
||||||
|
def align_up(x, align):
|
||||||
|
return (x + align - 1) & ~(align - 1)
|
||||||
|
|
||||||
|
def get_reg_info(reg_name):
|
||||||
|
if reg_name in ["аш", "чш", "дш", "бш"]:
|
||||||
|
return {"size": 8, "index": REGISTERS[reg_name], "high8": True}
|
||||||
|
elif reg_name.endswith(("б", "л")) or reg_name in ["ал", "кл", "дл", "бл", "спл", "бпл", "сил", "дил"]:
|
||||||
|
return {"size": 8, "index": REGISTERS[reg_name], "high8": False}
|
||||||
|
elif reg_name.endswith("в") or reg_name in ["аикс", "сикс", "дикс", "бикс", "эсп", "бипи", "эс", "ди"]:
|
||||||
|
return {"size": 16, "index": REGISTERS[reg_name]}
|
||||||
|
elif reg_name.endswith("д") or reg_name in ["еаикс", "есикс", "едикс", "ебикс", "есипи", "ебипи", "есиай", "едиай"]:
|
||||||
|
return {"size": 32, "index": REGISTERS[reg_name]}
|
||||||
|
else:
|
||||||
|
return {"size": 64, "index": REGISTERS[reg_name]}
|
||||||
|
|
||||||
|
# === Функции формирования ошибок ===
|
||||||
|
def make_error_msg(line_num, line_text, detail):
|
||||||
|
return "Ошибка в файле " + source_filename + ", строка " + str(line_num) + ":\n " + line_text + "\n" + detail
|
||||||
|
|
||||||
|
def error_invalid_operand_count(mnemonic, expected, got):
|
||||||
|
return "Инструкция '" + mnemonic + "':\n ожидается " + str(expected) + " операнд(а/ов), получено: " + str(got)
|
||||||
|
|
||||||
|
def error_unknown_mnemonic(mnemonic):
|
||||||
|
return "Неизвестная инструкция: '" + mnemonic + "'"
|
||||||
|
|
||||||
|
def error_invalid_register(op_name, reg_name, mnemonic):
|
||||||
|
return ("Инструкция '" + mnemonic + "':\n операнд '" + op_name + "' = '" + reg_name +
|
||||||
|
"' не является допустимым регистром.\n Допустимые регистры: " + ", ".join(list(REGISTERS.keys())))
|
||||||
|
|
||||||
|
def error_invalid_number_format(s):
|
||||||
|
return "Недопустимый формат числа: '" + s + "'"
|
||||||
|
|
||||||
|
def error_unknown_directive(word):
|
||||||
|
return "Неизвестная директива: '" + word + "'"
|
||||||
|
|
||||||
|
def error_missing_label(label):
|
||||||
|
return "Метка не найдена: '" + label + "'"
|
||||||
|
|
||||||
|
def error_unexpected_string_in_byte():
|
||||||
|
return ".байт требует числовые значения, не строки"
|
||||||
|
|
||||||
|
def error_unterminated_string():
|
||||||
|
return "Незакрытая кавычка в строке"
|
||||||
|
|
||||||
|
# === Лексер ===
|
||||||
|
def tokenize_line(line):
|
||||||
|
semi = line.find(';')
|
||||||
|
if semi != -1:
|
||||||
|
line = line[:semi]
|
||||||
|
line = line.rstrip()
|
||||||
|
if not line:
|
||||||
|
return []
|
||||||
|
tokens = []
|
||||||
|
i = 0
|
||||||
|
n = len(line)
|
||||||
|
while i < n:
|
||||||
|
ch = line[i]
|
||||||
|
if ch.isspace():
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if ch == '"':
|
||||||
|
i += 1
|
||||||
|
s = ''
|
||||||
|
while i < n and line[i] != '"':
|
||||||
|
if line[i] == '\\' and i + 1 < n:
|
||||||
|
i += 1
|
||||||
|
esc = line[i]
|
||||||
|
if esc == 'n':
|
||||||
|
s += '\n'
|
||||||
|
elif esc == 't':
|
||||||
|
s += '\t'
|
||||||
|
elif esc == '"':
|
||||||
|
s += '"'
|
||||||
|
elif esc == '\\':
|
||||||
|
s += '\\'
|
||||||
|
else:
|
||||||
|
s += '\\' + esc
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
s += line[i]
|
||||||
|
i += 1
|
||||||
|
if i >= n:
|
||||||
|
raise ValueError(error_unterminated_string())
|
||||||
|
i += 1
|
||||||
|
tokens.append(('string', s))
|
||||||
|
continue
|
||||||
|
if ch == ',':
|
||||||
|
tokens.append(('comma', ','))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if ch == ':':
|
||||||
|
tokens.append(('colon', ':'))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
j = i
|
||||||
|
while j < n and not (line[j].isspace() or line[j] in ',:;'):
|
||||||
|
j += 1
|
||||||
|
word = line[i:j]
|
||||||
|
if word:
|
||||||
|
tokens.append(('word', word))
|
||||||
|
i = j
|
||||||
|
return tokens
|
||||||
|
|
||||||
|
# === Парсинг ===
|
||||||
|
def parse_operand(operand):
|
||||||
|
if operand.isdigit():
|
||||||
|
return int(operand)
|
||||||
|
if operand.startswith("0x"):
|
||||||
|
return int(operand, 16)
|
||||||
|
if operand in labels:
|
||||||
|
section = label_sections[operand]
|
||||||
|
if pass_num == 2:
|
||||||
|
base = vaddr_text if section == ".text" else vaddr_data
|
||||||
|
return labels[operand] + base
|
||||||
|
else:
|
||||||
|
return labels[operand]
|
||||||
|
if operand in symbols:
|
||||||
|
return symbols[operand]
|
||||||
|
raise ValueError("Неизвестный операнд: " + operand)
|
||||||
|
|
||||||
|
def encode_instruction(mnemonic, operands, line_num, line_text):
|
||||||
|
instr = INSTRUCTIONS[mnemonic]
|
||||||
|
code = bytearray()
|
||||||
|
itype = instr["type"]
|
||||||
|
|
||||||
|
if itype == "none":
|
||||||
|
code.extend(instr["code"])
|
||||||
|
|
||||||
|
elif itype == "reg_imm":
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("назначения", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
size = reg_info["size"]
|
||||||
|
imm = parse_operand(operands[1])
|
||||||
|
|
||||||
|
if size == 64:
|
||||||
|
if 0 <= reg <= 7:
|
||||||
|
code.extend(b'\x48')
|
||||||
|
code.append(0xB8 + reg)
|
||||||
|
code.extend(struct.pack('<Q', imm))
|
||||||
|
elif 8 <= reg <= 15:
|
||||||
|
code.extend(b'\x49')
|
||||||
|
code.append(0xB8 + (reg - 8))
|
||||||
|
code.extend(struct.pack('<Q', imm))
|
||||||
|
else:
|
||||||
|
raise ValueError("Недопустимый регистр в '" + mnemonic + "'")
|
||||||
|
elif size == 32:
|
||||||
|
if -0x80000000 <= imm <= 0x7FFFFFFF:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xC7)
|
||||||
|
modrm = 0xC0 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.extend(struct.pack('<I', imm & 0xFFFFFFFF))
|
||||||
|
else:
|
||||||
|
raise ValueError("32-битное значение вне диапазона")
|
||||||
|
elif size == 16:
|
||||||
|
if 0 <= imm <= 0xFFFF:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xC7)
|
||||||
|
modrm = 0xC0 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
code.append((imm >> 8) & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("16-битное значение вне диапазона")
|
||||||
|
elif size == 8:
|
||||||
|
if not (0 <= imm <= 255):
|
||||||
|
raise ValueError("8-битное значение вне диапазона 0–255")
|
||||||
|
if reg_info.get("high8"):
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xB0 + reg + 4)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Старшие байты только для первых 4 регистров")
|
||||||
|
else:
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xB0 + reg)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xB0 + (reg & 7))
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый размер регистра")
|
||||||
|
|
||||||
|
elif itype == "cmp_reg_imm":
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("регистра", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
size = reg_info["size"]
|
||||||
|
imm = parse_operand(operands[1])
|
||||||
|
|
||||||
|
# --- ИЗМЕНЕНИЕ: Всегда используем 32-битную форму для 64-битных регистров, если imm помещается ---
|
||||||
|
if size == 64:
|
||||||
|
if -0x80000000 <= imm <= 0x7FFFFFFF:
|
||||||
|
# Используем 32-битное сравнение (с REX.W для 64-битного регистра)
|
||||||
|
rex = 0x48
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x81) # cmp r/m64, imm32
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.extend(struct.pack('<i', imm)) # imm32 sign-extended
|
||||||
|
else:
|
||||||
|
raise ValueError("Непосредственное значение слишком велико для сравнения: " + str(imm))
|
||||||
|
elif size == 32:
|
||||||
|
if -128 <= imm <= 127:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x83)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
elif -0x80000000 <= imm <= 0x7FFFFFFF:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x81)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.extend(struct.pack('<I', imm & 0xFFFFFFFF))
|
||||||
|
else:
|
||||||
|
raise ValueError("32-битное непосредственное значение вне диапазона")
|
||||||
|
elif size == 16:
|
||||||
|
if -128 <= imm <= 127:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x83)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
elif 0 <= imm <= 0xFFFF:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x81)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
code.append((imm >> 8) & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("16-битное непосредственное значение вне диапазона")
|
||||||
|
elif size == 8:
|
||||||
|
if not (0 <= imm <= 255):
|
||||||
|
raise ValueError("8-битное значение вне диапазона 0–255")
|
||||||
|
if reg_info.get("high8"):
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0x80)
|
||||||
|
modrm = 0xF8 | reg
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Старшие байты только для первых 4 регистров")
|
||||||
|
else:
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0x80)
|
||||||
|
modrm = 0xF8 | reg
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0x80)
|
||||||
|
modrm = 0xF8 | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
code.append(imm & 0xFF)
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый размер регистра")
|
||||||
|
|
||||||
|
elif itype == "jmp":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 5)
|
||||||
|
if offset < -0x80000000 or offset > 0x7FFFFFFF:
|
||||||
|
raise ValueError("Цель слишком далеко для 32-битного смещения в инструкции '" + mnemonic + "': " + str(offset))
|
||||||
|
code.extend(struct.pack('<i', offset))
|
||||||
|
|
||||||
|
elif itype == "jcc":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 6)
|
||||||
|
if offset < -0x80000000 or offset > 0x7FFFFFFF:
|
||||||
|
raise ValueError("Цель условного перехода слишком далеко: " + str(offset))
|
||||||
|
code.extend(struct.pack('<i', offset))
|
||||||
|
|
||||||
|
elif itype == "short_jmp":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 2)
|
||||||
|
if offset < -128 or offset > 127:
|
||||||
|
raise ValueError("Цель слишком далеко для короткого перехода: " + str(offset))
|
||||||
|
code.append(0xEB)
|
||||||
|
code.append(offset & 0xFF)
|
||||||
|
|
||||||
|
elif itype == "short_jcc":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
code.extend(instr["code"])
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
current_addr = vaddr_text + position[".text"]
|
||||||
|
offset = target - (current_addr + 2)
|
||||||
|
if offset < -128 or offset > 127:
|
||||||
|
raise ValueError("Цель слишком далеко для короткого условного перехода: " + str(offset))
|
||||||
|
code.append(offset & 0xFF)
|
||||||
|
|
||||||
|
elif itype in ("cmp_reg_reg", "test_reg_reg", "add_reg_reg", "sub_reg_reg"):
|
||||||
|
if len(operands) != 2:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 2, len(operands)))
|
||||||
|
dst_info = get_reg_info(operands[0])
|
||||||
|
src_info = get_reg_info(operands[1])
|
||||||
|
if dst_info is None:
|
||||||
|
raise ValueError(error_invalid_register("назначения", operands[0], mnemonic))
|
||||||
|
if src_info is None:
|
||||||
|
raise ValueError(error_invalid_register("источника", operands[1], mnemonic))
|
||||||
|
dst = dst_info["index"]
|
||||||
|
src = src_info["index"]
|
||||||
|
size = dst_info["size"]
|
||||||
|
if size != src_info["size"]:
|
||||||
|
raise ValueError("Размеры операндов не совпадают в инструкции '" + mnemonic + "'")
|
||||||
|
|
||||||
|
use_66 = (size == 16)
|
||||||
|
use_rex_w = (size == 64)
|
||||||
|
rex = 0x40
|
||||||
|
if use_rex_w:
|
||||||
|
rex |= 0x08
|
||||||
|
if src >= 8:
|
||||||
|
rex |= 0x04
|
||||||
|
if dst >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if dst_info.get("high8") or src_info.get("high8"):
|
||||||
|
if rex != 0x40:
|
||||||
|
raise ValueError("Старшие байты несовместимы с REX")
|
||||||
|
rex = 0
|
||||||
|
|
||||||
|
op_map = {
|
||||||
|
"cmp_reg_reg": 0x39,
|
||||||
|
"test_reg_reg": 0x85,
|
||||||
|
"add_reg_reg": 0x01,
|
||||||
|
"sub_reg_reg": 0x29,
|
||||||
|
}
|
||||||
|
op = op_map[itype]
|
||||||
|
|
||||||
|
if use_66:
|
||||||
|
code.append(0x66)
|
||||||
|
if rex != 0x40 or use_rex_w:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(op)
|
||||||
|
modrm = 0xC0 | ((src & 7) << 3) | (dst & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
|
||||||
|
elif itype == "incdec":
|
||||||
|
if len(operands) != 1:
|
||||||
|
raise ValueError(error_invalid_operand_count(mnemonic, 1, len(operands)))
|
||||||
|
reg_info = get_reg_info(operands[0])
|
||||||
|
if reg_info is None:
|
||||||
|
raise ValueError(error_invalid_register("регистра", operands[0], mnemonic))
|
||||||
|
reg = reg_info["index"]
|
||||||
|
size = reg_info["size"]
|
||||||
|
subop = instr["subop"]
|
||||||
|
|
||||||
|
if size == 64:
|
||||||
|
rex = 0x48
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFF)
|
||||||
|
elif size == 32:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFF)
|
||||||
|
elif size == 16:
|
||||||
|
code.append(0x66)
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
if rex != 0x40:
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFF)
|
||||||
|
elif size == 8:
|
||||||
|
if reg_info.get("high8"):
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xFE)
|
||||||
|
else:
|
||||||
|
raise ValueError("Старшие байты только для первых 4 регистров")
|
||||||
|
else:
|
||||||
|
if reg < 4:
|
||||||
|
code.append(0xFE)
|
||||||
|
else:
|
||||||
|
rex = 0x40
|
||||||
|
if reg >= 8:
|
||||||
|
rex |= 0x01
|
||||||
|
code.append(rex)
|
||||||
|
code.append(0xFE)
|
||||||
|
modrm = 0xC0 | (subop << 3) | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
return bytes(code)
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый размер регистра")
|
||||||
|
|
||||||
|
modrm = 0xC0 | (subop << 3) | (reg & 7)
|
||||||
|
code.append(modrm)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError("Неизвестный тип инструкции: " + itype)
|
||||||
|
|
||||||
|
return bytes(code)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parse_instruction_or_directive(tokens, line_num, line_text):
|
||||||
|
global current_section, entry_point, symbols # Не забудьте добавить symbols в global
|
||||||
|
first = tokens[0]
|
||||||
|
if first[0] != 'word':
|
||||||
|
raise ValueError("Ожидалось слово, получено: " + str(first))
|
||||||
|
word = first[1]
|
||||||
|
if word.startswith('.'):
|
||||||
|
if word == '.текст':
|
||||||
|
current_section = ".text"
|
||||||
|
elif word == '.данные':
|
||||||
|
current_section = ".data"
|
||||||
|
elif word == '.глобал':
|
||||||
|
if len(tokens) < 2 or tokens[1][0] != 'word':
|
||||||
|
raise ValueError(".глобал требует имя метки")
|
||||||
|
entry_point = tokens[1][1]
|
||||||
|
elif word == '.строка_нуль' or word == '.строка':
|
||||||
|
if len(tokens) < 2 or tokens[1][0] != 'string':
|
||||||
|
raise ValueError(word + " требует строку в кавычках")
|
||||||
|
if current_section != ".data":
|
||||||
|
raise ValueError("Строки разрешены только в секции .data")
|
||||||
|
s = tokens[1][1]
|
||||||
|
bstring = s.encode('utf-8')
|
||||||
|
add_null = (word == '.строка_нуль')
|
||||||
|
size = len(bstring) + (1 if add_null else 0)
|
||||||
|
if pass_num == 1:
|
||||||
|
position[".data"] += size
|
||||||
|
elif pass_num == 2:
|
||||||
|
sections[".data"] += bstring
|
||||||
|
if add_null:
|
||||||
|
sections[".data"] += b'\x00'
|
||||||
|
position[".data"] += size
|
||||||
|
# === НОВАЯ ДИРЕКТИВА .КОНСТАНТА ===
|
||||||
|
elif word == '.константа':
|
||||||
|
if len(tokens) < 3 or tokens[1][0] != 'word' or tokens[2][0] != 'word' or tokens[2][1] != '=' or len(tokens) < 4 or tokens[3][0] not in ('word', 'string'): # Проверяем формат: .константа имя = значение
|
||||||
|
raise ValueError(".константа требует формат: .константа <имя> = <значение>")
|
||||||
|
const_name = tokens[1][1]
|
||||||
|
const_value_str = tokens[3][1]
|
||||||
|
try:
|
||||||
|
# Попробуем распарсить значение как число или символ (если это метка)
|
||||||
|
const_value = parse_operand(const_value_str)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Невозможно распознать значение константы '" + const_value_str + "'")
|
||||||
|
|
||||||
|
# Записываем в глобальный словарь символов
|
||||||
|
symbols[const_name] = const_value
|
||||||
|
# Директива .константа не добавляет байты в секцию
|
||||||
|
return
|
||||||
|
# === КОНЕЦ НОВОЙ ДИРЕКТИВЫ ===
|
||||||
|
else:
|
||||||
|
raise ValueError(error_unknown_directive(word))
|
||||||
|
return
|
||||||
|
|
||||||
|
mnemonic = word
|
||||||
|
if mnemonic not in INSTRUCTIONS:
|
||||||
|
raise ValueError(error_unknown_mnemonic(mnemonic))
|
||||||
|
|
||||||
|
operands = []
|
||||||
|
for tok in tokens[1:]:
|
||||||
|
if tok[0] == 'word':
|
||||||
|
operands.append(tok[1])
|
||||||
|
elif tok[0] == 'comma':
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raise ValueError("Недопустимый токен в операндах: " + str(tok))
|
||||||
|
|
||||||
|
if pass_num == 2:
|
||||||
|
instr_info = INSTRUCTIONS[mnemonic]
|
||||||
|
itype = instr_info["type"]
|
||||||
|
code = encode_instruction(mnemonic, operands, line_num, line_text)
|
||||||
|
start_pos = position[current_section]
|
||||||
|
|
||||||
|
if current_section == ".text":
|
||||||
|
start_vaddr = vaddr_text + start_pos
|
||||||
|
target_addr = ""
|
||||||
|
try:
|
||||||
|
if itype in ("jmp", "jcc", "short_jmp", "short_jcc"):
|
||||||
|
target = parse_operand(operands[0])
|
||||||
|
target_addr = hex(target)
|
||||||
|
elif itype == "reg_imm":
|
||||||
|
op_str = operands[1]
|
||||||
|
if op_str in labels:
|
||||||
|
sec = label_sections[op_str]
|
||||||
|
addr = labels[op_str] + (vaddr_text if sec == ".text" else vaddr_data)
|
||||||
|
target_addr = hex(addr)
|
||||||
|
elif op_str in symbols: # Проверяем символы
|
||||||
|
target_addr = hex(symbols[op_str])
|
||||||
|
except Exception:
|
||||||
|
target_addr = "ошибка"
|
||||||
|
|
||||||
|
original_cmd = line_text.split(';')[0].strip()
|
||||||
|
for i, byte in enumerate(code):
|
||||||
|
addr = start_vaddr + i
|
||||||
|
byte_hex = "{:02X}".format(byte)
|
||||||
|
cmd_to_log = original_cmd if i == 0 else ""
|
||||||
|
log_entries.append((hex(addr), byte_hex, target_addr if i == 0 else "", cmd_to_log))
|
||||||
|
|
||||||
|
sections[current_section] += code
|
||||||
|
position[current_section] += len(code)
|
||||||
|
else:
|
||||||
|
instr_info = INSTRUCTIONS[mnemonic]
|
||||||
|
itype = instr_info["type"]
|
||||||
|
size_map = {
|
||||||
|
"reg_imm": 10,
|
||||||
|
"cmp_reg_imm": 7, # 6 байт для REX.W + 0x81 + ModR/M + imm32
|
||||||
|
"jmp": 5,
|
||||||
|
"jcc": 6,
|
||||||
|
"none": lambda: len(instr_info["code"]), # Используем длину кода для "none" инструкций
|
||||||
|
"short_jmp": 2,
|
||||||
|
"short_jcc": 2,
|
||||||
|
"cmp_reg_reg": 3,
|
||||||
|
"test_reg_reg": 3,
|
||||||
|
"add_reg_reg": 3,
|
||||||
|
"sub_reg_reg": 3,
|
||||||
|
"incdec": 3,
|
||||||
|
}
|
||||||
|
if itype in size_map:
|
||||||
|
sz = size_map[itype]
|
||||||
|
position[current_section] += sz() if callable(sz) else sz
|
||||||
|
else:
|
||||||
|
raise ValueError("Неподдерживаемый тип инструкции при подсчёте размера: " + itype)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parse_tokens(tokens, line_num, line_text):
|
||||||
|
if not tokens:
|
||||||
|
return
|
||||||
|
if len(tokens) >= 2 and tokens[0][0] == 'word' and tokens[1][0] == 'colon':
|
||||||
|
label = tokens[0][1]
|
||||||
|
labels[label] = position[current_section]
|
||||||
|
label_sections[label] = current_section
|
||||||
|
rest = tokens[2:]
|
||||||
|
if rest:
|
||||||
|
parse_instruction_or_directive(rest, line_num, line_text)
|
||||||
|
return
|
||||||
|
parse_instruction_or_directive(tokens, line_num, line_text)
|
||||||
|
|
||||||
|
def parse(source):
|
||||||
|
global pass_num, text_size, data_size, comment_size
|
||||||
|
global offset_text, offset_data, offset_comment, shstrtab_offset, shdr_offset
|
||||||
|
global vaddr_text, vaddr_data
|
||||||
|
global sections, position, log_entries
|
||||||
|
|
||||||
|
log_entries = []
|
||||||
|
lines = source.split('\n')
|
||||||
|
|
||||||
|
# ПРОХОД 1
|
||||||
|
pass_num = 1
|
||||||
|
position[".text"] = 0
|
||||||
|
position[".data"] = 0
|
||||||
|
labels.clear()
|
||||||
|
label_sections.clear()
|
||||||
|
|
||||||
|
for line_num, line in enumerate(lines, start=1):
|
||||||
|
original_line = line.rstrip()
|
||||||
|
try:
|
||||||
|
tokens = tokenize_line(line)
|
||||||
|
parse_tokens(tokens, line_num, original_line)
|
||||||
|
except Exception as e:
|
||||||
|
error_full = make_error_msg(line_num, original_line, str(e))
|
||||||
|
print(error_full, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
text_size_pass1 = position[".text"]
|
||||||
|
data_size_pass1 = position[".data"]
|
||||||
|
print("ПРОХОД 1: text_size=" + str(text_size_pass1) + " bytes, data_size=" + str(data_size_pass1) + " bytes")
|
||||||
|
|
||||||
|
# РАЗМЕЩЕНИЕ
|
||||||
|
elf_header_size = 64
|
||||||
|
ph_size = 56
|
||||||
|
ph_num = 3
|
||||||
|
ph_table_size = ph_num * ph_size
|
||||||
|
|
||||||
|
offset_text = align_up(elf_header_size + ph_table_size, PAGE_SIZE)
|
||||||
|
offset_data = align_up(offset_text + text_size_pass1, PAGE_SIZE)
|
||||||
|
vaddr_text = text_vaddr_base
|
||||||
|
vaddr_data = align_up(vaddr_text + text_size_pass1, PAGE_SIZE)
|
||||||
|
|
||||||
|
comment_content = "Сборщик КВС".encode('utf-8') + b'\x00'
|
||||||
|
comment_size = len(comment_content)
|
||||||
|
offset_comment = align_up(offset_data + data_size_pass1, 1)
|
||||||
|
|
||||||
|
shstrtab_content = b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00"
|
||||||
|
shstrtab_size = len(shstrtab_content)
|
||||||
|
shstrtab_offset = align_up(offset_comment + comment_size, 8)
|
||||||
|
shdr_size = 64
|
||||||
|
shdr_num = 5
|
||||||
|
shdr_offset = align_up(shstrtab_offset + shstrtab_size, 16)
|
||||||
|
|
||||||
|
print("РАЗМЕЩЕНИЕ: .text at offset=" + hex(offset_text) + ", .data at offset=" + hex(offset_data))
|
||||||
|
print("ВИРТУАЛЬНЫЕ АДРЕСА: .text at " + hex(vaddr_text) + ", .data at " + hex(vaddr_data))
|
||||||
|
print("РАССТОЯНИЕ МЕЖДУ СЕКЦИЯМИ: " + hex(vaddr_data - vaddr_text) + " bytes")
|
||||||
|
|
||||||
|
sections[".comment"] = comment_content
|
||||||
|
|
||||||
|
# ПРОХОД 2
|
||||||
|
pass_num = 2
|
||||||
|
position[".text"] = 0
|
||||||
|
position[".data"] = 0
|
||||||
|
sections[".text"] = bytearray()
|
||||||
|
sections[".data"] = bytearray()
|
||||||
|
|
||||||
|
for line_num, line in enumerate(lines, start=1):
|
||||||
|
original_line = line.rstrip()
|
||||||
|
try:
|
||||||
|
tokens = tokenize_line(line)
|
||||||
|
parse_tokens(tokens, line_num, original_line)
|
||||||
|
except Exception as e:
|
||||||
|
error_full = make_error_msg(line_num, original_line, str(e))
|
||||||
|
print(error_full, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
text_size_pass2 = len(sections[".text"])
|
||||||
|
data_size_pass2 = len(sections[".data"])
|
||||||
|
print("ПРОХОД 2: text_size=" + str(text_size_pass2) + " bytes, data_size=" + str(data_size_pass2) + " bytes")
|
||||||
|
|
||||||
|
if text_size_pass1 != text_size_pass2:
|
||||||
|
print("ПРЕДУПРЕЖДЕНИЕ: Размер .text изменился между проходами: " + str(text_size_pass1) + " -> " + str(text_size_pass2))
|
||||||
|
if data_size_pass1 != data_size_pass2:
|
||||||
|
print("ПРЕДУПРЕЖДЕНИЕ: Размер .data изменился между проходами: " + str(data_size_pass1) + " -> " + str(data_size_pass2))
|
||||||
|
|
||||||
|
text_size = text_size_pass2
|
||||||
|
data_size = data_size_pass2
|
||||||
|
|
||||||
|
def create_elf(filename):
|
||||||
|
global sections, entry_point, labels, vaddr_text, vaddr_data
|
||||||
|
global offset_text, offset_data, offset_comment, shstrtab_offset, shdr_offset
|
||||||
|
|
||||||
|
text = sections[".text"]
|
||||||
|
data = sections[".data"]
|
||||||
|
comment = sections[".comment"]
|
||||||
|
|
||||||
|
actual_text_size = len(text)
|
||||||
|
actual_data_size = len(data)
|
||||||
|
expected_vaddr_data = align_up(vaddr_text + actual_text_size, PAGE_SIZE)
|
||||||
|
if vaddr_data != expected_vaddr_data:
|
||||||
|
print("КОРРЕКЦИЯ: vaddr_data исправлен с " + hex(vaddr_data) + " на " + hex(expected_vaddr_data))
|
||||||
|
vaddr_data = expected_vaddr_data
|
||||||
|
|
||||||
|
print("ФАКТИЧЕСКИЕ РАЗМЕРЫ: .text=" + str(actual_text_size) + ", .data=" + str(actual_data_size))
|
||||||
|
print("КОНЕЧНЫЕ АДРЕСА: .text ends at " + hex(vaddr_text + actual_text_size) + ", .data starts at " + hex(vaddr_data))
|
||||||
|
print("ПРОВЕРКА ПЕРЕКРЫТИЯ: " + ("ПЕРЕКРЫТИЕ!" if (vaddr_text + actual_text_size) > vaddr_data else "OK"))
|
||||||
|
|
||||||
|
entry_addr = vaddr_text + labels.get(entry_point, 0)
|
||||||
|
|
||||||
|
shstrtab_content = b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00"
|
||||||
|
shstrtab_size = len(shstrtab_content)
|
||||||
|
|
||||||
|
elf_header_size = 64
|
||||||
|
ph_size = 56
|
||||||
|
ph_num = 3
|
||||||
|
shdr_size = 64
|
||||||
|
shdr_num = 5
|
||||||
|
|
||||||
|
file_size = shdr_offset + shdr_num * shdr_size
|
||||||
|
elf_data = bytearray(file_size)
|
||||||
|
|
||||||
|
# ELF header
|
||||||
|
e_ident = b"\x7fELF\x02\x01\x01\x00" + b"\x00" * 8
|
||||||
|
elf_header = struct.pack(
|
||||||
|
'<16sHHIQQQIHHHHHH',
|
||||||
|
e_ident,
|
||||||
|
2,
|
||||||
|
0x3e,
|
||||||
|
1,
|
||||||
|
entry_addr,
|
||||||
|
elf_header_size,
|
||||||
|
shdr_offset,
|
||||||
|
0,
|
||||||
|
elf_header_size,
|
||||||
|
ph_size,
|
||||||
|
ph_num,
|
||||||
|
shdr_size,
|
||||||
|
shdr_num,
|
||||||
|
4
|
||||||
|
)
|
||||||
|
elf_data[0:64] = elf_header
|
||||||
|
|
||||||
|
def phdr(p_type, p_flags, p_offset, p_vaddr, p_filesz, p_memsz):
|
||||||
|
return struct.pack('<IIQQQQQQ',
|
||||||
|
p_type, p_flags,
|
||||||
|
p_offset, p_vaddr, p_vaddr,
|
||||||
|
p_filesz, p_memsz,
|
||||||
|
PAGE_SIZE
|
||||||
|
)
|
||||||
|
|
||||||
|
ph0 = phdr(1, 4, 0, elf_base_vaddr, elf_header_size + ph_num * ph_size, PAGE_SIZE)
|
||||||
|
ph1 = phdr(1, 5, offset_text, vaddr_text, len(text), align_up(len(text), PAGE_SIZE))
|
||||||
|
ph2 = phdr(1, 6, offset_data, vaddr_data, len(data), align_up(len(data), PAGE_SIZE))
|
||||||
|
|
||||||
|
phdrs = ph0 + ph1 + ph2
|
||||||
|
elf_data[elf_header_size : elf_header_size + len(phdrs)] = phdrs
|
||||||
|
|
||||||
|
elf_data[offset_text : offset_text + len(text)] = text
|
||||||
|
elf_data[offset_data : offset_data + len(data)] = data
|
||||||
|
elf_data[offset_comment : offset_comment + len(comment)] = comment
|
||||||
|
elf_data[shstrtab_offset : shstrtab_offset + shstrtab_size] = shstrtab_content
|
||||||
|
|
||||||
|
def shdr(name_idx, sh_type, flags, addr, offset, size, addralign=1):
|
||||||
|
return struct.pack('<IIQQQQIIQQ',
|
||||||
|
name_idx, sh_type, flags, addr, offset, size,
|
||||||
|
0, 0, addralign, 0
|
||||||
|
)
|
||||||
|
|
||||||
|
sh0 = shdr(0, 0, 0, 0, 0, 0)
|
||||||
|
sh1 = shdr(1, 1, 6, vaddr_text, offset_text, len(text), 16)
|
||||||
|
sh2 = shdr(7, 1, 3, vaddr_data, offset_data, len(data), 8)
|
||||||
|
sh3 = shdr(13, 1, 0, 0, offset_comment, len(comment), 1)
|
||||||
|
sh4 = shdr(22, 3, 0, 0, shstrtab_offset, shstrtab_size, 1)
|
||||||
|
|
||||||
|
shdrs = sh0 + sh1 + sh2 + sh3 + sh4
|
||||||
|
elf_data[shdr_offset : shdr_offset + len(shdrs)] = shdrs
|
||||||
|
|
||||||
|
f_out = open(filename, "wb")
|
||||||
|
f_out.write(elf_data)
|
||||||
|
f_out.close()
|
||||||
|
|
||||||
|
import os
|
||||||
|
os.chmod(filename, 0o755)
|
||||||
|
|
||||||
|
# === Основной запуск ===
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("Использование: python kvs_7.py <файл.квс>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
source_file = sys.argv[1]
|
||||||
|
source_filename = source_file
|
||||||
|
if not source_file.endswith('.квс'):
|
||||||
|
print("Ошибка: файл должен иметь расширение .квс")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
f_in = None
|
||||||
|
try:
|
||||||
|
f_in = open(source_file, "r", encoding="utf-8")
|
||||||
|
source = f_in.read()
|
||||||
|
f_in.close()
|
||||||
|
except FileNotFoundError:
|
||||||
|
safe_close(f_in)
|
||||||
|
print("Ошибка: файл '" + source_file + "' не найден.")
|
||||||
|
sys.exit(1)
|
||||||
|
except UnicodeDecodeError as e:
|
||||||
|
safe_close(f_in)
|
||||||
|
print("Ошибка кодировки в файле '" + source_file + "': " + str(e))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
parse(source)
|
||||||
|
elf_file = source_file[:-4] + ".elf"
|
||||||
|
create_elf(elf_file)
|
||||||
|
|
||||||
|
log_file = source_file[:-4] + ".log.csv"
|
||||||
|
f_log = open(log_file, "w", encoding="utf-8")
|
||||||
|
f_log.write("адрес;байт;целевой_адрес;исходная_команда\n")
|
||||||
|
for addr, byte, target, cmd in log_entries:
|
||||||
|
if cmd and ('"' in cmd or ';' in cmd):
|
||||||
|
cmd = '"' + cmd.replace('"', '""') + '"'
|
||||||
|
f_log.write(addr + ";" + byte + ";" + target + ";" + cmd + "\n")
|
||||||
|
f_log.close()
|
||||||
|
print("Лог создан: " + log_file)
|
||||||
|
|
||||||
|
print("ELF-файл создан: " + elf_file)
|
||||||
|
print("Запустить: ./" + elf_file)
|
||||||
|
except SystemExit:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
print("Внутренняя ошибка ассемблера: " + str(e), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
124
jumps/длин_тест0.квс
Normal file
124
jumps/длин_тест0.квс
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
;длин_тест0.квс
|
||||||
|
; Тест: один длинный переход и один мусорный сегмент
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистра
|
||||||
|
переместить_имм раикс, 10 ; rax = 10 (не ноль)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'вывести_сообщение', пропуская мертвый_код_1
|
||||||
|
переход_если_не_ноль вывести_сообщение
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
; Добавляем много "мусора", чтобы точно выйти за пределы короткого перехода
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
; --- КОД ОШИБКИ (на всякий случай) ---
|
||||||
|
; Если мы сюда попали, значит переход НЕ сработал (ошибка)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_fail
|
||||||
|
переместить_имм рдикс, len_msg_fail
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 14
|
||||||
|
msg_fail: .строка_нуль "Ошибка: переход не сработал!"
|
||||||
|
.константа len_msg_fail = 28
|
||||||
230
jumps/длин_тест1.квс
Normal file
230
jumps/длин_тест1.квс
Normal file
|
|
@ -0,0 +1,230 @@
|
||||||
|
; длин_тест1.квс
|
||||||
|
; Тест: два длинных перехода и два мусорных сегмента
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10 (не ноль)
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5 (для сравнения)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
; Добавляем "мусор", чтобы точно выйти за пределы короткого перехода
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: переход_если_равно
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0 (т.е. когда НЕ равны).
|
||||||
|
; У нас нет инструкции 'переход_если_не_равно' (jne), но она эквивалентна 'переход_если_не_ноль' (jnz) для флага ZF.
|
||||||
|
; Однако, у нас есть 'переход_если_равно' (je), который сработает при ZF=1.
|
||||||
|
; Мы хотим, чтобы переход НЕ срабатывал при ZF=0.
|
||||||
|
; Поэтому мы используем логику: if (ZF == 0) jmp; (псевдокод).
|
||||||
|
; Это можно выразить как: if (ZF == 1) goto skip_jmp; jmp target; skip_jmp: ... (псевдокод).
|
||||||
|
; Это и есть: cmp ...; je skip_jmp; jmp target; skip_jmp: ...
|
||||||
|
; Где 'jmp target' - это прыжок, который происходит, если ZF=0 (т.е. когда je НЕ сработал).
|
||||||
|
; Итак:
|
||||||
|
; cmp rax, rbx (ZF=0)
|
||||||
|
; je skip_jmp (ZF=0, переход НЕ сработает -> идем дальше)
|
||||||
|
; переход мимо_мертвого_кода_2 (ZF=0, СРАБОТАЕТ -> прыгаем мимо мертвого кода)
|
||||||
|
; skip_jmp: (ZF=1, мы сюда попали, прыгнув через безусловный переход)
|
||||||
|
; [мертвый код 2 - выполнится ТОЛЬКО если ZF=1]
|
||||||
|
; мимо_мертвого_кода_2:
|
||||||
|
; [продолжение]
|
||||||
|
|
||||||
|
; Это как раз то, что нужно!
|
||||||
|
; cmp rax, rbx (ZF=0)
|
||||||
|
; je skip_jmp (ZF=0 -> не прыгаем)
|
||||||
|
; переход мимо_мертвого_кода_2 (ZF=0 -> прыгаем мимо мертвого кода 2)
|
||||||
|
; skip_jmp: (ZF=1 -> сюда попали, прыгнув через безусловный переход)
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
переход_если_равно skip_jmp
|
||||||
|
переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
; Добавляем "мусор", чтобы точно выйти за пределы короткого перехода
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 12 ;
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 14
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 14
|
||||||
175
jumps/длин_тест2.квс
Normal file
175
jumps/длин_тест2.квс
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
; длин_тест2.квс
|
||||||
|
; Тест: три длинных перехода и три мусорных сегмента
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_равно skip_jmp_2
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше skip_jmp_3
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 12 ; Длина "Успех!\n" в UTF-8 без нулевого байта
|
||||||
|
; "Мертвый код 3!" = 12 букв * 2 байта (UTF-8) + 1 (!) + 1 (\n от .строка_нуль) = 24 + 2 = 26 байт. len = 25 (без \0)
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 25 ; Длина "Мертвый код 3!" в UTF-8 без нулевого байта
|
||||||
|
; "Мертвый код 2!" = 12 букв * 2 байта (UTF-8) + 1 (!) + 1 (\n от .строка_нуль) = 24 + 2 = 26 байт. len = 25 (без \0)
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 25 ; Длина "Мертвый код 2!" в UTF-8 без нулевого байта
|
||||||
|
; "Мертвый код 1!" = 12 букв * 2 байта (UTF-8) + 1 (!) + 1 (\n от .строка_нуль) = 24 + 2 = 26 байт. len = 25 (без \0)
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 25 ; Длина "Мертвый код 1!" в UTF-8 без нулевого байта
|
||||||
196
jumps/длин_тест3.квс
Normal file
196
jumps/длин_тест3.квс
Normal file
|
|
@ -0,0 +1,196 @@
|
||||||
|
; длин_тест3.квс
|
||||||
|
; Тест: четыре длинных перехода и четыре мусорных сегмента
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_равно skip_jmp_2
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше skip_jmp_3
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 1 (\n от .строка_нуль) = 10 + 2 = 12 байт. len = 12
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 12
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 19
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 19
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 19
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 19
|
||||||
260
jumps/длин_тест4.квс
Normal file
260
jumps/длин_тест4.квс
Normal file
|
|
@ -0,0 +1,260 @@
|
||||||
|
; длин_тест4.квс
|
||||||
|
; Тест: пять длинных переходов и пять мусорных сегментов
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_равно skip_jmp_2
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше skip_jmp_3
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ПЯТЫЙ ПЕРЕХОД: переход_если_меньше_или_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jle: ZF=1 ИЛИ SF != OF. ZF=0 (ложь), SF != OF (0 != 0, ложь). jle НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 5, если jle НЕ сработает (т.е. если rax > rbx).
|
||||||
|
; Используем: jle skip_jmp_5 (переход НЕ сработает); jmp мимо_мертвого_кода_5 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше_или_равно skip_jmp_5
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_5
|
||||||
|
skip_jmp_5:
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jle не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_5:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 1 (\n от .строка_нуль) = 10 + 2 = 12 байт. len = 12
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 12
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 19
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 19
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 19
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 19
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 19
|
||||||
280
jumps/длин_тест5.квс
Normal file
280
jumps/длин_тест5.квс
Normal file
|
|
@ -0,0 +1,280 @@
|
||||||
|
; длин_тест5.квс
|
||||||
|
; Тест: шесть длинных переходов и шесть мусорных сегментов
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_равно skip_jmp_2
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше skip_jmp_3
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ПЯТЫЙ ПЕРЕХОД: переход_если_меньше_или_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jle: ZF=1 ИЛИ SF != OF. ZF=0 (ложь), SF != OF (0 != 0, ложь). jle НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 5, если jle НЕ сработает (т.е. если rax > rbx).
|
||||||
|
; Используем: jle skip_jmp_5 (переход НЕ сработает); jmp мимо_мертвого_кода_5 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше_или_равно skip_jmp_5
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_5
|
||||||
|
skip_jmp_5:
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jle не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_5:
|
||||||
|
|
||||||
|
; ШЕСТОЙ ПЕРЕХОД: переход_если_больше_или_равно
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jge: SF=OF. SF=0, OF=0, SF=OF (0=0). jge СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 6, если jge сработает (т.е. если rax >= rbx).
|
||||||
|
переход_если_больше_или_равно мимо_мертвого_кода_6
|
||||||
|
; --- МЕРТВЫЙ КОД 6 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jge сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_6:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 1 (\n от .строка_нуль) = 10 + 2 = 12 байт. len = 12
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 12
|
||||||
|
; "Мертвый код 6!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_6: .строка_нуль "Мертвый код 6!"
|
||||||
|
.константа len_msg_dead_6 = 19
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 19
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 19
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 19
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 19
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт. len = 19
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 19
|
||||||
374
jumps/длин_тест6.квс
Normal file
374
jumps/длин_тест6.квс
Normal file
|
|
@ -0,0 +1,374 @@
|
||||||
|
; длин_тест6.квс
|
||||||
|
; Тест: семь длинных переходов и семь мусорных сегментов
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
; Добавляем "мусор", чтобы точно выйти за пределы короткого перехода
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_равно skip_jmp_2
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше skip_jmp_3
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ПЯТЫЙ ПЕРЕХОД: переход_если_меньше_или_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jle: ZF=1 ИЛИ SF != OF. ZF=0 (ложь), SF != OF (0 != 0, ложь). jle НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 5, если jle НЕ сработает (т.е. если rax > rbx).
|
||||||
|
; Используем: jle skip_jmp_5 (переход НЕ сработает); jmp мимо_мертвого_кода_5 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше_или_равно skip_jmp_5
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_5
|
||||||
|
skip_jmp_5:
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jle не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_5:
|
||||||
|
|
||||||
|
; ШЕСТОЙ ПЕРЕХОД: переход_если_больше_или_равно
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jge: SF=OF. SF=0, OF=0, SF=OF (0=0). jge СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 6, если jge сработает (т.е. если rax >= rbx).
|
||||||
|
переход_если_больше_или_равно мимо_мертвого_кода_6
|
||||||
|
; --- МЕРТВЫЙ КОД 6 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jge сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_6:
|
||||||
|
|
||||||
|
; СЕДЬМОЙ ПЕРЕХОД: переход_если_перенос
|
||||||
|
; Выполним вычитание, которое вызовет перенос: rbx - rax = 5 - 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
; rbx - rax = 5 - 10 -> CF=1
|
||||||
|
вычесть рбикс, раикс ; rbx = rbx - rax = 5 - 10. Это вызовет перенос (CF=1).
|
||||||
|
; Условие jc: CF=1. CF=1. jc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 7, если jc сработает (т.е. если был перенос).
|
||||||
|
переход_если_перенос мимо_мертвого_кода_7
|
||||||
|
; --- МЕРТВЫЙ КОД 7 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_7:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 2 (\n) = 13 байт на содержимое. len = 13
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
; "Мертвый код 7!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_7: .строка_нуль "Мертвый код 7!"
|
||||||
|
.константа len_msg_dead_7 = 18
|
||||||
|
; "Мертвый код 6!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_6: .строка_нуль "Мертвый код 6!"
|
||||||
|
.константа len_msg_dead_6 = 18
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 18
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 18
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 18
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 18
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 18
|
||||||
396
jumps/длин_тест7.квс
Normal file
396
jumps/длин_тест7.квс
Normal file
|
|
@ -0,0 +1,396 @@
|
||||||
|
; длин_тест7.квс
|
||||||
|
; Тест: восемь длинных переходов и восемь мусорных сегментов
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
; Добавляем "мусор", чтобы точно выйти за пределы короткого перехода
|
||||||
|
переход_если_не_ноль проверка_2
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_равно skip_jmp_2
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше skip_jmp_3
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ПЯТЫЙ ПЕРЕХОД: переход_если_меньше_или_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jle: ZF=1 ИЛИ SF != OF. ZF=0 (ложь), SF != OF (0 != 0, ложь). jle НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 5, если jle НЕ сработает (т.е. если rax > rbx).
|
||||||
|
; Используем: jle skip_jmp_5 (переход НЕ сработает); jmp мимо_мертвого_кода_5 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше_или_равно skip_jmp_5
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_5
|
||||||
|
skip_jmp_5:
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jle не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_5:
|
||||||
|
|
||||||
|
; ШЕСТОЙ ПЕРЕХОД: переход_если_больше_или_равно
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jge: SF=OF. SF=0, OF=0, SF=OF (0=0). jge СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 6, если jge сработает (т.е. если rax >= rbx).
|
||||||
|
переход_если_больше_или_равно мимо_мертвого_кода_6
|
||||||
|
; --- МЕРТВЫЙ КОД 6 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jge сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_6:
|
||||||
|
|
||||||
|
; СЕДЬМОЙ ПЕРЕХОД: переход_если_перенос
|
||||||
|
; Выполним вычитание, которое вызовет перенос: rbx - rax = 5 - 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
; rbx - rax = 5 - 10 -> CF=1
|
||||||
|
вычесть рбикс, раикс ; rbx = rbx - rax = 5 - 10. Это вызовет перенос (CF=1).
|
||||||
|
; Условие jc: CF=1. CF=1. jc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 7, если jc сработает (т.е. если был перенос).
|
||||||
|
переход_если_перенос мимо_мертвого_кода_7
|
||||||
|
; --- МЕРТВЫЙ КОД 7 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_7:
|
||||||
|
|
||||||
|
; ВОСЬМОЙ ПЕРЕХОД: переход_если_нет_переноса
|
||||||
|
; Убедимся, что CF=0. Выполним операцию, которая сбросит CF.
|
||||||
|
сравнить раикс, раикс ; CF = 0 (так как rax - rax = 0, без переноса)
|
||||||
|
; Условие jnc: CF=0. CF=0. jnc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 8, если jnc сработает (т.е. если НЕ было переноса).
|
||||||
|
переход_если_нет_переноса мимо_мертвого_кода_8
|
||||||
|
; --- МЕРТВЫЙ КОД 8 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jnc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_8:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 1 (\n от .строка_нуль) = 12 байт на содержимое. len = 12
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 12
|
||||||
|
; "Мертвый код 8!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_8: .строка_нуль "Мертвый код 8!"
|
||||||
|
.константа len_msg_dead_8 = 19
|
||||||
|
; "Мертвый код 7!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_7: .строка_нуль "Мертвый код 7!"
|
||||||
|
.константа len_msg_dead_7 = 19
|
||||||
|
; "Мертвый код 6!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_6: .строка_нуль "Мертвый код 6!"
|
||||||
|
.константа len_msg_dead_6 = 19
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 19
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 19
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 19
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 19
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 19
|
||||||
409
jumps/длин_тест8.квс
Normal file
409
jumps/длин_тест8.квс
Normal file
|
|
@ -0,0 +1,409 @@
|
||||||
|
; длин_тест8.квс
|
||||||
|
; Тест: девять длинных переходов и девять мусорных сегментов
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
; Добавляем "мусор", чтобы точно выйти за пределы короткого перехода
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_равно skip_jmp_2
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше skip_jmp_3
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ПЯТЫЙ ПЕРЕХОД: переход_если_меньше_или_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jle: ZF=1 ИЛИ SF != OF. ZF=0 (ложь), SF != OF (0 != 0, ложь). jle НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 5, если jle НЕ сработает (т.е. если rax > rbx).
|
||||||
|
; Используем: jle skip_jmp_5 (переход НЕ сработает); jmp мимо_мертвого_кода_5 (переход СРАБОТАЕТ)
|
||||||
|
переход_если_меньше_или_равно skip_jmp_5
|
||||||
|
; Добавляем "мусор" из нет_операции для увеличения расстояния
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
нет_операции
|
||||||
|
переход мимо_мертвого_кода_5
|
||||||
|
skip_jmp_5:
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jle не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_5:
|
||||||
|
|
||||||
|
; ШЕСТОЙ ПЕРЕХОД: переход_если_больше_или_равно
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jge: SF=OF. SF=0, OF=0, SF=OF (0=0). jge СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 6, если jge сработает (т.е. если rax >= rbx).
|
||||||
|
переход_если_больше_или_равно мимо_мертвого_кода_6
|
||||||
|
; --- МЕРТВЫЙ КОД 6 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jge сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_6:
|
||||||
|
|
||||||
|
; СЕДЬМОЙ ПЕРЕХОД: переход_если_перенос
|
||||||
|
; Выполним вычитание, которое вызовет перенос: rbx - rax = 5 - 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
; rbx - rax = 5 - 10 -> CF=1
|
||||||
|
вычесть рбикс, раикс ; rbx = rbx - rax = 5 - 10. Это вызовет перенос (CF=1).
|
||||||
|
; Условие jc: CF=1. CF=1. jc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 7, если jc сработает (т.е. если был перенос).
|
||||||
|
переход_если_перенос мимо_мертвого_кода_7
|
||||||
|
; --- МЕРТВЫЙ КОД 7 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_7:
|
||||||
|
|
||||||
|
; ВОСЬМОЙ ПЕРЕХОД: переход_если_нет_переноса
|
||||||
|
; Убедимся, что CF=0. Выполним операцию, которая сбросит CF.
|
||||||
|
сравнить раикс, раикс ; CF = 0 (так как rax - rax = 0, без переноса)
|
||||||
|
; Условие jnc: CF=0. CF=0. jnc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 8, если jnc сработает (т.е. если НЕ было переноса).
|
||||||
|
переход_если_нет_переноса мимо_мертвого_кода_8
|
||||||
|
; --- МЕРТВЫЙ КОД 8 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jnc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_8:
|
||||||
|
|
||||||
|
; ДЕВЯТЫЙ ПЕРЕХОД: переход (безусловный)
|
||||||
|
; Просто прыгаем мимо мертвого кода 9.
|
||||||
|
переход мимо_мертвого_кода_9
|
||||||
|
; --- МЕРТВЫЙ КОД 9 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jmp сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_9:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 1 (\n от .строка_нуль) = 10 + 2 = 12 байт на содержимое. len = 12
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 12
|
||||||
|
; "Мертвый код 9!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_9: .строка_нуль "Мертвый код 9!"
|
||||||
|
.константа len_msg_dead_9 = 19
|
||||||
|
; "Мертвый код 8!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_8: .строка_нуль "Мертвый код 8!"
|
||||||
|
.константа len_msg_dead_8 = 19
|
||||||
|
; "Мертвый код 7!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_7: .строка_нуль "Мертвый код 7!"
|
||||||
|
.константа len_msg_dead_7 = 19
|
||||||
|
; "Мертвый код 6!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_6: .строка_нуль "Мертвый код 6!"
|
||||||
|
.константа len_msg_dead_6 = 19
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 19
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 19
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 19
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 19
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 19
|
||||||
835
jumps/длин_тест9.квс
Normal file
835
jumps/длин_тест9.квс
Normal file
|
|
@ -0,0 +1,835 @@
|
||||||
|
; длин_тест9.квс
|
||||||
|
; Тест: запутанные переходы, крякмис (для длинных переходов)
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
; Добавляем "мусор", чтобы точно выйти за пределы короткого перехода
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ДОПОЛНИТЕЛЬНЫЙ ПЕРЕХОД 1: "Два шага вперед" - переход через мертвый_код_2 и мертвый_код_3
|
||||||
|
; Прыгаем к проверка_4, минуя мертвый_код_2 и мертвый_код_3
|
||||||
|
переход проверка_4
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться из-за прыжка выше
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мертвый_код_3:
|
||||||
|
; ЖИВОЙ КОД 3: Этот код выполнится благодаря прыжку "назад"
|
||||||
|
; Выведем сообщение, чтобы убедиться, что он выполнился
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_live_from_3
|
||||||
|
переместить_имм рдикс, len_msg_live_from_3
|
||||||
|
вызов_системы
|
||||||
|
; ДОПОЛНИТЕЛЬНЫЙ ПЕРЕХОД 3: "Четыре вперед" - переход через мертвый_код_4, 5, 6, 7
|
||||||
|
; Цель слишком далеко для короткого перехода. Используем длинный.
|
||||||
|
; Прыгаем к проверка_8
|
||||||
|
переход проверка_8
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_4:
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ДОПОЛНИТЕЛЬНЫЙ ПЕРЕХОД 2: "Один назад" - переход к мертвому_коду_3 (делая его живым)
|
||||||
|
переход мертвый_код_3
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 6 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 7 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_8:
|
||||||
|
; СЕДЬМОЙ ПЕРЕХОД: переход_если_перенос
|
||||||
|
; Выполним вычитание, которое вызовет перенос: rbx - rax = 5 - 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
; rbx - rax = 5 - 10 -> CF=1
|
||||||
|
вычесть рбикс, раикс ; rbx = rbx - rax = 5 - 10. Это вызовет перенос (CF=1).
|
||||||
|
; Условие jc: CF=1. CF=1. jc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 8, если jc сработает (т.е. если был перенос).
|
||||||
|
переход_если_перенос мимо_мертвого_кода_8
|
||||||
|
; --- МЕРТВЫЙ КОД 8 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_8:
|
||||||
|
|
||||||
|
; ВОСЬМОЙ ПЕРЕХОД: переход_если_нет_переноса
|
||||||
|
; Убедимся, что CF=0. Выполним операцию, которая сбросит CF.
|
||||||
|
сравнить раикс, раикс ; CF = 0 (так как rax - rax = 0, без переноса)
|
||||||
|
; Условие jnc: CF=0. CF=0. jnc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 9, если jnc сработает (т.е. если НЕ было переноса).
|
||||||
|
переход_если_нет_переноса мимо_мертвого_кода_9
|
||||||
|
; --- МЕРТВЫЙ КОД 9 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jnc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_9:
|
||||||
|
|
||||||
|
; ДЕВЯТЫЙ ПЕРЕХОД: переход (безусловный)
|
||||||
|
; Просто прыгаем мимо мертвого кода 10.
|
||||||
|
переход мимо_мертвого_кода_10
|
||||||
|
; --- МЕРТВЫЙ КОД 10 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jmp сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 2
|
||||||
|
переместить_имм рдиай, 2
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 3
|
||||||
|
переместить_имм рдиай, 3
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 4
|
||||||
|
переместить_имм рдиай, 4
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 5
|
||||||
|
переместить_имм рдиай, 5
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 6
|
||||||
|
переместить_имм рдиай, 6
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 7
|
||||||
|
переместить_имм рдиай, 7
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 8
|
||||||
|
переместить_имм рдиай, 8
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 9
|
||||||
|
переместить_имм рдиай, 9
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 10
|
||||||
|
переместить_имм рдиай, 10
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 11
|
||||||
|
переместить_имм рдиай, 11
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 12
|
||||||
|
переместить_имм рдиай, 12
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 13
|
||||||
|
переместить_имм рдиай, 13
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 14
|
||||||
|
переместить_имм рдиай, 14
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
переместить_имм раикс, 15
|
||||||
|
переместить_имм рдиай, 15
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_10:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Живой из 3!\n" = 8 букв * 2 + 1 (!) + 1 (\n от .строка_нуль) = 16 + 2 = 18 байт на содержимое. len = 18
|
||||||
|
msg_live_from_3: .строка_нуль "Живой из 3!\n"
|
||||||
|
.константа len_msg_live_from_3 = 18
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 1 (\n от .строка_нуль) = 10 + 2 = 12 байт на содержимое. len = 12
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 12
|
||||||
|
; "Мертвый код 10!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_10: .строка_нуль "Мертвый код 10!"
|
||||||
|
.константа len_msg_dead_10 = 19
|
||||||
|
; "Мертвый код 9!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_9: .строка_нуль "Мертвый код 9!"
|
||||||
|
.константа len_msg_dead_9 = 19
|
||||||
|
; "Мертвый код 8!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_8: .строка_нуль "Мертвый код 8!"
|
||||||
|
.константа len_msg_dead_8 = 19
|
||||||
|
; "Мертвый код 7!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_7: .строка_нуль "Мертвый код 7!"
|
||||||
|
.константа len_msg_dead_7 = 19
|
||||||
|
; "Мертвый код 6!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_6: .строка_нуль "Мертвый код 6!"
|
||||||
|
.константа len_msg_dead_6 = 19
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 19
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 19
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 19
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 19
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 + 1 (\n от .строка_нуль) = 14 + 4 + 1 = 19 байт на содержимое. len = 19
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 19
|
||||||
35
jumps/привеет.квс
Normal file
35
jumps/привеет.квс
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация: raikc = 1 → пропустить первую строку
|
||||||
|
; Попробуйте изменить на 0 — тогда обе строки напечатаются
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
сравнить_с раикс, 1 ; ← обязательно!
|
||||||
|
|
||||||
|
; Если raikc == 0 → прыгаем к выводу второй строки
|
||||||
|
короткий_переход_если_ноль пропустить_первую
|
||||||
|
|
||||||
|
; Вывод первой строки
|
||||||
|
переместить_имм раикс, 1 ; write
|
||||||
|
переместить_имм рдиай, 1 ; stdout
|
||||||
|
переместить_имм рсиай, msg0 ; адрес строки
|
||||||
|
переместить_имм рдикс, 21 ; длина "Привет мир!\n" = 13 байт
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
пропустить_первую:
|
||||||
|
; Всегда выводим вторую строку
|
||||||
|
переместить_имм раикс, 1 ; write
|
||||||
|
переместить_имм рдиай, 1 ; stdout
|
||||||
|
переместить_имм рсиай, msg1 ; адрес строки
|
||||||
|
переместить_имм рдикс, 21 ; длина "Поди прочь!\n" = 13 байт
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; Завершение
|
||||||
|
переместить_имм раикс, 60 ; exit
|
||||||
|
переместить_имм рдиай, 0 ; код возврата
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
msg0: .строка_нуль "Привет мир!\n"
|
||||||
|
msg1: .строка_нуль "Поди прочь!\n"
|
||||||
53
jumps/сложный_тест0.квс
Normal file
53
jumps/сложный_тест0.квс
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
; сложный тест0.квс
|
||||||
|
; Тест: один переход и один мусорный сегмент
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистра
|
||||||
|
переместить_имм раикс, 10 ; rax = 10 (не ноль)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: короткий_переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'вывести_сообщение', пропуская мертвый_код_1
|
||||||
|
короткий_переход_если_не_ноль вывести_сообщение
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
; --- КОД ОШИБКИ (на всякий случай) ---
|
||||||
|
; Если мы сюда попали, значит переход НЕ сработал (ошибка)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_fail
|
||||||
|
переместить_имм рдикс, len_msg_fail
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 14
|
||||||
|
msg_fail: .строка_нуль "Ошибка: переход не сработал!"
|
||||||
|
.константа len_msg_fail = 28
|
||||||
131
jumps/сложный_тест1.квс
Normal file
131
jumps/сложный_тест1.квс
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
; сложный_тест1.квс
|
||||||
|
; Тест: два перехода и два мусорных сегмента
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10 (не ноль)
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5 (для сравнения)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: короткий_переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
короткий_переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: короткий_переход_если_равно
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Нам нужно ПРЫГНУТЬ через мертвый код, если ZF НЕ 1 (т.е. ZF = 0).
|
||||||
|
; У нас нет инструкции 'короткий_переход_если_не_равно' (jne), но она эквивалентна 'короткий_переход_если_не_ноль' (jnz) для флага ZF.
|
||||||
|
; Однако, у нас есть 'короткий_переход_если_равно' (je), который сработает при ZF=1.
|
||||||
|
; Мы хотим, чтобы переход НЕ срабатывал при ZF=0.
|
||||||
|
; Поэтому мы используем 'короткий_переход_если_равно' и прыгаем к метке ПОСЛЕ мертвого кода, если ZF=1.
|
||||||
|
; Но ZF=0, поэтому переход НЕ сработает, и выполнение пойдёт на следующую инструкцию - в мертвый код.
|
||||||
|
; Нам нужно наоборот: прыгнуть, если ZF=0.
|
||||||
|
; Используем безусловный переход ПОСЛЕ мертвого кода, чтобы обойти его, если ZF=0.
|
||||||
|
; Правильная логика:
|
||||||
|
; cmp ...
|
||||||
|
; je мимо_мертвого_кода_2 (переход, если ZF=1)
|
||||||
|
; [мертвый код 2]
|
||||||
|
; мимо_мертвого_кода_2:
|
||||||
|
; [продолжение кода]
|
||||||
|
|
||||||
|
; Итак, мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0 (т.е. если НЕ равны).
|
||||||
|
; У нас есть только 'je'. Значит, мы прыгаем МИМО, если ZF=1 (равны).
|
||||||
|
; Мы НЕ хотим прыгать мимо, если ZF=0.
|
||||||
|
; Поэтому: cmp, je (прыгнуть мимо, если ZF=1), [мертвый код], [метка мимо], [остальной код]
|
||||||
|
; Это означает: если ZF=1 -> прыгаем мимо. Если ZF=0 -> выполняем мертвый код.
|
||||||
|
; Это НЕ то, что нам нужно.
|
||||||
|
|
||||||
|
; Нам нужно: если ZF=0 -> прыгаем мимо. Если ZF=1 -> выполняем мертвый код (или идём дальше в него).
|
||||||
|
; У нас нет jne/jnz. Используем логику: если НЕ (ZF=1), то прыгаем.
|
||||||
|
; Или: используем безусловный переход после мертвого кода, но перед ним поставим je на метку ПОСЛЕ безусловного перехода.
|
||||||
|
; Это хитро, но работает:
|
||||||
|
; cmp rax, rbx
|
||||||
|
; je метка_после_безусловного (ZF=1 -> прыгаем, обходим безусловный переход)
|
||||||
|
; короткий_переход мимо_мертвого_кода_2 (ZF=0 -> прыгаем через мертвый код)
|
||||||
|
; метка_после_безусловного:
|
||||||
|
; [мертвый код 2 - выполнится, если ZF=1]
|
||||||
|
; мимо_мертвого_кода_2:
|
||||||
|
; [продолжение]
|
||||||
|
|
||||||
|
; Но мы хотим, чтобы мертвый код НЕ выполнялся, если ZF=0.
|
||||||
|
; cmp rax, rbx (ZF = 0)
|
||||||
|
; je метка_после_безусловного (ZF=0, переход НЕ сработает)
|
||||||
|
; короткий_переход мимо_мертвого_кода_2 (ZF=0, переход СРАБОТАЕТ, прыгаем мимо)
|
||||||
|
; метка_после_безусловного: [попадаем сюда, если ZF=1]
|
||||||
|
; [мертвый код 2 - выполнится, если ZF=1]
|
||||||
|
; мимо_мертвого_кода_2: [попадаем сюда, если ZF=0 (прыгнули) или если ZF=1 (прошли через мертвый код)]
|
||||||
|
; [продолжение кода]
|
||||||
|
|
||||||
|
; Это работает! Если ZF=0 (не равны), мы прыгаем мимо мертвого кода 2.
|
||||||
|
; Если ZF=1 (равны), мы пропускаем безусловный переход и попадаем в мертвый код 2.
|
||||||
|
; Нам нужно наоборот: прыгать мимо, если ZF=0 (не равны).
|
||||||
|
; Значит, если cmp показывает НЕ равны (ZF=0), мы хотим прыгнуть.
|
||||||
|
; У нас нет jne. Но мы можем использовать логику: if (ZF == 0) jmp; (псевдокод).
|
||||||
|
; Это можно выразить как: if (ZF == 1) goto skip_jmp; jmp target; skip_jmp: ... (псевдокод).
|
||||||
|
; Это и есть: cmp ...; je skip_jmp; jmp target; skip_jmp: ...
|
||||||
|
; Где 'jmp target' - это прыжок, который происходит, если ZF=0 (т.е. когда je НЕ сработал).
|
||||||
|
; Итак:
|
||||||
|
; cmp rax, rbx (ZF=0)
|
||||||
|
; je skip_jmp (ZF=0, переход НЕ сработает -> идем дальше)
|
||||||
|
; короткий_переход мимо_мертвого_кода_2 (ZF=0, СРАБОТАЕТ -> прыгаем мимо мертвого кода)
|
||||||
|
; skip_jmp: (ZF=1, мы сюда попали, прыгнув через безусловный переход)
|
||||||
|
; [мертвый код 2 - выполнится ТОЛЬКО если ZF=1]
|
||||||
|
; мимо_мертвого_кода_2:
|
||||||
|
; [продолжение]
|
||||||
|
|
||||||
|
; Это как раз то, что нужно!
|
||||||
|
; cmp rax, rbx (ZF=0)
|
||||||
|
; je skip_jmp (ZF=0 -> не прыгаем)
|
||||||
|
; короткий_переход мимо_мертвого_кода_2 (ZF=0 -> прыгаем мимо мертвого кода 2)
|
||||||
|
; skip_jmp: (ZF=1 -> сюда попали, прыгнув через безусловный переход)
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
короткий_переход_если_равно skip_jmp
|
||||||
|
короткий_переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13 ; Исправлено на длину "Успех!\n" (10 байт + 1 \n)
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 14
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 14
|
||||||
93
jumps/сложный_тест2.квс
Normal file
93
jumps/сложный_тест2.квс
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
; сложный_тест2.квс
|
||||||
|
; Тест: три перехода и три мусорных сегмента
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: короткий_переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
короткий_переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: короткий_переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_равно skip_jmp_2
|
||||||
|
короткий_переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: короткий_переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше skip_jmp_3
|
||||||
|
короткий_переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
; "Мертвый код 3!" = 12 букв * 3 байта + 1 (!) = 36 + 1 = 37 байт. len = 37
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 37
|
||||||
|
; "Мертвый код 2!" = 12 букв * 3 байта + 1 (!) = 36 + 1 = 37 байт. len = 37
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 37
|
||||||
|
; "Мертвый код 1!" = 12 букв * 3 байта + 1 (!) = 36 + 1 = 37 байт. len = 37
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 37
|
||||||
114
jumps/сложный_тест3.квс
Normal file
114
jumps/сложный_тест3.квс
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
; сложный_тест3.квс
|
||||||
|
; Тест: четыре перехода и четыре мусорных сегмента
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: короткий_переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
короткий_переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: короткий_переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_равно skip_jmp_2
|
||||||
|
короткий_переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: короткий_переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше skip_jmp_3
|
||||||
|
короткий_переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: короткий_переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
короткий_переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 2 (\n) = 13 байт на содержимое. len = 13
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 18
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 18
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 18
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 18
|
||||||
137
jumps/сложный_тест4.квс
Normal file
137
jumps/сложный_тест4.квс
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
; сложный_тест4.квс
|
||||||
|
; Тест: пять переходов и пять мусорных сегментов
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: короткий_переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
короткий_переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: короткий_переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_равно skip_jmp_2
|
||||||
|
короткий_переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: короткий_переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше skip_jmp_3
|
||||||
|
короткий_переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: короткий_переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
короткий_переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ПЯТЫЙ ПЕРЕХОД: короткий_переход_если_меньше_или_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jle: ZF=1 ИЛИ SF != OF. ZF=0 (ложь), SF != OF (0 != 0, ложь). jle НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 5, если jle НЕ сработает (т.е. если rax > rbx).
|
||||||
|
; Используем: jle skip_jmp_5 (переход НЕ сработает); jmp мимо_мертвого_кода_5 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше_или_равно skip_jmp_5
|
||||||
|
короткий_переход мимо_мертвого_кода_5
|
||||||
|
skip_jmp_5:
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jle не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_5:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 2 (\n) = 13 байт на содержимое. len = 13
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 18
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 18
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 18
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 18
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 18
|
||||||
157
jumps/сложный_тест5.квс
Normal file
157
jumps/сложный_тест5.квс
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
; сложный_тест5.квс
|
||||||
|
; Тест: шесть переходов и шесть мусорных сегментов
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: короткий_переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
короткий_переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: короткий_переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_равно skip_jmp_2
|
||||||
|
короткий_переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: короткий_переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше skip_jmp_3
|
||||||
|
короткий_переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: короткий_переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
короткий_переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ПЯТЫЙ ПЕРЕХОД: короткий_переход_если_меньше_или_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jle: ZF=1 ИЛИ SF != OF. ZF=0 (ложь), SF != OF (0 != 0, ложь). jle НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 5, если jle НЕ сработает (т.е. если rax > rbx).
|
||||||
|
; Используем: jle skip_jmp_5 (переход НЕ сработает); jmp мимо_мертвого_кода_5 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше_или_равно skip_jmp_5
|
||||||
|
короткий_переход мимо_мертвого_кода_5
|
||||||
|
skip_jmp_5:
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jle не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_5:
|
||||||
|
|
||||||
|
; ШЕСТОЙ ПЕРЕХОД: короткий_переход_если_больше_или_равно
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jge: SF=OF. SF=0, OF=0, SF=OF (0=0). jge СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 6, если jge сработает (т.е. если rax >= rbx).
|
||||||
|
короткий_переход_если_больше_или_равно мимо_мертвого_кода_6
|
||||||
|
; --- МЕРТВЫЙ КОД 6 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jge сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_6:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 2 (\n) = 13 байт на содержимое. len = 13
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
; "Мертвый код 6!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_6: .строка_нуль "Мертвый код 6!"
|
||||||
|
.константа len_msg_dead_6 = 18
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 18
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 18
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 18
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 18
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 18
|
||||||
180
jumps/сложный_тест6.квс
Normal file
180
jumps/сложный_тест6.квс
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
; сложный_тест6.квс
|
||||||
|
; Тест: семь переходов и семь мусорных сегментов
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: короткий_переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
короткий_переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: короткий_переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_равно skip_jmp_2
|
||||||
|
короткий_переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: короткий_переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше skip_jmp_3
|
||||||
|
короткий_переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: короткий_переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
короткий_переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ПЯТЫЙ ПЕРЕХОД: короткий_переход_если_меньше_или_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jle: ZF=1 ИЛИ SF != OF. ZF=0 (ложь), SF != OF (0 != 0, ложь). jle НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 5, если jle НЕ сработает (т.е. если rax > rbx).
|
||||||
|
; Используем: jle skip_jmp_5 (переход НЕ сработает); jmp мимо_мертвого_кода_5 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше_или_равно skip_jmp_5
|
||||||
|
короткий_переход мимо_мертвого_кода_5
|
||||||
|
skip_jmp_5:
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jle не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_5:
|
||||||
|
|
||||||
|
; ШЕСТОЙ ПЕРЕХОД: короткий_переход_если_больше_или_равно
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jge: SF=OF. SF=0, OF=0, SF=OF (0=0). jge СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 6, если jge сработает (т.е. если rax >= rbx).
|
||||||
|
короткий_переход_если_больше_или_равно мимо_мертвого_кода_6
|
||||||
|
; --- МЕРТВЫЙ КОД 6 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jge сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_6:
|
||||||
|
|
||||||
|
; СЕДЬМОЙ ПЕРЕХОД: короткий_переход_если_перенос
|
||||||
|
; Выполним вычитание, которое вызовет перенос: rbx - rax = 5 - 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
; rbx - rax = 5 - 10 -> CF=1
|
||||||
|
вычесть рбикс, раикс ; rbx = rbx - rax = 5 - 10. Это вызовет перенос (CF=1).
|
||||||
|
; Условие jc: CF=1. CF=1. jc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 7, если jc сработает (т.е. если был перенос).
|
||||||
|
короткий_переход_если_перенос мимо_мертвого_кода_7
|
||||||
|
; --- МЕРТВЫЙ КОД 7 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_7:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 2 (\n) = 13 байт на содержимое. len = 13
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
; "Мертвый код 7!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_7: .строка_нуль "Мертвый код 7!"
|
||||||
|
.константа len_msg_dead_7 = 18
|
||||||
|
; "Мертвый код 6!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_6: .строка_нуль "Мертвый код 6!"
|
||||||
|
.константа len_msg_dead_6 = 18
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 18
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 18
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 18
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 18
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 18
|
||||||
200
jumps/сложный_тест7.квс
Normal file
200
jumps/сложный_тест7.квс
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
; сложный_тест7.квс
|
||||||
|
; Тест: восемь переходов и восемь мусорных сегментов
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: короткий_переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
короткий_переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: короткий_переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_равно skip_jmp_2
|
||||||
|
короткий_переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: короткий_переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше skip_jmp_3
|
||||||
|
короткий_переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: короткий_переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
короткий_переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ПЯТЫЙ ПЕРЕХОД: короткий_переход_если_меньше_или_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jle: ZF=1 ИЛИ SF != OF. ZF=0 (ложь), SF != OF (0 != 0, ложь). jle НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 5, если jle НЕ сработает (т.е. если rax > rbx).
|
||||||
|
; Используем: jle skip_jmp_5 (переход НЕ сработает); jmp мимо_мертвого_кода_5 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше_или_равно skip_jmp_5
|
||||||
|
короткий_переход мимо_мертвого_кода_5
|
||||||
|
skip_jmp_5:
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jle не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_5:
|
||||||
|
|
||||||
|
; ШЕСТОЙ ПЕРЕХОД: короткий_переход_если_больше_или_равно
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jge: SF=OF. SF=0, OF=0, SF=OF (0=0). jge СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 6, если jge сработает (т.е. если rax >= rbx).
|
||||||
|
короткий_переход_если_больше_или_равно мимо_мертвого_кода_6
|
||||||
|
; --- МЕРТВЫЙ КОД 6 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jge сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_6:
|
||||||
|
|
||||||
|
; СЕДЬМОЙ ПЕРЕХОД: короткий_переход_если_перенос
|
||||||
|
; Выполним вычитание, которое вызовет перенос: rbx - rax = 5 - 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
; rbx - rax = 5 - 10 -> CF=1
|
||||||
|
вычесть рбикс, раикс ; rbx = rbx - rax = 5 - 10. Это вызовет перенос (CF=1).
|
||||||
|
; Условие jc: CF=1. CF=1. jc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 7, если jc сработает (т.е. если был перенос).
|
||||||
|
короткий_переход_если_перенос мимо_мертвого_кода_7
|
||||||
|
; --- МЕРТВЫЙ КОД 7 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_7:
|
||||||
|
|
||||||
|
; ВОСЬМОЙ ПЕРЕХОД: короткий_переход_если_нет_переноса
|
||||||
|
; Убедимся, что CF=0. Выполним операцию, которая сбросит CF.
|
||||||
|
сравнить раикс, раикс ; CF = 0 (так как rax - rax = 0, без переноса)
|
||||||
|
; Условие jnc: CF=0. CF=0. jnc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 8, если jnc сработает (т.е. если НЕ было переноса).
|
||||||
|
короткий_переход_если_нет_переноса мимо_мертвого_кода_8
|
||||||
|
; --- МЕРТВЫЙ КОД 8 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jnc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_8:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 2 (\n) = 13 байт на содержимое. len = 13
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
; "Мертвый код 8!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_8: .строка_нуль "Мертвый код 8!"
|
||||||
|
.константа len_msg_dead_8 = 18
|
||||||
|
; "Мертвый код 7!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_7: .строка_нуль "Мертвый код 7!"
|
||||||
|
.константа len_msg_dead_7 = 18
|
||||||
|
; "Мертвый код 6!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_6: .строка_нуль "Мертвый код 6!"
|
||||||
|
.константа len_msg_dead_6 = 18
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 18
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 18
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 18
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 18
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 18
|
||||||
217
jumps/сложный_тест8.квс
Normal file
217
jumps/сложный_тест8.квс
Normal file
|
|
@ -0,0 +1,217 @@
|
||||||
|
; сложный_тест8.квс
|
||||||
|
; Тест: девять переходов и девять мусорных сегментов (включая короткий безусловный)
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: короткий_переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
короткий_переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ВТОРОЙ ПЕРЕХОД: короткий_переход_если_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> ZF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; ZF=0, значит je НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 2, если ZF=0.
|
||||||
|
; Используем: je skip_jmp_2 (переход НЕ сработает); jmp мимо_мертвого_кода_2 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_равно skip_jmp_2
|
||||||
|
короткий_переход мимо_мертвого_кода_2
|
||||||
|
skip_jmp_2:
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как ZF=0)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_2:
|
||||||
|
|
||||||
|
; ТРЕТИЙ ПЕРЕХОД: короткий_переход_если_меньше (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; SF=0, OF=0. Условие jl: SF != OF (0 != 0 - ложь). jl НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 3, если jl НЕ сработает (т.е. если rax >= rbx).
|
||||||
|
; Используем: jl skip_jmp_3 (переход НЕ сработает); jmp мимо_мертвого_кода_3 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше skip_jmp_3
|
||||||
|
короткий_переход мимо_мертвого_кода_3
|
||||||
|
skip_jmp_3:
|
||||||
|
; --- МЕРТВЫЙ КОД 3 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jl не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_3
|
||||||
|
переместить_имм рдикс, len_msg_dead_3
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_3:
|
||||||
|
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: короткий_переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
короткий_переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ПЯТЫЙ ПЕРЕХОД: короткий_переход_если_меньше_или_равно (и безусловный)
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jle: ZF=1 ИЛИ SF != OF. ZF=0 (ложь), SF != OF (0 != 0, ложь). jle НЕ сработает.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 5, если jle НЕ сработает (т.е. если rax > rbx).
|
||||||
|
; Используем: jle skip_jmp_5 (переход НЕ сработает); jmp мимо_мертвого_кода_5 (переход СРАБОТАЕТ)
|
||||||
|
короткий_переход_если_меньше_или_равно skip_jmp_5
|
||||||
|
короткий_переход мимо_мертвого_кода_5
|
||||||
|
skip_jmp_5:
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jle не сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_5:
|
||||||
|
|
||||||
|
; ШЕСТОЙ ПЕРЕХОД: короткий_переход_если_больше_или_равно
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jge: SF=OF. SF=0, OF=0, SF=OF (0=0). jge СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 6, если jge сработает (т.е. если rax >= rbx).
|
||||||
|
короткий_переход_если_больше_или_равно мимо_мертвого_кода_6
|
||||||
|
; --- МЕРТВЫЙ КОД 6 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jge сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_6:
|
||||||
|
|
||||||
|
; СЕДЬМОЙ ПЕРЕХОД: короткий_переход_если_перенос
|
||||||
|
; Выполним вычитание, которое вызовет перенос: rbx - rax = 5 - 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
; rbx - rax = 5 - 10 -> CF=1
|
||||||
|
вычесть рбикс, раикс ; rbx = rbx - rax = 5 - 10. Это вызовет перенос (CF=1).
|
||||||
|
; Условие jc: CF=1. CF=1. jc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 7, если jc сработает (т.е. если был перенос).
|
||||||
|
короткий_переход_если_перенос мимо_мертвого_кода_7
|
||||||
|
; --- МЕРТВЫЙ КОД 7 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_7:
|
||||||
|
|
||||||
|
; ВОСЬМОЙ ПЕРЕХОД: короткий_переход_если_нет_переноса
|
||||||
|
; Убедимся, что CF=0. Выполним операцию, которая сбросит CF.
|
||||||
|
сравнить раикс, раикс ; CF = 0 (так как rax - rax = 0, без переноса)
|
||||||
|
; Условие jnc: CF=0. CF=0. jnc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 8, если jnc сработает (т.е. если НЕ было переноса).
|
||||||
|
короткий_переход_если_нет_переноса мимо_мертвого_кода_8
|
||||||
|
; --- МЕРТВЫЙ КОД 8 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jnc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_8:
|
||||||
|
|
||||||
|
; ДЕВЯТЫЙ ПЕРЕХОД: короткий_переход (безусловный)
|
||||||
|
; Просто прыгаем мимо мертвого кода 9.
|
||||||
|
короткий_переход мимо_мертвого_кода_9
|
||||||
|
; --- МЕРТВЫЙ КОД 9 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jmp сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_9:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 2 (\n) = 13 байт на содержимое. len = 13
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
; "Мертвый код 9!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_9: .строка_нуль "Мертвый код 9!"
|
||||||
|
.константа len_msg_dead_9 = 18
|
||||||
|
; "Мертвый код 8!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_8: .строка_нуль "Мертвый код 8!"
|
||||||
|
.константа len_msg_dead_8 = 18
|
||||||
|
; "Мертвый код 7!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_7: .строка_нуль "Мертвый код 7!"
|
||||||
|
.константа len_msg_dead_7 = 18
|
||||||
|
; "Мертвый код 6!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_6: .строка_нуль "Мертвый код 6!"
|
||||||
|
.константа len_msg_dead_6 = 18
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 18
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 18
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 18
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 18
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 18
|
||||||
204
jumps/сложный_тест9.квс
Normal file
204
jumps/сложный_тест9.квс
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
; сложный_тест9.квс
|
||||||
|
; Тест: запутанные переходы, крякмис
|
||||||
|
|
||||||
|
.текст
|
||||||
|
.глобал _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; Инициализация регистров
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм рсикс, 10 ; rcx = 10 (для проверки ZF в jz)
|
||||||
|
|
||||||
|
; ПЕРВЫЙ ПЕРЕХОД: короткий_переход_если_не_ноль
|
||||||
|
; ZF=0 (так как rax=10), значит jnz сработает
|
||||||
|
; Прыгаем к метке 'проверка_2', пропуская мертвый_код_1
|
||||||
|
короткий_переход_если_не_ноль проверка_2
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 1 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_1
|
||||||
|
переместить_имм рдикс, len_msg_dead_1
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_2:
|
||||||
|
; ДОПОЛНИТЕЛЬНЫЙ ПЕРЕХОД 1: "Два шага вперед" - короткий_переход через мертвый_код_2 и мертвый_код_3
|
||||||
|
; Прыгаем к проверка_4, минуя мертвый_код_2 и мертвый_код_3
|
||||||
|
короткий_переход проверка_4
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 2 ---
|
||||||
|
; Этот код НЕ должен выполниться из-за прыжка выше
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_2
|
||||||
|
переместить_имм рдикс, len_msg_dead_2
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мертвый_код_3:
|
||||||
|
; ЖИВОЙ КОД 3: Этот код выполнится благодаря прыжку "назад"
|
||||||
|
; Выведем сообщение, чтобы убедиться, что он выполнился
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_live_from_3
|
||||||
|
переместить_имм рдикс, len_msg_live_from_3
|
||||||
|
вызов_системы
|
||||||
|
; ДОПОЛНИТЕЛЬНЫЙ ПЕРЕХОД 3: "Четыре вперед" - переход через мертвый_код_4, 5, 6, 7
|
||||||
|
; Цель слишком далеко для короткого перехода. Используем длинный.
|
||||||
|
; Прыгаем к проверка_8
|
||||||
|
переход проверка_8
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_4:
|
||||||
|
; ЧЕТВЁРТЫЙ ПЕРЕХОД: короткий_переход_если_больше
|
||||||
|
; Сравниваем rax (10) и rbx (5) -> rax > rbx, ZF=0, SF=0, OF=0
|
||||||
|
сравнить раикс, рбикс
|
||||||
|
; Условие jg: ZF=0 (истина) И SF=OF (0=0, истина). jg СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 4, если jg сработает (т.е. если rax > rbx).
|
||||||
|
короткий_переход_если_больше мимо_мертвого_кода_4
|
||||||
|
; --- МЕРТВЫЙ КОД 4 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jg сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_4
|
||||||
|
переместить_имм рдикс, len_msg_dead_4
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
мимо_мертвого_кода_4:
|
||||||
|
|
||||||
|
; ДОПОЛНИТЕЛЬНЫЙ ПЕРЕХОД 2: "Один назад" - короткий_переход к мертвому_коду_3 (делая его живым)
|
||||||
|
короткий_переход мертвый_код_3
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 5 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_5
|
||||||
|
переместить_имм рдикс, len_msg_dead_5
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 6 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_6
|
||||||
|
переместить_имм рдикс, len_msg_dead_6
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
; --- МЕРТВЫЙ КОД 7 ---
|
||||||
|
; Этот код НЕ должен выполниться
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_7
|
||||||
|
переместить_имм рдикс, len_msg_dead_7
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
проверка_8:
|
||||||
|
; СЕДЬМОЙ ПЕРЕХОД: короткий_переход_если_перенос
|
||||||
|
; Выполним вычитание, которое вызовет перенос: rbx - rax = 5 - 10
|
||||||
|
переместить_имм рбикс, 5 ; rbx = 5
|
||||||
|
переместить_имм раикс, 10 ; rax = 10
|
||||||
|
; rbx - rax = 5 - 10 -> CF=1
|
||||||
|
вычесть рбикс, раикс ; rbx = rbx - rax = 5 - 10. Это вызовет перенос (CF=1).
|
||||||
|
; Условие jc: CF=1. CF=1. jc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 8, если jc сработает (т.е. если был перенос).
|
||||||
|
короткий_переход_если_перенос мимо_мертвого_кода_8
|
||||||
|
; --- МЕРТВЫЙ КОД 8 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_8
|
||||||
|
переместить_имм рдикс, len_msg_dead_8
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_8:
|
||||||
|
|
||||||
|
; ВОСЬМОЙ ПЕРЕХОД: короткий_переход_если_нет_переноса
|
||||||
|
; Убедимся, что CF=0. Выполним операцию, которая сбросит CF.
|
||||||
|
сравнить раикс, раикс ; CF = 0 (так как rax - rax = 0, без переноса)
|
||||||
|
; Условие jnc: CF=0. CF=0. jnc СРАБОТАЕТ.
|
||||||
|
; Мы хотим прыгнуть МИМО мертвого кода 9, если jnc сработает (т.е. если НЕ было переноса).
|
||||||
|
короткий_переход_если_нет_переноса мимо_мертвого_кода_9
|
||||||
|
; --- МЕРТВЫЙ КОД 9 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jnc сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_9
|
||||||
|
переместить_имм рдикс, len_msg_dead_9
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_9:
|
||||||
|
|
||||||
|
; ДЕВЯТЫЙ ПЕРЕХОД: короткий_переход (безусловный)
|
||||||
|
; Просто прыгаем мимо мертвого кода 10.
|
||||||
|
короткий_переход мимо_мертвого_кода_10
|
||||||
|
; --- МЕРТВЫЙ КОД 10 ---
|
||||||
|
; Этот код НЕ должен выполниться (так как jmp сработал)
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_dead_10
|
||||||
|
переместить_имм рдикс, len_msg_dead_10
|
||||||
|
вызов_системы
|
||||||
|
; ---------------------
|
||||||
|
|
||||||
|
мимо_мертвого_кода_10:
|
||||||
|
|
||||||
|
; --- ВЫВОД ЦЕЛЕВОГО СООБЩЕНИЯ ---
|
||||||
|
вывести_сообщение:
|
||||||
|
переместить_имм раикс, 1
|
||||||
|
переместить_имм рдиай, 1
|
||||||
|
переместить_имм рсиай, msg_success
|
||||||
|
переместить_имм рдикс, len_msg_success
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
; --- ЗАВЕРШЕНИЕ ---
|
||||||
|
переместить_имм раикс, 60
|
||||||
|
переместить_имм рдиай, 0
|
||||||
|
вызов_системы
|
||||||
|
|
||||||
|
.данные
|
||||||
|
; Перемешиваем строки и константы
|
||||||
|
; "Живой из 3!\n" = 8 букв * 2 + 1 (!) + 2 (\n) = 16 + 3 = 19 байт на содержимое. len = 19
|
||||||
|
msg_live_from_3: .строка_нуль "Живой из 3!\n"
|
||||||
|
.константа len_msg_live_from_3 = 19
|
||||||
|
; "Успех!\n" = 5 букв * 2 + 1 (!) + 2 (\n) = 13 байт на содержимое. len = 13
|
||||||
|
msg_success: .строка_нуль "Успех!\n"
|
||||||
|
.константа len_msg_success = 13
|
||||||
|
; "Мертвый код 10!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_10: .строка_нуль "Мертвый код 10!"
|
||||||
|
.константа len_msg_dead_10 = 18
|
||||||
|
; "Мертвый код 9!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_9: .строка_нуль "Мертвый код 9!"
|
||||||
|
.константа len_msg_dead_9 = 18
|
||||||
|
; "Мертвый код 8!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_8: .строка_нуль "Мертвый код 8!"
|
||||||
|
.константа len_msg_dead_8 = 18
|
||||||
|
; "Мертвый код 7!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_7: .строка_нуль "Мертвый код 7!"
|
||||||
|
.константа len_msg_dead_7 = 18
|
||||||
|
; "Мертвый код 6!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_6: .строка_нуль "Мертвый код 6!"
|
||||||
|
.константа len_msg_dead_6 = 18
|
||||||
|
; "Мертвый код 5!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_5: .строка_нуль "Мертвый код 5!"
|
||||||
|
.константа len_msg_dead_5 = 18
|
||||||
|
; "Мертвый код 4!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_4: .строка_нуль "Мертвый код 4!"
|
||||||
|
.константа len_msg_dead_4 = 18
|
||||||
|
; "Мертвый код 3!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_3: .строка_нуль "Мертвый код 3!"
|
||||||
|
.константа len_msg_dead_3 = 18
|
||||||
|
; "Мертвый код 2!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_2: .строка_нуль "Мертвый код 2!"
|
||||||
|
.константа len_msg_dead_2 = 18
|
||||||
|
; "Мертвый код 1!" = 7 букв * 2 + 4 символа * 1 = 14 + 4 = 18 байт на содержимое. len = 18
|
||||||
|
msg_dead_1: .строка_нуль "Мертвый код 1!"
|
||||||
|
.константа len_msg_dead_1 = 18
|
||||||
Loading…
Reference in a new issue