добавление .bss

This commit is contained in:
mzhoot 2026-05-17 11:22:39 +03:00
parent ead2caead8
commit 5f7d212dbf
11 changed files with 328 additions and 72 deletions

View file

@ -9,11 +9,11 @@ import sys
import struct import struct
import os import os
sys.path.insert(0, '.') 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): def read_csv(input_file, vaddr_text, vaddr_data, text_size, data_size):
"""Загружает байты из CSV используя точные виртуальные адреса""" """Загружает байты из CSV используя точные виртуальные адреса"""
text_bytes = bytearray(text_size) # точный размер из pass1 text_bytes = bytearray(text_size)
data_bytes = bytearray(data_size) data_bytes = bytearray(data_size)
with open(input_file, 'r', encoding='utf-8') as f: with open(input_file, 'r', encoding='utf-8') as f:
@ -72,8 +72,12 @@ def read_pass1(input_file):
def create_elf(text_bytes, data_bytes, pass1_data, labels, output_file): def create_elf(text_bytes, data_bytes, pass1_data, labels, output_file):
vaddr_text = pass1_data.get("vaddr_text", 0x401000) vaddr_text = pass1_data.get("vaddr_text", 0x401000)
text_size = pass1_data.get("text_size", len(text_bytes)) 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_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_text = pass1_data.get("offset_text", 0x1000)
offset_data = align_up(offset_text + len(text_bytes), PAGE_SIZE) 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) entry_addr = vaddr_text + labels.get(entry_point_name, 0)
comment_content = "Сборщик КВС".encode('utf-8') + b'\x00' 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 elf_header_size = 64
ph_size = 56 ph_size = 56
ph_num = 3 ph_num = 3
shdr_size = 64 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 file_size = shdr_offset + shdr_num * shdr_size
elf_data = bytearray(file_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 p_filesz, p_memsz, PAGE_SIZE
) )
# Program headers
ph0 = phdr(1, 4, 0, 0x400000, elf_header_size + ph_num * ph_size, PAGE_SIZE) 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)) 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 phdrs = ph0 + ph1 + ph2
elf_data[elf_header_size : elf_header_size + len(phdrs)] = phdrs 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_text : offset_text + len(text_bytes)] = text_bytes
elf_data[offset_data : offset_data + len(data_bytes)] = data_bytes elf_data[offset_data : offset_data + len(data_bytes)] = data_bytes
elf_data[offset_comment : offset_comment + len(comment_content)] = comment_content 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 0, 0, addralign, 0
) )
sh0 = shdr(0, 0, 0, 0, 0, 0) # Индексы имён в shstrtab зависят от наличия .bss
sh1 = shdr(1, 1, 6, vaddr_text, offset_text, len(text_bytes), 16) if bnd_size > 0:
sh2 = shdr(7, 1, 3, vaddr_data, offset_data, len(data_bytes), 8) name_text = 1 # ".text"
sh3 = shdr(13, 1, 0, 0, offset_comment, len(comment_content), 1) name_data = 7 # ".data"
sh4 = shdr(22, 3, 0, 0, shstrtab_offset, len(shstrtab_content), 1) 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 elf_data[shdr_offset : shdr_offset + len(shdrs)] = shdrs
with open(output_file, "wb") as f: 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"Сборщик: ELF-файл создан: {output_file}")
print(f" .text: {len(text_bytes)} байт, адрес: 0x{vaddr_text:x}") print(f" .text: {len(text_bytes)} байт, адрес: 0x{vaddr_text:x}")
print(f" .data: {len(data_bytes)} байт, адрес: 0x{vaddr_data: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 __name__ == "__main__":
if len(sys.argv) != 4: if len(sys.argv) != 4:
@ -158,7 +199,7 @@ if __name__ == "__main__":
text_size = pass1_data["text_size"] text_size = pass1_data["text_size"]
data_size = pass1_data["data_size"] data_size = pass1_data["data_size"]
# Вычисляем vaddr_data как в kvs_8 # Вычисляем vaddr_data
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE) 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) text_bytes, data_bytes = read_csv(sys.argv[1], vaddr_text, vaddr_data, text_size, data_size)

View file

@ -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 константы # ELF константы
PAGE_SIZE = 0x1000 # Размер страницы памяти (4096 байт) PAGE_SIZE = 0x1000 # Размер страницы памяти (4096 байт)
elf_base_vaddr = 0x400000 # Базовый виртуальный адрес ELF elf_base_vaddr = 0x400000 # Базовый виртуальный адрес ELF

View file

@ -104,19 +104,45 @@ class Parser:
return True return True
def parse_directive(self, word): def parse_directive(self, word):
"""
Разбор директив ассемблера.
Вызывает ошибку при некорректном синтаксисе или контексте.
"""
# === Секции ===
if word == '.текст': if word == '.текст':
self.current_section = ".text" self.current_section = ".text"
self.parsed_lines.append(f"DIRECTIVE:{word}") self.parsed_lines.append(f"DIRECTIVE:{word}")
elif word == '.данные': elif word == '.данные':
self.current_section = ".data" self.current_section = ".data"
self.parsed_lines.append(f"DIRECTIVE:{word}") self.parsed_lines.append(f"DIRECTIVE:{word}")
elif word == '.бнд':
self.current_section = ".бнд"
self.parsed_lines.append(f"DIRECTIVE:{word}")
# === Глобальные метки ===
elif word == '.глобал': elif word == '.глобал':
label = self.expect('WORD')[1] label = self.expect('WORD')[1]
self.parsed_lines.append(f"DIRECTIVE:{word}:{label}") self.parsed_lines.append(f"DIRECTIVE:{word}:{label}")
# === Строковые директивы (запрещены в .бнд) ===
elif word in ('.строка_нуль', '.строка'): elif word in ('.строка_нуль', '.строка'):
if self.current_section == ".бнд":
raise ValueError(
"Ошибка: секция .бнд не поддерживает инициализированные данные "
"(используйте .резб, .резс, .рездс, .резкс)"
)
string_tok = self.expect('STRING') string_tok = self.expect('STRING')
self.parsed_lines.append(f"DIRECTIVE:{word}:{self.current_section}:{string_tok[1]}") self.parsed_lines.append(f"DIRECTIVE:{word}:{self.current_section}:{string_tok[1]}")
# === Константы (запрещены в .бнд) ===
elif word == '.константа': elif word == '.константа':
if self.current_section == ".бнд":
raise ValueError(
"Ошибка: секция .бнд не поддерживает инициализированные данные "
"(используйте .резб, .резс, .рездс, .резкс)"
)
name = self.expect('WORD')[1] name = self.expect('WORD')[1]
# Пропускаем '=', если есть # Пропускаем '=', если есть
eq_tok = self.peek() eq_tok = self.peek()
@ -125,7 +151,14 @@ class Parser:
# Значение может быть WORD или NUMBER # Значение может быть WORD или NUMBER
value_tok = self.expect_one_of(['WORD', 'NUMBER']) value_tok = self.expect_one_of(['WORD', 'NUMBER'])
self.parsed_lines.append(f"DIRECTIVE:{word}:{name}:{value_tok[1]}") self.parsed_lines.append(f"DIRECTIVE:{word}:{name}:{value_tok[1]}")
# === Байты (запрещены в .бнд) ===
elif word == '.байт': elif word == '.байт':
if self.current_section == ".бнд":
raise ValueError(
"Ошибка: секция .бнд не поддерживает инициализированные данные "
"(используйте .резб, .резс, .рездс, .резкс)"
)
bytes_list = [] bytes_list = []
while True: while True:
tok = self.peek() tok = self.peek()
@ -139,6 +172,23 @@ class Parser:
val_tok = self.expect_one_of(['WORD', 'NUMBER', 'STRING']) val_tok = self.expect_one_of(['WORD', 'NUMBER', 'STRING'])
bytes_list.append(val_tok[1]) bytes_list.append(val_tok[1])
self.parsed_lines.append(f"DIRECTIVE:{word}:{self.current_section}:" + ",".join(bytes_list)) 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: else:
raise ValueError(f"Неизвестная директива: {word}") raise ValueError(f"Неизвестная директива: {word}")

View file

@ -151,7 +151,7 @@ class Pass1:
self.labels = {} self.labels = {}
self.label_sections = {} self.label_sections = {}
self.symbols = {} self.symbols = {}
self.position = {".text": 0, ".data": 0} self.position = {".text": 0, ".data": 0, ".бнд": 0}
self.current_section = ".text" self.current_section = ".text"
self.entry_point = "_start" self.entry_point = "_start"
@ -165,6 +165,8 @@ class Pass1:
self.current_section = ".text" self.current_section = ".text"
elif directive == '.данные': elif directive == '.данные':
self.current_section = ".data" self.current_section = ".data"
elif directive == '.бнд':
self.current_section = ".бнд"
elif directive == '.глобал': elif directive == '.глобал':
self.entry_point = parts[2] self.entry_point = parts[2]
elif directive in ('.строка_нуль', '.строка'): elif directive in ('.строка_нуль', '.строка'):
@ -188,6 +190,23 @@ class Pass1:
if len(parts) > 3 and parts[3]: if len(parts) > 3 and parts[3]:
num_bytes = len(parts[3].split(',')) num_bytes = len(parts[3].split(','))
self.position[sec] += num_bytes 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": elif line_type == "LABEL":
label_name = parts[1] label_name = parts[1]
@ -292,6 +311,7 @@ class Pass1:
def calculate_layout(self): def calculate_layout(self):
text_size = self.position[".text"] text_size = self.position[".text"]
data_size = self.position[".data"] data_size = self.position[".data"]
bnd_size = self.position[".бнд"]
elf_header_size = 64 elf_header_size = 64
ph_size = 56 ph_size = 56
@ -302,21 +322,29 @@ class Pass1:
offset_data = align_up(offset_text + text_size, PAGE_SIZE) offset_data = align_up(offset_text + text_size, PAGE_SIZE)
vaddr_text = text_vaddr_base vaddr_text = text_vaddr_base
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE) vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE)
vaddr_bnd = align_up(vaddr_data + data_size, PAGE_SIZE)
comment_size = len("Сборщик КВС".encode('utf-8')) + 1 comment_size = len("Сборщик КВС".encode('utf-8')) + 1
offset_comment = align_up(offset_data + data_size, 1) offset_comment = align_up(offset_data + data_size, 1)
shstrtab_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) shstrtab_offset = align_up(offset_comment + comment_size, 8)
shdr_offset = align_up(shstrtab_offset + shstrtab_size, 16) shdr_offset = align_up(shstrtab_offset + shstrtab_size, 16)
return { return {
"text_size": text_size, "text_size": text_size,
"data_size": data_size, "data_size": data_size,
"bnd_size": bnd_size,
"offset_text": offset_text, "offset_text": offset_text,
"offset_data": offset_data, "offset_data": offset_data,
"vaddr_text": vaddr_text, "vaddr_text": vaddr_text,
"vaddr_data": vaddr_data, "vaddr_data": vaddr_data,
"vaddr_bnd": vaddr_bnd,
"offset_comment": offset_comment, "offset_comment": offset_comment,
"comment_size": comment_size, "comment_size": comment_size,
"shstrtab_offset": shstrtab_offset, "shstrtab_offset": shstrtab_offset,
@ -347,4 +375,4 @@ if __name__ == "__main__":
layout = pass1.calculate_layout() layout = pass1.calculate_layout()
write_pass1(layout, pass1.labels, pass1.label_sections, pass1.symbols, sys.argv[2]) write_pass1(layout, pass1.labels, pass1.label_sections, pass1.symbols, sys.argv[2])
print(f"Проход 1: text_size={layout['text_size']}, data_size={layout['data_size']}") print(f"Проход 1: text_size={layout['text_size']}, data_size={layout['data_size']}, bnd_size={layout['bnd_size']}")

View file

@ -91,8 +91,11 @@ class Pass2:
self.symbols = symbols self.symbols = symbols
self.vaddr_text = pass1_data["vaddr_text"] self.vaddr_text = pass1_data["vaddr_text"]
text_size = pass1_data["text_size"] 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.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.current_section = ".text"
self.csv_lines = [] self.csv_lines = []
self.data_bytes = {".text": bytearray(), ".data": bytearray()} self.data_bytes = {".text": bytearray(), ".data": bytearray()}
@ -119,7 +122,14 @@ class Pass2:
op_str = operands[1] op_str = operands[1]
if op_str in self.labels: if op_str in self.labels:
sec = self.label_sections[op_str] 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) return hex(addr)
elif op_str in self.symbols: elif op_str in self.symbols:
return hex(self.symbols[op_str]) return hex(self.symbols[op_str])
@ -139,6 +149,8 @@ class Pass2:
self.current_section = ".text" self.current_section = ".text"
elif directive == '.данные': elif directive == '.данные':
self.current_section = ".data" self.current_section = ".data"
elif directive == '.бнд':
self.current_section = ".бнд"
elif directive in ('.строка_нуль', '.строка'): elif directive in ('.строка_нуль', '.строка'):
s = parts[3] if len(parts) > 3 else "" s = parts[3] if len(parts) > 3 else ""
real_s = unescape_string(s) real_s = unescape_string(s)
@ -180,6 +192,23 @@ class Pass2:
self.data_bytes[".data"].append(val & 0xFF) self.data_bytes[".data"].append(val & 0xFF)
self.position[".data"] += len(byte_values) 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": elif line_type == "LABEL":
label_name = parts[1] label_name = parts[1]
@ -249,4 +278,6 @@ if __name__ == "__main__":
print(f"Проход 2: {len(csv_lines)} строк CSV записано в {sys.argv[3]}") print(f"Проход 2: {len(csv_lines)} строк CSV записано в {sys.argv[3]}")
print(f" .text: {pass2.position['.text']} байт, виртуальный адрес: 0x{pass2.vaddr_text:x}") print(f" .text: {pass2.position['.text']} байт, виртуальный адрес: 0x{pass2.vaddr_text:x}")
print(f" .data: {pass2.position['.data']} байт, виртуальный адрес: 0x{pass2.vaddr_data:x}") 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}")

View file

@ -11,13 +11,13 @@ import sys
from kvs_data import INSTRUCTIONS, REGISTERS, get_reg_info 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) - десятичные числа (123)
- шестнадцатеричные (0x7B) - шестнадцатеричные (0x7B)
- метки (имя_метки) - метки (имя_метки) — из .text, .data или .бнд
- константы (из .константа) - константы (из .константа)
""" """
if operand.isdigit(): if operand.isdigit():
@ -29,20 +29,29 @@ def parse_operand(operand, labels, label_sections, symbols, vaddr_text, vaddr_da
pass pass
if operand in labels: if operand in labels:
section = label_sections.get(operand, '.text') section = label_sections.get(operand, '.text')
base = vaddr_text if section == '.text' else vaddr_data if section == '.text':
return labels[operand] + base 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: if operand in symbols:
return symbols[operand] return symbols[operand]
raise ValueError("Неизвестный операнд: " + 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. Возвращает словарь с информацией или None.
Поддерживает: Поддерживает:
- [число] — абсолютный адрес - [число] — абсолютный адрес
- [метка] — адрес метки (из .data или .text) - [метка] — адрес метки (из .data, .text или .бнд)
- [регистр] — косвенная адресация (TODO) - [регистр] — косвенная адресация (TODO)
""" """
if not operand_str.startswith('[') or not operand_str.endswith(']'): 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: if content in labels:
section = label_sections.get(content, '.data') 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 addr = labels[content] + base
return { return {
'type': 'absolute', 'type': 'absolute',
@ -145,7 +161,7 @@ def encode_mov_mem_reg_absolute(reg_info, mem_info, current_pos, vaddr_text):
return code 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 - загрузить из памяти в регистр 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_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': if mem_info and mem_info['type'] == 'absolute':
return encode_mov_reg_mem_absolute(reg_info, mem_info, current_pos, vaddr_text) 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 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 - сохранить из регистра в память 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]) 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': if mem_info and mem_info['type'] == 'absolute':
return encode_mov_mem_reg_absolute(reg_info, mem_info, current_pos, vaddr_text) 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 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 - загрузить эффективный адрес LEA reg, mem - загрузить эффективный адрес
Формат: загрузить_адрес <регистр>, [<адрес>] Формат: загрузить_адрес <регистр>, [<адрес>]
@ -190,7 +206,7 @@ def encode_lea_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_
mem_operand = operands[1] 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': if mem_info and mem_info['type'] == 'absolute':
target_addr = mem_info['address'] target_addr = mem_info['address']
rip_at_end = vaddr_text + current_pos + 7 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) ========== # ========== 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 - переместить непосредственное значение в регистр 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_info = get_reg_info(operands[0])
reg = reg_info["index"] reg = reg_info["index"]
size = reg_info["size"] 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 size == 64:
if 0 <= reg <= 7: if 0 <= reg <= 7:
@ -335,7 +351,7 @@ def encode_mov_reg8_imm8(operands):
return code 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 - переместить с расширением нулями MOVZX reg, mem8 - переместить с расширением нулями
Формат: переместить_с_нулями <регистр>, <адрес_байта> Формат: переместить_с_нулями <регистр>, <адрес_байта>
@ -344,7 +360,7 @@ def encode_movzx(operands, labels, label_sections, symbols, vaddr_text, vaddr_da
instr = INSTRUCTIONS["переместить_с_нулями"] instr = INSTRUCTIONS["переместить_с_нулями"]
reg_info = get_reg_info(operands[0]) reg_info = get_reg_info(operands[0])
reg = reg_info["index"] 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 rex = 0x48 if reg_info["size"] == 64 else 0x40
if reg >= 8: if reg >= 8:
@ -357,7 +373,7 @@ def encode_movzx(operands, labels, label_sections, symbols, vaddr_text, vaddr_da
return code 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 - переместить с расширением знака MOVSX reg, mem8 - переместить с расширением знака
Формат: переместить_со_знаком <регистр>, <адрес_байта> Формат: переместить_со_знаком <регистр>, <адрес_байта>
@ -366,7 +382,7 @@ def encode_movsx(operands, labels, label_sections, symbols, vaddr_text, vaddr_da
instr = INSTRUCTIONS["переместить_со_знаком"] instr = INSTRUCTIONS["переместить_со_знаком"]
reg_info = get_reg_info(operands[0]) reg_info = get_reg_info(operands[0])
reg = reg_info["index"] 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 rex = 0x48 if reg_info["size"] == 64 else 0x40
if reg >= 8: if reg >= 8:
@ -381,7 +397,7 @@ def encode_movsx(operands, labels, label_sections, symbols, vaddr_text, vaddr_da
# ========== 2. Инструкции сравнения (CMP, TEST) ========== # ========== 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 - сравнить регистр с непосредственным значением 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_info = get_reg_info(operands[0])
reg = reg_info["index"] reg = reg_info["index"]
size = reg_info["size"] 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 size == 64:
rex = 0x48 rex = 0x48
@ -493,7 +509,7 @@ def encode_cmp_reg_reg(mnemonic, operands):
# ========== 3. Арифметические инструкции (ADD, SUB, MUL, DIV) ========== # ========== 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 - прибавить/вычесть непосредственное значение 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_info = get_reg_info(operands[0])
reg = reg_info["index"] reg = reg_info["index"]
size = reg_info["size"] 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 = { op_map = {
"прибавить_непосредственно": 0x81, "прибавить_непосредственно": 0x81,
@ -671,26 +687,26 @@ def encode_not_neg(mnemonic, operands):
# ========== 5. Инструкции переходов и вызовов ========== # ========== 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-битным смещением JMP rel32 - безусловный переход с 32-битным смещением
""" """
code = bytearray() code = bytearray()
instr = INSTRUCTIONS["переход"] instr = INSTRUCTIONS["переход"]
code.extend(instr["opcode"]) 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) offset = target - (vaddr_text + current_pos + 5)
code.extend(struct.pack('<i', offset)) code.extend(struct.pack('<i', offset))
return code return code
def encode_jmp_short(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos): def encode_jmp_short(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd=None):
""" """
JMP SHORT - короткий безусловный переход с 8-битным смещением JMP SHORT - короткий безусловный переход с 8-битным смещением
""" """
code = bytearray() code = bytearray()
code.append(0xEB) code.append(0xEB)
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 + 2) offset = target - (vaddr_text + current_pos + 2)
if not (-128 <= offset <= 127): if not (-128 <= offset <= 127):
raise ValueError(f"Смещение короткого перехода {offset} вне диапазона [-128..127]") raise ValueError(f"Смещение короткого перехода {offset} вне диапазона [-128..127]")
@ -698,27 +714,27 @@ def encode_jmp_short(operands, labels, label_sections, symbols, vaddr_text, vadd
return code return code
def encode_jcc_rel32(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos): def encode_jcc_rel32(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd=None):
""" """
Jcc rel32 - условный переход с 32-битным смещением Jcc rel32 - условный переход с 32-битным смещением
""" """
code = bytearray() code = bytearray()
instr = INSTRUCTIONS[mnemonic] instr = INSTRUCTIONS[mnemonic]
code.extend(instr["opcode"]) 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 + 6) offset = target - (vaddr_text + current_pos + 6)
code.extend(struct.pack('<i', offset)) code.extend(struct.pack('<i', offset))
return code return code
def encode_jcc_short(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos): def encode_jcc_short(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd=None):
""" """
Jcc SHORT - короткий условный переход с 8-битным смещением Jcc SHORT - короткий условный переход с 8-битным смещением
""" """
code = bytearray() code = bytearray()
instr = INSTRUCTIONS[mnemonic] instr = INSTRUCTIONS[mnemonic]
code.extend(instr["opcode"]) 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 + 2) offset = target - (vaddr_text + current_pos + 2)
if not (-128 <= offset <= 127): if not (-128 <= offset <= 127):
raise ValueError(f"Смещение короткого перехода {offset} вне диапазона [-128..127]") raise ValueError(f"Смещение короткого перехода {offset} вне диапазона [-128..127]")
@ -726,14 +742,14 @@ def encode_jcc_short(mnemonic, operands, labels, label_sections, symbols, vaddr_
return code return code
def encode_call(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos): def encode_call(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd=None):
""" """
CALL rel32 - вызов процедуры CALL rel32 - вызов процедуры
""" """
code = bytearray() code = bytearray()
instr = INSTRUCTIONS["вызвать"] instr = INSTRUCTIONS["вызвать"]
code.extend(instr["opcode"]) 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) offset = target - (vaddr_text + current_pos + 5)
code.extend(struct.pack('<i', offset)) code.extend(struct.pack('<i', offset))
return code return code
@ -744,14 +760,14 @@ def encode_ret():
return INSTRUCTIONS["вернуться"]["opcode"] return INSTRUCTIONS["вернуться"]["opcode"]
def encode_loop(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos): def encode_loop(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd=None):
""" """
LOOP rel8 - инструкция цикла LOOP rel8 - инструкция цикла
""" """
code = bytearray() code = bytearray()
instr = INSTRUCTIONS["цикл"] instr = INSTRUCTIONS["цикл"]
code.extend(instr["opcode"]) 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 + 2) offset = target - (vaddr_text + current_pos + 2)
if not (-128 <= offset <= 127): if not (-128 <= offset <= 127):
raise ValueError(f"Смещение LOOP {offset} вне диапазона [-128..127]") raise ValueError(f"Смещение LOOP {offset} вне диапазона [-128..127]")
@ -1002,7 +1018,7 @@ def encode_xchg(operands):
# ========== ГЛАВНЫЙ ДИСПЕТЧЕР ========== # ========== ГЛАВНЫЙ ДИСПЕТЧЕР ==========
def encode_instruction(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos): def encode_instruction(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd=None):
""" """
Главный диспетчер генерации машинного кода. Главный диспетчер генерации машинного кода.
По мнемонике выбирает соответствующую функцию генерации. По мнемонике выбирает соответствующую функцию генерации.
@ -1031,33 +1047,33 @@ def encode_instruction(mnemonic, operands, labels, label_sections, symbols, vadd
# ----- MOV с памятью ----- # ----- MOV с памятью -----
elif mnemonic == "загрузить": elif mnemonic == "загрузить":
return encode_mov_reg_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos) return encode_mov_reg_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd)
elif mnemonic == "сохранить": elif mnemonic == "сохранить":
return encode_mov_mem_reg(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos) return encode_mov_mem_reg(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd)
elif mnemonic == "загрузить_адрес": elif mnemonic == "загрузить_адрес":
return encode_lea_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos) return encode_lea_mem(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd)
# ----- MOV (разные формы) ----- # ----- MOV (разные формы) -----
elif mnemonic == "переместить_имм": elif mnemonic == "переместить_имм":
return encode_mov_reg_imm(operands, labels, label_sections, symbols, vaddr_text, vaddr_data) return encode_mov_reg_imm(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd)
elif mnemonic == "переместить": elif mnemonic == "переместить":
return encode_mov_reg_reg(operands) return encode_mov_reg_reg(operands)
elif mnemonic == "загрузить_байт": elif mnemonic == "загрузить_байт":
return encode_mov_reg8_imm8(operands) return encode_mov_reg8_imm8(operands)
elif mnemonic == "переместить_с_нулями": elif mnemonic == "переместить_с_нулями":
return encode_movzx(operands, labels, label_sections, symbols, vaddr_text, vaddr_data) return encode_movzx(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd)
elif mnemonic == "переместить_со_знаком": elif mnemonic == "переместить_со_знаком":
return encode_movsx(operands, labels, label_sections, symbols, vaddr_text, vaddr_data) return encode_movsx(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd)
# ----- CMP (сравнение) ----- # ----- CMP (сравнение) -----
elif mnemonic == "сравнить_с": elif mnemonic == "сравнить_с":
return encode_cmp_reg_imm(operands, labels, label_sections, symbols, vaddr_text, vaddr_data) return encode_cmp_reg_imm(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd)
elif mnemonic in ("сравнить", "сравнить_байт", "проверить"): elif mnemonic in ("сравнить", "сравнить_байт", "проверить"):
return encode_cmp_reg_reg(mnemonic, operands) return encode_cmp_reg_reg(mnemonic, operands)
# ----- ADD/SUB (арифметика) ----- # ----- ADD/SUB (арифметика) -----
elif mnemonic in ("прибавить_непосредственно", "вычесть_непосредственно"): elif mnemonic in ("прибавить_непосредственно", "вычесть_непосредственно"):
return encode_add_sub_reg_imm(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data) return encode_add_sub_reg_imm(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, vaddr_bnd)
elif mnemonic in ("прибавить", "вычесть", "прибавить_байт", "вычесть_байт"): elif mnemonic in ("прибавить", "вычесть", "прибавить_байт", "вычесть_байт"):
return encode_add_sub_reg_reg(mnemonic, operands) return encode_add_sub_reg_reg(mnemonic, operands)
@ -1079,25 +1095,25 @@ def encode_instruction(mnemonic, operands, labels, label_sections, symbols, vadd
# ----- Переходы ----- # ----- Переходы -----
elif mnemonic == "переход": elif mnemonic == "переход":
return encode_jmp_rel32(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos) return encode_jmp_rel32(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd)
elif mnemonic == "короткий_переход": elif mnemonic == "короткий_переход":
return encode_jmp_short(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos) return encode_jmp_short(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd)
elif mnemonic in ("переход_если_равно", "переход_если_неравно", "переход_если_меньше", elif mnemonic in ("переход_если_равно", "переход_если_неравно", "переход_если_меньше",
"переход_если_больше", "переход_если_меньше_или_равно", "переход_если_больше_или_равно", "переход_если_больше", "переход_если_меньше_или_равно", "переход_если_больше_или_равно",
"переход_если_перенос", "переход_если_нет_переноса", "переход_если_ноль", "переход_если_не_ноль"): "переход_если_перенос", "переход_если_нет_переноса", "переход_если_ноль", "переход_если_не_ноль"):
return encode_jcc_rel32(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos) return encode_jcc_rel32(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd)
elif mnemonic in ("короткий_переход_если_равно", "короткий_переход_если_неравно", elif mnemonic in ("короткий_переход_если_равно", "короткий_переход_если_неравно",
"короткий_переход_если_меньше", "короткий_переход_если_больше", "короткий_переход_если_меньше", "короткий_переход_если_больше",
"короткий_переход_если_меньше_или_равно", "короткий_переход_если_больше_или_равно", "короткий_переход_если_меньше_или_равно", "короткий_переход_если_больше_или_равно",
"короткий_переход_если_перенос", "короткий_переход_если_нет_переноса", "короткий_переход_если_перенос", "короткий_переход_если_нет_переноса",
"короткий_переход_если_ноль", "короткий_переход_если_не_ноль"): "короткий_переход_если_ноль", "короткий_переход_если_не_ноль"):
return encode_jcc_short(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos) return encode_jcc_short(mnemonic, operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd)
# ----- CALL/RET/LOOP ----- # ----- CALL/RET/LOOP -----
elif mnemonic == "вызвать": elif mnemonic == "вызвать":
return encode_call(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos) return encode_call(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd)
elif mnemonic == "цикл": elif mnemonic == "цикл":
return encode_loop(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos) return encode_loop(operands, labels, label_sections, symbols, vaddr_text, vaddr_data, current_pos, vaddr_bnd)
# ----- PUSH/POP ----- # ----- PUSH/POP -----
elif mnemonic == "втолкнуть": elif mnemonic == "втолкнуть":

View file

@ -243,4 +243,9 @@ Pass2 (шаг 5):
**Статус: v2.0 — абсолютная адресация реализована полностью.** **Статус: v2.0 — абсолютная адресация реализована полностью.**
**Следующая цель: v3.0 — косвенная адресация `[reg]`.** **Следующая цель: v3.0 — косвенная адресация `[reg]`.**
``` ```
избавиться от ре и перенести таблицу фиксированных размеров
вынести работу с памятью из второго прохода в отдельный энкодер

View file

@ -0,0 +1,9 @@
.текст
.глобал _start
_start:
переместить_имм раикс, 60
переместить_имм рдиай, 0
вызов_системы
.бнд
буфер: .резб 1048576 ; 1 МБ = 1024 * 1024

View file

@ -25,4 +25,4 @@ _start:
.данные .данные
msg: .строка "Тест пройден!\n" ; не менять их местами, чтоб не затереть текст msg: .строка "Тест пройден!\n" ; не менять их местами, чтоб не затереть текст
переменная: .байт 0 ; тут либо резервировать пустые, либо .bss изобретать переменная: .байт 0 ; тут либо резервировать пустые, либо .bss изобретать (или кучу?)

View file

@ -0,0 +1,30 @@
.текст
.глобал _start
_start:
; 25 - длина сообщения из метки msg
; Запись значения 25 в переменную по метке
переместить_имм рдикс, 25
сохранить [переменная], рдикс
; перепишем для теста
переместить_имм рдикс, 0
; Системный вызов write(1, msg, len)
переместить_имм раикс, 1
переместить_имм рдиай, 1
переместить_имм рсиай, msg
загрузить рдикс, [переменная]
вызов_системы
; Системный вызов exit()
переместить_имм раикс, 60 ; номер syscall exit = 60
переместить_имм рдиай, 44 ; код возврата (старый метод)
вызов_системы
.данные
msg: .строка "Тест пройден!\n" ; строка остаётся в .данные
.бнд
переменная: .резкс 1 ; 8 байт под qword (как и было .байт 0)

View file

@ -0,0 +1,36 @@
.текст
.глобал _start
_start:
; 25 - длина сообщения из метки msg
; Запись значения 25 в переменную в .бнд
переместить_имм рдикс, 25
сохранить [переменная], рдикс
; Загружаем адрес строки и сохраняем в буфер в .бнд
загрузить_адрес раикс, [msg]
сохранить [буфер_строки], раикс
; перепишем для теста
переместить_имм рдикс, 0
; Системный вызов write(1, msg, len)
переместить_имм раикс, 1
переместить_имм рдиай, 1
загрузить рсиай, [буфер_строки]
загрузить рдикс, [переменная]
вызов_системы
; Системный вызов exit()
переместить_имм раикс, 60
переместить_имм рдиай, 44
вызов_системы
.данные
msg: .строка "Тест пройден!\n"
.бнд
переменная: .резкс 1 ; 8 байт под длину
буфер_строки: .резкс 1 ; 8 байт под указатель на строку