From 5f7d212dbf80dd7ab04cf11c596e80234fb029f2 Mon Sep 17 00:00:00 2001 From: mzhoot Date: Sun, 17 May 2026 11:22:39 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20.bss?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kvs_builder.py | 69 +++++++++++++++---- kvs_data.py | 10 +++ kvs_parser.py | 50 ++++++++++++++ kvs_pass1.py | 34 +++++++++- kvs_pass2.py | 37 +++++++++- kvs_pass2_encoder.py | 116 ++++++++++++++++++-------------- todo.txt | 7 +- тесты/test_bss.квс | 9 +++ тесты/test_success.квс | 2 +- тесты/test_success2.квс | 30 +++++++++ тесты/test_success3.квс | 36 ++++++++++ 11 files changed, 328 insertions(+), 72 deletions(-) create mode 100644 тесты/test_bss.квс create mode 100644 тесты/test_success2.квс create mode 100644 тесты/test_success3.квс diff --git a/kvs_builder.py b/kvs_builder.py index 7893157..ae0b95c 100644 --- a/kvs_builder.py +++ b/kvs_builder.py @@ -9,11 +9,11 @@ import sys import struct import os sys.path.insert(0, '.') -from kvs_data import PAGE_SIZE, align_up +from kvs_data import PAGE_SIZE, align_up, SHT_NOBITS, SHF_WRITE, SHF_ALLOC def read_csv(input_file, vaddr_text, vaddr_data, text_size, data_size): """Загружает байты из CSV используя точные виртуальные адреса""" - text_bytes = bytearray(text_size) # точный размер из pass1 + text_bytes = bytearray(text_size) data_bytes = bytearray(data_size) with open(input_file, 'r', encoding='utf-8') as f: @@ -72,8 +72,12 @@ def read_pass1(input_file): def create_elf(text_bytes, data_bytes, pass1_data, labels, output_file): vaddr_text = pass1_data.get("vaddr_text", 0x401000) text_size = pass1_data.get("text_size", len(text_bytes)) - # Вычисляем vaddr_data динамически, как в kvs_8 + data_size = pass1_data.get("data_size", len(data_bytes)) + bnd_size = pass1_data.get("bnd_size", 0) + + # Вычисляем виртуальные адреса vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE) + vaddr_bnd = pass1_data.get("vaddr_bnd", align_up(vaddr_data + data_size, PAGE_SIZE)) offset_text = pass1_data.get("offset_text", 0x1000) offset_data = align_up(offset_text + len(text_bytes), PAGE_SIZE) @@ -85,13 +89,18 @@ def create_elf(text_bytes, data_bytes, pass1_data, labels, output_file): entry_addr = vaddr_text + labels.get(entry_point_name, 0) comment_content = "Сборщик КВС".encode('utf-8') + b'\x00' - shstrtab_content = b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00" + + # shstrtab с учётом .bss + if bnd_size > 0: + shstrtab_content = b"\x00.text\x00.data\x00.bss\x00.comment\x00.shstrtab\x00" + else: + shstrtab_content = b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00" elf_header_size = 64 ph_size = 56 ph_num = 3 shdr_size = 64 - shdr_num = 5 + shdr_num = 5 + (1 if bnd_size > 0 else 0) # 5 базовых + .bss если есть file_size = shdr_offset + shdr_num * shdr_size elf_data = bytearray(file_size) @@ -111,13 +120,23 @@ def create_elf(text_bytes, data_bytes, pass1_data, labels, output_file): p_filesz, p_memsz, PAGE_SIZE ) + # Program headers ph0 = phdr(1, 4, 0, 0x400000, elf_header_size + ph_num * ph_size, PAGE_SIZE) ph1 = phdr(1, 5, offset_text, vaddr_text, len(text_bytes), align_up(len(text_bytes), PAGE_SIZE)) - ph2 = phdr(1, 6, offset_data, vaddr_data, len(data_bytes), align_up(len(data_bytes), PAGE_SIZE)) + + if bnd_size > 0: + # Сегмент данных включает .data + .bss + # p_filesz — только данные в файле, p_memsz — данные + BSS в памяти + data_segment_filesz = len(data_bytes) + data_segment_memsz = align_up(len(data_bytes) + bnd_size, PAGE_SIZE) + ph2 = phdr(1, 6, offset_data, vaddr_data, data_segment_filesz, data_segment_memsz) + else: + ph2 = phdr(1, 6, offset_data, vaddr_data, len(data_bytes), align_up(len(data_bytes), 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_bytes)] = text_bytes elf_data[offset_data : offset_data + len(data_bytes)] = data_bytes elf_data[offset_comment : offset_comment + len(comment_content)] = comment_content @@ -129,13 +148,34 @@ def create_elf(text_bytes, data_bytes, pass1_data, labels, output_file): 0, 0, addralign, 0 ) - sh0 = shdr(0, 0, 0, 0, 0, 0) - sh1 = shdr(1, 1, 6, vaddr_text, offset_text, len(text_bytes), 16) - sh2 = shdr(7, 1, 3, vaddr_data, offset_data, len(data_bytes), 8) - sh3 = shdr(13, 1, 0, 0, offset_comment, len(comment_content), 1) - sh4 = shdr(22, 3, 0, 0, shstrtab_offset, len(shstrtab_content), 1) + # Индексы имён в shstrtab зависят от наличия .bss + if bnd_size > 0: + name_text = 1 # ".text" + name_data = 7 # ".data" + name_bss = 13 # ".bss" + name_comment = 18 # ".comment" + name_shstrtab = 27 # ".shstrtab" + else: + name_text = 1 + name_data = 7 + name_comment = 13 + name_shstrtab = 22 + + # Section headers + sh0 = shdr(0, 0, 0, 0, 0, 0) # NULL + sh1 = shdr(name_text, 1, 6, vaddr_text, offset_text, len(text_bytes), 16) # .text + sh2 = shdr(name_data, 1, 3, vaddr_data, offset_data, len(data_bytes), 8) # .data + + if bnd_size > 0: + sh3 = shdr(name_bss, SHT_NOBITS, SHF_WRITE | SHF_ALLOC, vaddr_bnd, 0, bnd_size, 16) # .bss + sh4 = shdr(name_comment, 1, 0, 0, offset_comment, len(comment_content), 1) # .comment + sh5 = shdr(name_shstrtab, 3, 0, 0, shstrtab_offset, len(shstrtab_content), 1) # .shstrtab + shdrs = sh0 + sh1 + sh2 + sh3 + sh4 + sh5 + else: + sh3 = shdr(name_comment, 1, 0, 0, offset_comment, len(comment_content), 1) + sh4 = shdr(name_shstrtab, 3, 0, 0, shstrtab_offset, len(shstrtab_content), 1) + shdrs = sh0 + sh1 + sh2 + sh3 + sh4 - shdrs = sh0 + sh1 + sh2 + sh3 + sh4 elf_data[shdr_offset : shdr_offset + len(shdrs)] = shdrs with open(output_file, "wb") as f: @@ -146,7 +186,8 @@ def create_elf(text_bytes, data_bytes, pass1_data, labels, output_file): print(f"Сборщик: ELF-файл создан: {output_file}") print(f" .text: {len(text_bytes)} байт, адрес: 0x{vaddr_text:x}") print(f" .data: {len(data_bytes)} байт, адрес: 0x{vaddr_data:x}") - print(f" Расстояние между секциями: 0x{vaddr_data - vaddr_text:x} байт") + if bnd_size > 0: + print(f" .bss: {bnd_size} байт, адрес: 0x{vaddr_bnd:x}") if __name__ == "__main__": if len(sys.argv) != 4: @@ -158,7 +199,7 @@ if __name__ == "__main__": text_size = pass1_data["text_size"] data_size = pass1_data["data_size"] - # Вычисляем vaddr_data как в kvs_8 + # Вычисляем vaddr_data vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE) text_bytes, data_bytes = read_csv(sys.argv[1], vaddr_text, vaddr_data, text_size, data_size) diff --git a/kvs_data.py b/kvs_data.py index e5f3b52..b6f760a 100644 --- a/kvs_data.py +++ b/kvs_data.py @@ -11,6 +11,16 @@ import struct # === ГЛОБАЛЬНЫЕ КОНСТАНТЫ === +# Константы для секции .бнд (аналог .bss) +SECTION_BND = '.бнд' +SECTION_BND_ELF = '.bss' # Имя секции в ELF-файле (стандарт Linux) + +# ELF-константы для секции типа SHT_NOBITS +SHT_NOBITS = 8 +SHF_WRITE = 0x1 +SHF_ALLOC = 0x2 + + # ELF константы PAGE_SIZE = 0x1000 # Размер страницы памяти (4096 байт) elf_base_vaddr = 0x400000 # Базовый виртуальный адрес ELF diff --git a/kvs_parser.py b/kvs_parser.py index c04be21..190c15e 100644 --- a/kvs_parser.py +++ b/kvs_parser.py @@ -104,19 +104,45 @@ class Parser: return True def parse_directive(self, word): + """ + Разбор директив ассемблера. + Вызывает ошибку при некорректном синтаксисе или контексте. + """ + # === Секции === if word == '.текст': self.current_section = ".text" self.parsed_lines.append(f"DIRECTIVE:{word}") + elif word == '.данные': self.current_section = ".data" self.parsed_lines.append(f"DIRECTIVE:{word}") + + elif word == '.бнд': + self.current_section = ".бнд" + self.parsed_lines.append(f"DIRECTIVE:{word}") + + # === Глобальные метки === elif word == '.глобал': label = self.expect('WORD')[1] self.parsed_lines.append(f"DIRECTIVE:{word}:{label}") + + # === Строковые директивы (запрещены в .бнд) === elif word in ('.строка_нуль', '.строка'): + if self.current_section == ".бнд": + raise ValueError( + "Ошибка: секция .бнд не поддерживает инициализированные данные " + "(используйте .резб, .резс, .рездс, .резкс)" + ) string_tok = self.expect('STRING') self.parsed_lines.append(f"DIRECTIVE:{word}:{self.current_section}:{string_tok[1]}") + + # === Константы (запрещены в .бнд) === elif word == '.константа': + if self.current_section == ".бнд": + raise ValueError( + "Ошибка: секция .бнд не поддерживает инициализированные данные " + "(используйте .резб, .резс, .рездс, .резкс)" + ) name = self.expect('WORD')[1] # Пропускаем '=', если есть eq_tok = self.peek() @@ -125,7 +151,14 @@ class Parser: # Значение может быть WORD или NUMBER value_tok = self.expect_one_of(['WORD', 'NUMBER']) self.parsed_lines.append(f"DIRECTIVE:{word}:{name}:{value_tok[1]}") + + # === Байты (запрещены в .бнд) === elif word == '.байт': + if self.current_section == ".бнд": + raise ValueError( + "Ошибка: секция .бнд не поддерживает инициализированные данные " + "(используйте .резб, .резс, .рездс, .резкс)" + ) bytes_list = [] while True: tok = self.peek() @@ -139,6 +172,23 @@ class Parser: val_tok = self.expect_one_of(['WORD', 'NUMBER', 'STRING']) bytes_list.append(val_tok[1]) self.parsed_lines.append(f"DIRECTIVE:{word}:{self.current_section}:" + ",".join(bytes_list)) + + # === Директивы резервирования (только в .бнд) === + elif word in ('.резб', '.резс', '.рездс', '.резкс'): + if self.current_section != ".бнд": + raise ValueError( + f"Ошибка: директива {word} допустима только внутри секции .бнд" + ) + count_tok = self.expect('NUMBER') + count = int(count_tok[1]) + if count <= 0: + raise ValueError( + f"Ошибка: размер резервирования должен быть положительным целым числом" + ) + self.parsed_lines.append( + f"DIRECTIVE:{word}:{self.current_section}:{count}" + ) + else: raise ValueError(f"Неизвестная директива: {word}") diff --git a/kvs_pass1.py b/kvs_pass1.py index 070e0bd..268e444 100644 --- a/kvs_pass1.py +++ b/kvs_pass1.py @@ -151,7 +151,7 @@ class Pass1: self.labels = {} self.label_sections = {} self.symbols = {} - self.position = {".text": 0, ".data": 0} + self.position = {".text": 0, ".data": 0, ".бнд": 0} self.current_section = ".text" self.entry_point = "_start" @@ -165,6 +165,8 @@ class Pass1: self.current_section = ".text" elif directive == '.данные': self.current_section = ".data" + elif directive == '.бнд': + self.current_section = ".бнд" elif directive == '.глобал': self.entry_point = parts[2] elif directive in ('.строка_нуль', '.строка'): @@ -188,6 +190,23 @@ class Pass1: if len(parts) > 3 and parts[3]: num_bytes = len(parts[3].split(',')) self.position[sec] += num_bytes + + # Директивы резервирования в .бнд + elif directive == '.резб': + count = int(parts[3]) + self.position['.бнд'] += count * 1 + + elif directive == '.резс': + count = int(parts[3]) + self.position['.бнд'] += count * 2 + + elif directive == '.рездс': + count = int(parts[3]) + self.position['.бнд'] += count * 4 + + elif directive == '.резкс': + count = int(parts[3]) + self.position['.бнд'] += count * 8 elif line_type == "LABEL": label_name = parts[1] @@ -292,6 +311,7 @@ class Pass1: def calculate_layout(self): text_size = self.position[".text"] data_size = self.position[".data"] + bnd_size = self.position[".бнд"] elf_header_size = 64 ph_size = 56 @@ -302,21 +322,29 @@ class Pass1: offset_data = align_up(offset_text + text_size, PAGE_SIZE) vaddr_text = text_vaddr_base vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE) + vaddr_bnd = align_up(vaddr_data + data_size, PAGE_SIZE) comment_size = len("Сборщик КВС".encode('utf-8')) + 1 offset_comment = align_up(offset_data + data_size, 1) - shstrtab_size = len(b"\x00.text\x00.data\x00.comment\x00.shstrtab\x00") + # shstrtab теперь включает ".bss" + if bnd_size > 0: + shstrtab_content = b"\x00.text\x00.data\x00.bss\x00.comment\x00.shstrtab\x00" + else: + 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_offset = align_up(shstrtab_offset + shstrtab_size, 16) return { "text_size": text_size, "data_size": data_size, + "bnd_size": bnd_size, "offset_text": offset_text, "offset_data": offset_data, "vaddr_text": vaddr_text, "vaddr_data": vaddr_data, + "vaddr_bnd": vaddr_bnd, "offset_comment": offset_comment, "comment_size": comment_size, "shstrtab_offset": shstrtab_offset, @@ -347,4 +375,4 @@ if __name__ == "__main__": layout = pass1.calculate_layout() write_pass1(layout, pass1.labels, pass1.label_sections, pass1.symbols, sys.argv[2]) - print(f"Проход 1: text_size={layout['text_size']}, data_size={layout['data_size']}") \ No newline at end of file + print(f"Проход 1: text_size={layout['text_size']}, data_size={layout['data_size']}, bnd_size={layout['bnd_size']}") \ No newline at end of file diff --git a/kvs_pass2.py b/kvs_pass2.py index c5b832f..26c5d4b 100644 --- a/kvs_pass2.py +++ b/kvs_pass2.py @@ -91,8 +91,11 @@ class Pass2: self.symbols = symbols self.vaddr_text = pass1_data["vaddr_text"] text_size = pass1_data["text_size"] + data_size = pass1_data["data_size"] self.vaddr_data = align_up(self.vaddr_text + text_size, PAGE_SIZE) - self.position = {".text": 0, ".data": 0} + self.vaddr_bnd = pass1_data.get("vaddr_bnd", align_up(self.vaddr_data + data_size, PAGE_SIZE)) + self.bnd_size = pass1_data.get("bnd_size", 0) + self.position = {".text": 0, ".data": 0, ".бнд": 0} self.current_section = ".text" self.csv_lines = [] self.data_bytes = {".text": bytearray(), ".data": bytearray()} @@ -119,7 +122,14 @@ class Pass2: op_str = operands[1] if op_str in self.labels: sec = self.label_sections[op_str] - addr = self.labels[op_str] + (self.vaddr_text if sec == ".text" else self.vaddr_data) + if sec == ".text": + addr = self.labels[op_str] + self.vaddr_text + elif sec == ".data": + addr = self.labels[op_str] + self.vaddr_data + elif sec == ".бнд": + addr = self.labels[op_str] + self.vaddr_bnd + else: + addr = self.labels[op_str] + self.vaddr_text return hex(addr) elif op_str in self.symbols: return hex(self.symbols[op_str]) @@ -139,6 +149,8 @@ class Pass2: self.current_section = ".text" elif directive == '.данные': self.current_section = ".data" + elif directive == '.бнд': + self.current_section = ".бнд" elif directive in ('.строка_нуль', '.строка'): s = parts[3] if len(parts) > 3 else "" real_s = unescape_string(s) @@ -180,6 +192,23 @@ class Pass2: self.data_bytes[".data"].append(val & 0xFF) self.position[".data"] += len(byte_values) + + # Директивы резервирования в .бнд — не генерируют байты + elif directive == '.резб': + count = int(parts[3]) + self.position['.бнд'] += count * 1 + + elif directive == '.резс': + count = int(parts[3]) + self.position['.бнд'] += count * 2 + + elif directive == '.рездс': + count = int(parts[3]) + self.position['.бнд'] += count * 4 + + elif directive == '.резкс': + count = int(parts[3]) + self.position['.бнд'] += count * 8 elif line_type == "LABEL": label_name = parts[1] @@ -249,4 +278,6 @@ if __name__ == "__main__": print(f"Проход 2: {len(csv_lines)} строк CSV записано в {sys.argv[3]}") print(f" .text: {pass2.position['.text']} байт, виртуальный адрес: 0x{pass2.vaddr_text:x}") - print(f" .data: {pass2.position['.data']} байт, виртуальный адрес: 0x{pass2.vaddr_data:x}") \ No newline at end of file + print(f" .data: {pass2.position['.data']} байт, виртуальный адрес: 0x{pass2.vaddr_data:x}") + if pass2.bnd_size > 0: + print(f" .бнд: {pass2.bnd_size} байт, виртуальный адрес: 0x{pass2.vaddr_bnd:x}") \ No newline at end of file diff --git a/kvs_pass2_encoder.py b/kvs_pass2_encoder.py index 5a62fb9..e2855de 100644 --- a/kvs_pass2_encoder.py +++ b/kvs_pass2_encoder.py @@ -11,13 +11,13 @@ import sys from kvs_data import INSTRUCTIONS, REGISTERS, get_reg_info -def parse_operand(operand, labels, label_sections, symbols, vaddr_text, vaddr_data): +def parse_operand(operand, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd=None): """ Вычисляет значение операнда. Поддерживает: - десятичные числа (123) - шестнадцатеричные (0x7B) - - метки (имя_метки) + - метки (имя_метки) — из .text, .data или .бнд - константы (из .константа) """ if operand.isdigit(): @@ -29,20 +29,29 @@ def parse_operand(operand, labels, label_sections, symbols, vaddr_text, vaddr_da pass if operand in labels: section = label_sections.get(operand, '.text') - base = vaddr_text if section == '.text' else vaddr_data - return labels[operand] + base + if section == '.text': + return labels[operand] + vaddr_text + elif section == '.data': + return labels[operand] + vaddr_data + elif section == '.бнд': + if vaddr_bnd is not None: + return labels[operand] + vaddr_bnd + else: + return labels[operand] + vaddr_data + else: + return labels[operand] + vaddr_text if operand in symbols: return symbols[operand] raise ValueError("Неизвестный операнд: " + operand) -def parse_memory_operand(operand_str, labels, label_sections, vaddr_text, vaddr_data): +def parse_memory_operand(operand_str, labels, label_sections, vaddr_text, vaddr_data, vaddr_bnd=None): """ Разбирает операнд памяти. Возвращает словарь с информацией или None. Поддерживает: - [число] — абсолютный адрес - - [метка] — адрес метки (из .data или .text) + - [метка] — адрес метки (из .data, .text или .бнд) - [регистр] — косвенная адресация (TODO) """ if not operand_str.startswith('[') or not operand_str.endswith(']'): @@ -69,7 +78,14 @@ def parse_memory_operand(operand_str, labels, label_sections, vaddr_text, vaddr_ # Проверяем, является ли содержимое меткой if content in labels: section = label_sections.get(content, '.data') - base = vaddr_text if section == '.text' else vaddr_data + if section == '.text': + base = vaddr_text + elif section == '.data': + base = vaddr_data + elif section == '.бнд': + base = vaddr_bnd if vaddr_bnd is not None else vaddr_data + else: + base = vaddr_text addr = labels[content] + base return { 'type': 'absolute', @@ -145,7 +161,7 @@ def encode_mov_mem_reg_absolute(reg_info, mem_info, current_pos, vaddr_text): return code -def encode_mov_reg_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos): +def encode_mov_reg_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd=None): """ MOV reg, mem - загрузить из памяти в регистр Формат: загрузить <регистр>, [<адрес>] @@ -154,7 +170,7 @@ def encode_mov_reg_mem(operands, labels, label_sections, symbols, vaddr_text, va mem_operand = operands[1] # Пытаемся разобрать операнд памяти - mem_info = parse_memory_operand(mem_operand, labels, label_sections, vaddr_text, vaddr_data) + mem_info = parse_memory_operand(mem_operand, labels, label_sections, vaddr_text, vaddr_data, vaddr_bnd) if mem_info and mem_info['type'] == 'absolute': return encode_mov_reg_mem_absolute(reg_info, mem_info, current_pos, vaddr_text) @@ -163,7 +179,7 @@ def encode_mov_reg_mem(operands, labels, label_sections, symbols, vaddr_text, va return b'\x90' * 3 -def encode_mov_mem_reg(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos): +def encode_mov_mem_reg(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd=None): """ MOV mem, reg - сохранить из регистра в память Формат: сохранить [<адрес>], <регистр> @@ -172,7 +188,7 @@ def encode_mov_mem_reg(operands, labels, label_sections, symbols, vaddr_text, va reg_info = get_reg_info(operands[1]) # Пытаемся разобрать операнд памяти - mem_info = parse_memory_operand(mem_operand, labels, label_sections, vaddr_text, vaddr_data) + mem_info = parse_memory_operand(mem_operand, labels, label_sections, vaddr_text, vaddr_data, vaddr_bnd) if mem_info and mem_info['type'] == 'absolute': return encode_mov_mem_reg_absolute(reg_info, mem_info, current_pos, vaddr_text) @@ -181,7 +197,7 @@ def encode_mov_mem_reg(operands, labels, label_sections, symbols, vaddr_text, va return b'\x90' * 3 -def encode_lea_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos): +def encode_lea_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd=None): """ LEA reg, mem - загрузить эффективный адрес Формат: загрузить_адрес <регистр>, [<адрес>] @@ -190,7 +206,7 @@ def encode_lea_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_ mem_operand = operands[1] # Пытаемся разобрать операнд памяти - mem_info = parse_memory_operand(mem_operand, labels, label_sections, vaddr_text, vaddr_data) + mem_info = parse_memory_operand(mem_operand, labels, label_sections, vaddr_text, vaddr_data, vaddr_bnd) if mem_info and mem_info['type'] == 'absolute': target_addr = mem_info['address'] rip_at_end = vaddr_text + current_pos + 7 @@ -217,7 +233,7 @@ def encode_lea_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_ # ========== 1. Инструкции перемещения данных (MOV, LEA, MOVZX, MOVSX) ========== -def encode_mov_reg_imm(operands, labels, label_sections, symbols, vaddr_text, vaddr_data): +def encode_mov_reg_imm(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd=None): """ MOV reg, imm - переместить непосредственное значение в регистр Формат: переместить_имм <регистр>, <значение|метка|константа> @@ -226,7 +242,7 @@ def encode_mov_reg_imm(operands, labels, label_sections, symbols, vaddr_text, va reg_info = get_reg_info(operands[0]) reg = reg_info["index"] size = reg_info["size"] - imm = parse_operand(operands[1], labels, label_sections, symbols, vaddr_text, vaddr_data) + imm = parse_operand(operands[1], labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd) if size == 64: if 0 <= reg <= 7: @@ -335,7 +351,7 @@ def encode_mov_reg8_imm8(operands): return code -def encode_movzx(operands, labels, label_sections, symbols, vaddr_text, vaddr_data): +def encode_movzx(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd=None): """ MOVZX reg, mem8 - переместить с расширением нулями Формат: переместить_с_нулями <регистр>, <адрес_байта> @@ -344,7 +360,7 @@ def encode_movzx(operands, labels, label_sections, symbols, vaddr_text, vaddr_da instr = INSTRUCTIONS["переместить_с_нулями"] reg_info = get_reg_info(operands[0]) reg = reg_info["index"] - addr = parse_operand(operands[1], labels, label_sections, symbols, vaddr_text, vaddr_data) + addr = parse_operand(operands[1], labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd) rex = 0x48 if reg_info["size"] == 64 else 0x40 if reg >= 8: @@ -357,7 +373,7 @@ def encode_movzx(operands, labels, label_sections, symbols, vaddr_text, vaddr_da return code -def encode_movsx(operands, labels, label_sections, symbols, vaddr_text, vaddr_data): +def encode_movsx(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd=None): """ MOVSX reg, mem8 - переместить с расширением знака Формат: переместить_со_знаком <регистр>, <адрес_байта> @@ -366,7 +382,7 @@ def encode_movsx(operands, labels, label_sections, symbols, vaddr_text, vaddr_da instr = INSTRUCTIONS["переместить_со_знаком"] reg_info = get_reg_info(operands[0]) reg = reg_info["index"] - addr = parse_operand(operands[1], labels, label_sections, symbols, vaddr_text, vaddr_data) + addr = parse_operand(operands[1], labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd) rex = 0x48 if reg_info["size"] == 64 else 0x40 if reg >= 8: @@ -381,7 +397,7 @@ def encode_movsx(operands, labels, label_sections, symbols, vaddr_text, vaddr_da # ========== 2. Инструкции сравнения (CMP, TEST) ========== -def encode_cmp_reg_imm(operands, labels, label_sections, symbols, vaddr_text, vaddr_data): +def encode_cmp_reg_imm(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd=None): """ CMP reg, imm - сравнить регистр с непосредственным значением Формат: сравнить_с <регистр>, <значение|метка|константа> @@ -390,7 +406,7 @@ def encode_cmp_reg_imm(operands, labels, label_sections, symbols, vaddr_text, va reg_info = get_reg_info(operands[0]) reg = reg_info["index"] size = reg_info["size"] - imm = parse_operand(operands[1], labels, label_sections, symbols, vaddr_text, vaddr_data) + imm = parse_operand(operands[1], labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd) if size == 64: rex = 0x48 @@ -493,7 +509,7 @@ def encode_cmp_reg_reg(mnemonic, operands): # ========== 3. Арифметические инструкции (ADD, SUB, MUL, DIV) ========== -def encode_add_sub_reg_imm(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data): +def encode_add_sub_reg_imm(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd=None): """ ADD/SUB reg, imm - прибавить/вычесть непосредственное значение Формат: прибавить_непосредственно / вычесть_непосредственно <регистр>, <значение> @@ -502,7 +518,7 @@ def encode_add_sub_reg_imm(mnemonic, operands, labels, label_sections, symbols, reg_info = get_reg_info(operands[0]) reg = reg_info["index"] size = reg_info["size"] - imm = parse_operand(operands[1], labels, label_sections, symbols, vaddr_text, vaddr_data) + imm = parse_operand(operands[1], labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd) op_map = { "прибавить_непосредственно": 0x81, @@ -671,26 +687,26 @@ def encode_not_neg(mnemonic, operands): # ========== 5. Инструкции переходов и вызовов ========== -def encode_jmp_rel32(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos): +def encode_jmp_rel32(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd=None): """ JMP rel32 - безусловный переход с 32-битным смещением """ code = bytearray() instr = INSTRUCTIONS["переход"] code.extend(instr["opcode"]) - target = parse_operand(operands[0], labels, label_sections, symbols, vaddr_text, vaddr_data) + target = parse_operand(operands[0], labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd) offset = target - (vaddr_text + current_pos + 5) code.extend(struct.pack('