91 lines
4.6 KiB
Plaintext
91 lines
4.6 KiB
Plaintext
|
|
## Исходник
|
|||
|
|
|
|||
|
|
```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` не перезаписывается.
|