исправление смещения .bss

This commit is contained in:
mzhoot 2026-05-17 16:15:27 +03:00
parent 9ba53693d5
commit e54fb6a479
6 changed files with 130 additions and 18 deletions

View file

@ -125,10 +125,10 @@ def create_elf(text_bytes, data_bytes, pass1_data, labels, output_file):
ph1 = phdr(1, 5, offset_text, vaddr_text, len(text_bytes), align_up(len(text_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)
# memsz должно покрывать от vaddr_data до конца .bss
bss_end = vaddr_bnd + bnd_size
data_segment_memsz = align_up(bss_end - vaddr_data, 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))

View file

@ -316,8 +316,8 @@ 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)
vaddr_bnd = align_up(vaddr_data + max(data_size, 1), PAGE_SIZE)
# .бнд всегда на следующей странице после .data
vaddr_bnd = vaddr_data + PAGE_SIZE
comment_size = len("Сборщик КВС".encode('utf-8')) + 1
offset_comment = align_up(offset_data + data_size, 1)
@ -370,4 +370,21 @@ 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']}, bnd_size={layout['bnd_size']}")
print(f"Проход 1:")
print(f" .text: размер={layout['text_size']} байт, смещение_в_файле=0x{layout['offset_text']:x}, виртуальный_адрес=0x{layout['vaddr_text']:x}")
print(f" .data: размер={layout['data_size']} байт, смещение_в_файле=0x{layout['offset_data']:x}, виртуальный_адрес=0x{layout['vaddr_data']:x}")
print(f" .бнд: размер={layout['bnd_size']} байт, виртуальный_адрес=0x{layout['vaddr_bnd']:x}")
print(f" entry_point: {layout['entry_point']}")
print(f" метки:")
for label, pos in pass1.labels.items():
sec = pass1.label_sections.get(label, ".text")
if sec == ".text":
addr = layout['vaddr_text'] + pos
elif sec == ".data":
addr = layout['vaddr_data'] + pos
elif sec == ".бнд":
addr = layout['vaddr_bnd'] + pos
else:
addr = pos
print(f" {label}: секция={sec}, смещение={pos}, адрес=0x{addr:x}")

View file

@ -65,7 +65,7 @@ def read_pass1(input_file):
if parts[0] == "PARAM":
key = parts[1]
value = parts[2]
if value.isdigit():
if value.isdigit() or (value.startswith('-') and value[1:].isdigit()):
value = int(value)
data[key] = value
elif parts[0] == "LABEL":
@ -182,8 +182,8 @@ class Pass2:
self.label_sections = label_sections
self.symbols = symbols
self.vaddr_text = pass1_data["vaddr_text"]
text_size = pass1_data["text_size"]
self.vaddr_data = align_up(self.vaddr_text + text_size, PAGE_SIZE)
self.vaddr_data = pass1_data.get("vaddr_data", align_up(self.vaddr_text + pass1_data["text_size"], PAGE_SIZE))
self.vaddr_bnd = pass1_data.get("vaddr_bnd", self.vaddr_data + PAGE_SIZE)
self.position = {".text": 0, ".data": 0}
self.current_section = ".text"
self.csv_lines = []
@ -211,7 +211,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])
@ -291,7 +298,8 @@ class Pass2:
current_pos = self.position[sec]
code = encode_instruction(mnemonic, operands, self.labels, self.label_sections,
self.symbols, self.vaddr_text, self.vaddr_data, current_pos)
self.symbols, self.vaddr_text, self.vaddr_data, current_pos,
self.vaddr_bnd)
target_addr = self.get_target_addr(mnemonic, operands)

View file

@ -55,10 +55,7 @@ def parse_operand(operand, labels, label_sections, symbols, vaddr_text, vaddr_da
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
return labels[operand] + vaddr_bnd
else:
return labels[operand] + vaddr_text
if operand in symbols:
@ -111,7 +108,7 @@ def parse_memory_operand(operand_str, labels, label_sections, vaddr_text, vaddr_
elif section == '.data':
base = vaddr_data
elif section == '.бнд':
base = vaddr_bnd if vaddr_bnd is not None else vaddr_data
base = vaddr_bnd
else:
base = vaddr_text
addr = labels[value] + base
@ -140,7 +137,7 @@ def parse_memory_operand(operand_str, labels, label_sections, vaddr_text, vaddr_
elif section == '.data':
base = vaddr_data
elif section == '.бнд':
base = vaddr_bnd if vaddr_bnd is not None else vaddr_data
base = vaddr_bnd
else:
base = vaddr_text
addr = labels[content] + base

View file

@ -88,4 +88,49 @@ _start:
## Как проверить
Если закомментировать Тест 3 (строки с `рсикс` и `неиниц_бнд`), код возврата станет `66` — баг исчезает, потому что `0x402000` не перезаписывается.
Если закомментировать Тест 3 (строки с `рсикс` и `неиниц_бнд`), код возврата станет `66` — баг исчезает, потому что `0x402000` не перезаписывается.
`vaddr_data` считается в **двух** местах:
### 1. `kvs_pass1.py` — метод `calculate_layout`
```python
vaddr_text = text_vaddr_base # 0x401000
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE) # 0x402000
vaddr_bnd = align_up(vaddr_data + data_size, PAGE_SIZE) # 0x402000 или 0x403000
```
Эти значения записываются в pass1-файл как `PARAM:vaddr_text:...`, `PARAM:vaddr_data:...`, `PARAM:vaddr_bnd:...`.
### 2. `kvs_pass2.py` — конструктор `Pass2.__init__`
```python
self.vaddr_text = pass1_data["vaddr_text"] # читает из pass1
self.vaddr_data = align_up(self.vaddr_text + text_size, PAGE_SIZE) # вычисляет заново
```
**Pass2 не читает `vaddr_data` из pass1, а вычисляет сам.** А `vaddr_bnd` не читает и не вычисляет вообще.
### 3. `kvs_builder.py` — функция `create_elf`
```python
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE) # вычисляет заново
vaddr_bnd = pass1_data.get("vaddr_bnd", ...) # читает из pass1
```
**Builder читает `vaddr_bnd` из pass1**, но энкодер (pass2) его не получает.
---
## Корень бага
| Модуль | `vaddr_data` | `vaddr_bnd` |
|--------|:-----------:|:----------:|
| pass1 | вычисляет ✅ | вычисляет ✅ |
| pass2 | вычисляет ✅ | **не читает** ❌ |
| builder | вычисляет ✅ | читает из pass1 ✅ |
| encoder (mutsize) | получает от pass2 ✅ | **не получает** ❌ |
Pass2 не передаёт `vaddr_bnd` в энкодер, поэтому `parse_operand` получает `vaddr_bnd=None` и подставляет `vaddr_data` для меток `.бнд`.

View file

@ -0,0 +1,45 @@
.текст
.глобал _start
_start:
; =============================================
; ТЕСТ 1: Абсолютная адресация в .бнд
; =============================================
переместить_имм раикс, 0x42
сохранить [абс_перем], раикс
; =============================================
; ТЕСТ 2: Косвенная адресация в .бнд
; =============================================
переместить_имм рбикс, косв_перем
переместить_имм раикс, 0x99
сохранить [рбикс], раикс
; =============================================
; ТЕСТ 3: Ещё одна косвенная адресация в .бнд
; =============================================
переместить_имм рсикс, ещё_перем
переместить_имм раикс, 0x77
сохранить [рсикс], раикс
; =============================================
; Читаем всё обратно
; =============================================
загрузить р8, [абс_перем]
загрузить р9, [рбикс]
загрузить р10, [рсикс]
; =============================================
; ЗАВЕРШЕНИЕ: возвращаем из абс_перем
; =============================================
загрузить рдиай, [абс_перем]
переместить_имм раикс, 60
вызов_системы
.бнд
абс_перем:
.резб 1
косв_перем:
.резб 1
ещё_перем:
.резб 8