добавление .bss
This commit is contained in:
parent
ead2caead8
commit
5f7d212dbf
|
|
@ -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)
|
||||
|
|
|
|||
10
kvs_data.py
10
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
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
||||
|
|
|
|||
34
kvs_pass1.py
34
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']}")
|
||||
print(f"Проход 1: text_size={layout['text_size']}, data_size={layout['data_size']}, bnd_size={layout['bnd_size']}")
|
||||
37
kvs_pass2.py
37
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}")
|
||||
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}")
|
||||
|
|
@ -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('<i', offset))
|
||||
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-битным смещением
|
||||
"""
|
||||
code = bytearray()
|
||||
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)
|
||||
if not (-128 <= offset <= 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
|
||||
|
||||
|
||||
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-битным смещением
|
||||
"""
|
||||
code = bytearray()
|
||||
instr = INSTRUCTIONS[mnemonic]
|
||||
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)
|
||||
code.extend(struct.pack('<i', offset))
|
||||
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-битным смещением
|
||||
"""
|
||||
code = bytearray()
|
||||
instr = INSTRUCTIONS[mnemonic]
|
||||
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)
|
||||
if not (-128 <= offset <= 127):
|
||||
raise ValueError(f"Смещение короткого перехода {offset} вне диапазона [-128..127]")
|
||||
|
|
@ -726,14 +742,14 @@ def encode_jcc_short(mnemonic, operands, labels, label_sections, symbols, vaddr_
|
|||
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 - вызов процедуры
|
||||
"""
|
||||
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('<i', offset))
|
||||
return code
|
||||
|
|
@ -744,14 +760,14 @@ def encode_ret():
|
|||
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 - инструкция цикла
|
||||
"""
|
||||
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 + 2)
|
||||
if not (-128 <= offset <= 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 с памятью -----
|
||||
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 == "сохранить":
|
||||
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 == "загрузить_адрес":
|
||||
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 (разные формы) -----
|
||||
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 == "переместить":
|
||||
return encode_mov_reg_reg(operands)
|
||||
elif mnemonic == "загрузить_байт":
|
||||
return encode_mov_reg8_imm8(operands)
|
||||
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 == "переместить_со_знаком":
|
||||
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 (сравнение) -----
|
||||
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 ("сравнить", "сравнить_байт", "проверить"):
|
||||
return encode_cmp_reg_reg(mnemonic, operands)
|
||||
|
||||
# ----- ADD/SUB (арифметика) -----
|
||||
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 ("прибавить", "вычесть", "прибавить_байт", "вычесть_байт"):
|
||||
return encode_add_sub_reg_reg(mnemonic, operands)
|
||||
|
||||
|
|
@ -1079,25 +1095,25 @@ def encode_instruction(mnemonic, operands, labels, label_sections, symbols, vadd
|
|||
|
||||
# ----- Переходы -----
|
||||
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 == "короткий_переход":
|
||||
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 ("переход_если_равно", "переход_если_неравно", "переход_если_меньше",
|
||||
"переход_если_больше", "переход_если_меньше_или_равно", "переход_если_больше_или_равно",
|
||||
"переход_если_перенос", "переход_если_нет_переноса", "переход_если_ноль", "переход_если_не_ноль"):
|
||||
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 ("короткий_переход_если_равно", "короткий_переход_если_неравно",
|
||||
"короткий_переход_если_меньше", "короткий_переход_если_больше",
|
||||
"короткий_переход_если_меньше_или_равно", "короткий_переход_если_больше_или_равно",
|
||||
"короткий_переход_если_перенос", "короткий_переход_если_нет_переноса",
|
||||
"короткий_переход_если_ноль", "короткий_переход_если_не_ноль"):
|
||||
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 -----
|
||||
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 == "цикл":
|
||||
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 -----
|
||||
elif mnemonic == "втолкнуть":
|
||||
|
|
|
|||
7
todo.txt
7
todo.txt
|
|
@ -243,4 +243,9 @@ Pass2 (шаг 5):
|
|||
|
||||
**Статус: v2.0 — абсолютная адресация реализована полностью.**
|
||||
**Следующая цель: v3.0 — косвенная адресация `[reg]`.**
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
|
||||
избавиться от ре и перенести таблицу фиксированных размеров
|
||||
вынести работу с памятью из второго прохода в отдельный энкодер
|
||||
9
тесты/test_bss.квс
Normal file
9
тесты/test_bss.квс
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
.текст
|
||||
.глобал _start
|
||||
_start:
|
||||
переместить_имм раикс, 60
|
||||
переместить_имм рдиай, 0
|
||||
вызов_системы
|
||||
|
||||
.бнд
|
||||
буфер: .резб 1048576 ; 1 МБ = 1024 * 1024
|
||||
|
|
@ -25,4 +25,4 @@ _start:
|
|||
|
||||
.данные
|
||||
msg: .строка "Тест пройден!\n" ; не менять их местами, чтоб не затереть текст
|
||||
переменная: .байт 0 ; тут либо резервировать пустые, либо .bss изобретать
|
||||
переменная: .байт 0 ; тут либо резервировать пустые, либо .bss изобретать (или кучу?)
|
||||
30
тесты/test_success2.квс
Normal file
30
тесты/test_success2.квс
Normal 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)
|
||||
36
тесты/test_success3.квс
Normal file
36
тесты/test_success3.квс
Normal 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 байт под указатель на строку
|
||||
Loading…
Reference in a new issue