## Исходник

```asm
.текст
.глобал _start

_start:
    ; ТЕСТ 1: Абсолютная адресация в .data
    переместить_имм раикс, 0x42
    сохранить [абс_данные], раикс       ; запись 0x42 по адресу абс_данные (0x402000)

    ; ТЕСТ 2: Косвенная адресация в .data
    переместить_имм рбикс, косв_данные   ; рбикс = адрес косв_данные (0x402001)
    переместить_имм раикс, 0x99
    сохранить [рбикс], раикс            ; запись 0x99 по адресу 0x402001

    ; ТЕСТ 3: Косвенная адресация в .бнд
    переместить_имм рсикс, неиниц_бнд   ; рсикс = адрес неиниц_бнд
    переместить_имм раикс, 0x77
    сохранить [рсикс], раикс            ; запись 0x77 по адресу неиниц_бнд

    ; Читаем всё обратно
    загрузить р8, [абс_данные]          ; чтение из 0x402000
    загрузить р9, [рбикс]               ; чтение из 0x402001
    загрузить р10, [рсикс]              ; чтение из неиниц_бнд

    ; ЗАВЕРШЕНИЕ: возвращаем значение из абс_данные
    загрузить рдиай, [абс_данные]       ; рдиай = значение из 0x402000
    переместить_имм раикс, 60           ; номер системного вызова exit
    вызов_системы

.данные
абс_данные:
    .байт 0
косв_данные:
    .байт 0

.бнд
неиниц_бнд:
    .резб 8
```

## Размещение секций в памяти

```
0x401000 ─ .text (код)
0x402000 ─ .data
             ├── абс_данные (смещение 0): байт 0
             └── косв_данные (смещение 1): байт 0
0x403000 ─ .бнд
             └── неиниц_бнд (смещение 0): 8 байт, ноль
```

## Что подразумевается

1. **Тест 1** пишет `0x42` в `абс_данные` по адресу `0x402000`.
2. **Тест 2** пишет `0x99` в `косв_данные` по адресу `0x402001`.
3. **Тест 3** пишет `0x77` в `неиниц_бнд` по адресу **`0x403000`**.

После этого:
- `[0x402000]` содержит `0x42`
- `[0x402001]` содержит `0x99`
- `[0x403000]` содержит `0x77`

Финал читает `[абс_данные]` = `[0x402000]` = `0x42` в `рдиай` и завершается.

**Ожидаемый код возврата:** `66` (это `0x42`).

## Что происходит на самом деле

**Фактический код возврата:** `119` (это `0x77`).

## Причина

Инструкция `переместить_имм рсикс, неиниц_бнд` загружает в `рсикс` **неправильный адрес**. Вместо `0x403000` (адрес `.бнд`) регистр получает `0x402002` (адрес внутри `.data`).

Это происходит потому, что при вычислении адреса метки `неиниц_бнд` компилятор ошибочно использует базовый адрес секции `.data` (`0x402000`) вместо базового адреса секции `.бнд` (`0x403000`).

Смещение метки `неиниц_бнд` внутри `.бнд` равно `0`. Правильный расчёт должен быть: `0x403000 + 0 = 0x403000`. Но компилятор считает: `0x402000 + 0 = 0x402000`.

## Цепочка последствий

1. `рсикс` получает `0x402000` вместо `0x403000`.
2. `сохранить [рсикс], раикс` пишет `0x77` по адресу `0x402000` — **это ячейка `абс_данные`**.
3. Значение `0x42`, записанное в Тесте 1, **затирается** значением `0x77`.
4. Финал читает `[абс_данные]` и получает `0x77` вместо `0x42`.
5. Код возврата становится `119` вместо `66`.

## Как проверить

Если закомментировать Тест 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` для меток `.бнд`.