Files
lab-rv32i-c-pointers-arrays/json/card_source.json
T
2026-07-19 18:39:17 +02:00

1286 lines
89 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"$schema": "https://zsl-gitea.mpabi.pl/edu-tools/card-layouts/raw/branch/main/schemas/card-source.schema.json",
"schema": "esc-card-source.v1",
"card": {
"id": "mpabi-inf-c-07-pointers-arrays",
"series": "c",
"series_title": "C · Freestanding RV32I and K&R",
"number": "07",
"count": "13",
"slug": "pointers-arrays",
"title": "Wskaźniki i tablice",
"topic": "Od K&R 5.1--5.4 do struktur i FreeRTOS heap_4",
"project": "Alokator pamięci",
"subject": "Informatyka",
"level": "PP@2024.06.28 · Inf. · ZP · Kl. 1 · Poz. 1",
"revision_date": "2026-07-19T00:00:00+02:00",
"status": "Gotowa",
"version": "v00.01",
"uuid": "4abec2d9-79e9-0dca-9040-c60669f51ff8",
"author": "M. Pabiszczak",
"year": "2026"
},
"generated": {
"tex": "doc/generated/main.tex",
"html": "web/index.html",
"html_css": "web/style.css",
"html_tree_inspector": false,
"react_app": true
},
"render_dictionary": false,
"debug_checkpoints": {
"schema": "stem-debug-checkpoints.v1",
"semantics": "deterministic-replay",
"recorded_grid_pattern": "debug-snapshots/{snapshot_ref}.json",
"artifact": {
"source": "src/tasks/task04_address_arithmetic_alloc.c",
"source_git_blob": "a8aa25b3e6b68af6dbfd640937b6660b2ed5c5af",
"elf": ".stem/instances/hazard3-sim-inf-pointers-t4/build/hazard3/task04_address_arithmetic_alloc/prog.elf",
"hazard3_image": ".stem/instances/hazard3-sim-inf-pointers-t4/build/hazard3/task04_address_arithmetic_alloc/prog.bin",
"hazard3_image_sha256": "59e042815059da76a8c5e85c1317abaae9decf5e9ea77ef54e6da4175f71a307"
},
"targets": {
"hazard3-sim": {
"adapter": "hazard3-reset-load-replay.v1",
"baseline": "restart-backend",
"clean_ram": true
},
"rp2350": {
"adapter": "rp2350-sram-reset-load-replay.v1",
"baseline": "reset-load-elf-sram",
"requires_probe_lease": true,
"persistent_flash": false
}
},
"items": {
"task04.reset.call": {"stop": {"symbol": "main", "offset": 16}, "verify": {"expressions": []}},
"task04.reset.address": {"stop": {"symbol": "allocator_reset", "offset": 28}, "verify": {"expressions": []}},
"task04.reset.store": {"stop": {"symbol": "allocator_reset", "offset": 32}, "verify": {"expressions": [{"expr": "allocp - allocbuf", "equals": 0}]}},
"task04.reset.return": {"stop": {"symbol": "main", "offset": 24}, "verify": {"expressions": [{"expr": "allocp - allocbuf", "equals": 0}]}},
"task04.alloc5.enter": {"stop": {"symbol": "main", "offset": 28}, "verify": {"expressions": [{"expr": "$a0", "equals": 5}, {"expr": "allocp - allocbuf", "equals": 0}]}},
"task04.alloc5.cursor": {"stop": {"symbol": "alloc_local", "offset": 40, "condition": "$a0 == 5"}, "verify": {"expressions": [{"expr": "$a0", "equals": 5}, {"expr": "allocp - allocbuf", "equals": 0}]}},
"task04.alloc5.buffer-address": {"stop": {"symbol": "alloc_local", "offset": 56, "condition": "$a0 == 5"}, "verify": {"expressions": [{"expr": "allocp - allocbuf", "equals": 0}]}},
"task04.alloc5.used": {"stop": {"symbol": "alloc_local", "offset": 64, "condition": "$a0 == 5"}, "verify": {"expressions": [{"expr": "$a0", "equals": 5}, {"expr": "allocp - allocbuf", "equals": 0}]}},
"task04.alloc5.commit": {"stop": {"symbol": "alloc_local", "offset": 156, "condition": "$a0 == 5"}, "verify": {"expressions": [{"expr": "$a0", "equals": 5}, {"expr": "allocp - allocbuf", "equals": 5}]}},
"task04.alloc5.return": {"stop": {"symbol": "main", "offset": 40}, "verify": {"expressions": [{"expr": "allocp - allocbuf", "equals": 5}, {"expr": "first - allocbuf", "equals": 0}]}},
"task04.alloc7.enter": {"stop": {"symbol": "main", "offset": 44}, "verify": {"expressions": [{"expr": "$a0", "equals": 7}, {"expr": "allocp - allocbuf", "equals": 5}]}},
"task04.alloc7.cursor": {"stop": {"symbol": "alloc_local", "offset": 40, "condition": "$a0 == 7"}, "verify": {"expressions": [{"expr": "$a0", "equals": 7}, {"expr": "allocp - allocbuf", "equals": 5}]}},
"task04.alloc7.used": {"stop": {"symbol": "alloc_local", "offset": 64, "condition": "$a0 == 7"}, "verify": {"expressions": [{"expr": "$a0", "equals": 7}, {"expr": "allocp - allocbuf", "equals": 5}]}},
"task04.alloc7.commit": {"stop": {"symbol": "alloc_local", "offset": 156, "condition": "$a0 == 7"}, "verify": {"expressions": [{"expr": "$a0", "equals": 7}, {"expr": "allocp - allocbuf", "equals": 12}]}},
"task04.alloc7.return": {"stop": {"symbol": "main", "offset": 56}, "verify": {"expressions": [{"expr": "allocp - allocbuf", "equals": 12}, {"expr": "first - allocbuf", "equals": 0}, {"expr": "second - allocbuf", "equals": 5}]}}
}
},
"template": "templates/karta-klasyczna.json",
"title_block": {
"category": "KARTA PRACY · INFORMATYKA",
"prepared_by": "M. Pabiszczak",
"prepared_on": "2026-07-19T00:00:00+02:00",
"title": "Wskaźniki i tablice",
"url": "https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/98dbe323-c624-53d6-9fe2-4ee688c44b38",
"repository_url": "https://zsl-gitea.mpabi.pl/edu-c/lab-rv32i-c-pointers-arrays",
"url_host_uuid": "dce7fb9d-7b2f-5d49-96a2-3a30d3070b84",
"url_domain": "mpabi.pl",
"doc_uuid": "98dbe323-c624-53d6-9fe2-4ee688c44b38",
"revision": "v00.01",
"issued_on": "2026-07-19T00:00:00+02:00",
"series": "C-07",
"document_type": "karta pracy",
"tool": "card-layouts",
"show_qr": true,
"show_repository_qr": true,
"height_cm": 2.6,
"repeat_on_every_page": true,
"replace_front_matter": true
},
"reference_registries": [
{
"uuid": "03403a8a-e20d-5b17-9004-26d9fe6c3003",
"source": "../../../tools/debugging-strategies/json/reference_registry.json"
}
],
"debug_strategies": {
"run.runtime": {
"id": "run.runtime",
"kind": "run",
"action": "replay",
"prerequisites": [
"Hazard3/GDB online",
"symbole ELF Task04"
],
"layout": [
"source",
"assembly",
"registers",
"stack",
"allocbuf"
],
"commands": [
"info registers a0 a4 a5 sp s0 pc",
"print allocp - allocbuf",
"x/16bx allocbuf"
],
"expected_observations": [
"allocp przechodzi przez offsety 0, 5 i 12",
"allocbuf i allocp należą do .bss, a sp do bieżącej ramki stosu"
],
"assertions": [
"wybrany checkpoint odtwarza deterministyczny stan alokatora",
"PC i linia źródła odpowiadają wybranej strzałce UML"
],
"evidence_fields": [
"snapshot_ref",
"source_ref",
"PC",
"registers",
"allocp offset",
"ELF hash",
"timestamp"
]
}
},
"front_page_break": true,
"front_page_scope": {
"title": "Cel karty",
"content_tex": "Uczeń implementuje i weryfikuje liniowy alokator z areną \\texttt{allocbuf} i kursorem \\texttt{allocp}; przewiduje offsety, odczytuje je w pamięci oraz dowodzi, że \\texttt{allocp} nie jest wskaźnikiem stosu \\texttt{sp}.",
"scope_title": "Zakres karty",
"scope_table": {
"headers": ["K&R", "Numer tasku", "Najważniejsza idea", "Priorytet", "Status", "Version"],
"rows": [
{"chapter": "5.1", "task": "Task01", "idea_tex": "adres, \\texttt{\\&}, \\texttt{*}", "priority": "obowiązkowe", "status": "not-started", "version": "v00.01"},
{"chapter": "5.2", "task": "Task02", "idea_tex": "wskaźnik jako argument funkcji", "priority": "obowiązkowe", "status": "not-started", "version": "v00.01"},
{"chapter": "5.3", "task": "Task03", "idea_tex": "relacja tablicy i wskaźnika", "priority": "obowiązkowe", "status": "not-started", "version": "v00.01"},
{"chapter": "5.4", "task": "Task04", "idea_tex": "arytmetyka adresów, alokator", "priority": "obowiązkowe", "status": "in-progress", "version": "v00.01", "key": true},
{"chapter": "5.5", "task": "Task05", "idea_tex": "napisy jako \\texttt{char *}, NUL", "priority": "ważne", "status": "not-started", "version": "v00.01"},
{"chapter": "5.6", "task": "Task06", "idea_tex": "tablica wskaźników", "priority": "ważne", "status": "not-started", "version": "v00.01"},
{"chapter": "5.7", "task": "Task07", "idea_tex": "tablice wielowymiarowe", "priority": "ważne", "status": "not-started", "version": "v00.01"},
{"chapter": "5.8", "task": "Task08", "idea_tex": "inicjalizacja tablic wskaźników", "priority": "wspierające", "status": "not-started", "version": "v00.01"},
{"chapter": "5.9", "task": "Task09", "idea_tex": "\\texttt{int a[R][C]} kontra \\texttt{int *a[]}", "priority": "bardzo ważne", "status": "not-started", "version": "v00.01"},
{"chapter": "5.10", "task": "Task10", "idea_tex": "\\texttt{argv} i argumenty programu", "priority": "wspierające", "status": "not-started", "version": "v00.01"},
{"chapter": "5.11", "task": "Task11", "idea_tex": "wskaźniki do funkcji", "priority": "ważne przed callbackami", "status": "not-started", "version": "v00.01"},
{"chapter": "5.12", "task": "Task12", "idea_tex": "czytanie złożonych deklaracji", "priority": "uzupełniające", "status": "not-started", "version": "v00.01"}
]
}
},
"side_margin_tree_layout": {
"columns": [
{
"id": "zawodowe",
"label": "TECH",
"side": "left",
"tree": "WE -> EK -> KW",
"description": "Umiejętności techniczne: C, RISC-V, debugowanie i pamięć."
},
{
"id": "ogolne",
"label": "OG",
"side": "right",
"tree": "WE -> EN -> KW",
"description": "Umiejętności ogólne: przewidywanie, pomiar i wnioskowanie."
}
]
},
"learning_effects": {
"PTR.EN01": {
"bloom_level": "Analiza",
"label": "Przewidywanie",
"text": "Uczeń przewiduje wartości, adresy i offsety przed uruchomieniem programu, a następnie porównuje je z pomiarem.",
"assessment_criteria": ["PTR.KW01", "PTR.KW02"]
},
"PTR.EN02": {
"bloom_level": "Ewaluacja",
"label": "Dowód",
"text": "Uczeń zapisuje odtwarzalny dowód i odróżnia wynik od jego interpretacji.",
"assessment_criteria": ["PTR.KW04"]
},
"PTR.EK01": {
"bloom_level": "Zastosowanie",
"label": "Wskaźniki i tablice",
"text": "Uczeń stosuje adresowanie, dereferencję, argumenty wskaźnikowe i arytmetykę wskaźników w granicach tablicy.",
"assessment_criteria": ["PTR.KW01"]
},
"PTR.EK02": {
"bloom_level": "Analiza",
"label": "Debugowanie RV32",
"text": "Uczeń odnajduje argumenty, zmienne lokalne, ramkę stosu, rejestry i bajty pamięci w debuggerze Hazard3.",
"assessment_criteria": ["PTR.KW03", "PTR.KW04"]
},
"PTR.EK03": {
"bloom_level": "Analiza",
"label": "Alokator",
"text": "Uczeń śledzi inwarianty liniowego alokatora i wskazuje elementy potrzebne do przejścia do struktur oraz heap_4.",
"assessment_criteria": ["PTR.KW02", "PTR.KW03"]
}
},
"assessment_criteria": {
"PTR.KW01": {
"text": "Task01--Task03 kończą się kodem 0, przewidywania są zapisane, a wartości i offsety zgadzają się z pomiarem.",
"learning_effects": ["PTR.EN01", "PTR.EK01"]
},
"PTR.KW02": {
"text": "Task04 daje offsety 0, 5, 12 i 5; odrzuca brak miejsca i żądanie zera; suma znaków wynosi 372.",
"learning_effects": ["PTR.EN01", "PTR.EK03"]
},
"PTR.KW03": {
"text": "Uczeń pokazuje allocbuf w pamięci, odróżnia allocp od sp oraz potwierdza wyrównanie sp do 16 bajtów.",
"learning_effects": ["PTR.EK02", "PTR.EK03"]
},
"PTR.KW04": {
"text": "Dowód zawiera wynik AMD64, Hazard3 i -- dla Task04 na zajęciach -- RP2350, wraz z komendą, bramką i obserwacją debuggera.",
"learning_effects": ["PTR.EN02", "PTR.EK02"]
}
},
"educational_requirements": {
"PTR.WE01": {
"text": "Poprawne rozumowanie o adresach, wartościach i przesunięciach wskaźników.",
"label": "Semantyka wskaźników",
"learning_effects": ["PTR.EN01", "PTR.EK01"],
"learning_tree": {
"schema": "we-learning-tree.v1",
"policy": "Najpierw przewidywanie, potem pomiar, na końcu wniosek.",
"ogolne": [
{
"effect_ref": "PTR.EN01",
"display": "EN PTR 01",
"source": "LOCAL",
"official": "PTR",
"local": "01",
"kind": "EN",
"text": "Przewidywanie i porównanie wyniku.",
"tree_id": "PTR.WE01.OG.EN01",
"kw": [
{
"criterion_ref": "PTR.KW01",
"display": "KW PTR 01",
"source": "LOCAL",
"kind": "KW",
"official": "PTR",
"local": "01",
"text": "Task01--Task03: zgodne wartości i offsety."
}
]
}
],
"zawodowe": [
{
"effect_ref": "PTR.EK01",
"display": "EK PTR 01",
"source": "LOCAL",
"official": "PTR",
"local": "01",
"kind": "EK",
"text": "Wskaźniki, tablice i argumenty funkcji.",
"tree_id": "PTR.WE01.TECH.EK01",
"kw": [
{
"criterion_ref": "PTR.KW01",
"display": "KW PTR 01",
"source": "LOCAL",
"kind": "KW",
"official": "PTR",
"local": "01",
"text": "Task01--Task03: zgodne wartości i offsety."
}
]
}
]
}
},
"PTR.WE02": {
"text": "Odtwarzalna obserwacja wykonania programu na RV32 i RP2350.",
"label": "Pomiar debuggera",
"learning_effects": ["PTR.EN02", "PTR.EK02"],
"learning_tree": {
"schema": "we-learning-tree.v1",
"policy": "Każdy wniosek wskazuje komendę i obserwowany stan.",
"ogolne": [
{
"effect_ref": "PTR.EN02",
"display": "EN PTR 02",
"source": "LOCAL",
"official": "PTR",
"local": "02",
"kind": "EN",
"text": "Dokumentowanie dowodu pomiarowego.",
"tree_id": "PTR.WE02.OG.EN02",
"kw": [
{
"criterion_ref": "PTR.KW04",
"display": "KW PTR 04",
"source": "LOCAL",
"kind": "KW",
"official": "PTR",
"local": "04",
"text": "Dowód z platform, bramek i debuggera."
}
]
}
],
"zawodowe": [
{
"effect_ref": "PTR.EK02",
"display": "EK PTR 02",
"source": "LOCAL",
"official": "PTR",
"local": "02",
"kind": "EK",
"text": "Rejestry, stos, ASM i pamięć RV32.",
"tree_id": "PTR.WE02.TECH.EK02",
"kw": [
{
"criterion_ref": "PTR.KW03",
"display": "KW PTR 03",
"source": "LOCAL",
"kind": "KW",
"official": "PTR",
"local": "03",
"text": "allocbuf, allocp, sp i wyrównanie stosu."
},
{
"criterion_ref": "PTR.KW04",
"display": "KW PTR 04",
"source": "LOCAL",
"kind": "KW",
"official": "PTR",
"local": "04",
"text": "Dowód z platform, bramek i debuggera."
}
]
}
]
}
},
"PTR.WE03": {
"text": "Wyjaśnienie działania alokatora liniowego i jego ograniczeń przed strukturami i heap_4.",
"label": "Od K&R 5.4 do heap_4",
"learning_effects": ["PTR.EN01", "PTR.EK03"],
"learning_tree": {
"schema": "we-learning-tree.v1",
"policy": "Stan kursora i granice areny są sprawdzane po każdej operacji.",
"ogolne": [
{
"effect_ref": "PTR.EN01",
"display": "EN PTR 03",
"source": "LOCAL",
"official": "PTR",
"local": "03",
"kind": "EN",
"text": "Przewidywanie osi zmian alokatora.",
"tree_id": "PTR.WE03.OG.EN01",
"kw": [
{
"criterion_ref": "PTR.KW02",
"display": "KW PTR 02",
"source": "LOCAL",
"kind": "KW",
"official": "PTR",
"local": "02",
"text": "Offsety i przypadki brzegowe Task04."
}
]
}
],
"zawodowe": [
{
"effect_ref": "PTR.EK03",
"display": "EK PTR 03",
"source": "LOCAL",
"official": "PTR",
"local": "03",
"kind": "EK",
"text": "Inwarianty alokatora i przejście do heap_4.",
"tree_id": "PTR.WE03.TECH.EK03",
"kw": [
{
"criterion_ref": "PTR.KW02",
"display": "KW PTR 02",
"source": "LOCAL",
"kind": "KW",
"official": "PTR",
"local": "02",
"text": "Offsety i przypadki brzegowe Task04."
},
{
"criterion_ref": "PTR.KW03",
"display": "KW PTR 03",
"source": "LOCAL",
"kind": "KW",
"official": "PTR",
"local": "03",
"text": "allocbuf, allocp, sp i wyrównanie stosu."
}
]
}
]
}
}
},
"sections": [
{
"title": "K&R 5.4 -- Task04: Linear Memory Allocator",
"order": 10,
"content_kind": "prose",
"content_tex": "\\textbf{Jak działa alokator liniowy}\n\n\\begin{itemize}[leftmargin=*]\n\\item \\textbf{Model pamięci:}\n \\begin{itemize}[label=--]\n \\item \\texttt{allocbuf[ALLOCSIZE]} jest statyczną areną 64 B.\n \\item \\texttt{allocp} wskazuje pierwszy wolny bajt; offset to \\texttt{allocp - allocbuf}.\n \\end{itemize}\n\\item \\textbf{Operacje:}\n \\begin{itemize}[label=--]\n \\item \\texttt{allocator\\_reset()} ustawia \\texttt{allocp = allocbuf}.\n \\item \\texttt{alloc\\_local(n)} zwraca bieżący kursor i przesuwa go o \\texttt{n}, jeżeli żądanie jest dodatnie i mieści się w arenie.\n \\end{itemize}\n\\item \\textbf{Stan po sekwencji reset → alloc(5) → alloc(7):}\n \\begin{itemize}[label=--]\n \\item \\texttt{first = allocbuf + 0},\n \\item \\texttt{second = allocbuf + 5},\n \\item \\texttt{allocp = allocbuf + 12}.\n \\end{itemize}\n\\item \\textbf{Ograniczenie:} pojedynczych bloków nie zwalniamy; pamięć odzyskuje \\texttt{allocator\\_reset()} dla całej areny. Dowolne \\texttt{free} pojawi się później przy strukturach i \\texttt{heap\\_4}.\n\\end{itemize}",
"asset_page_mode": "one-per-page",
"render_step_map": false,
"assets": [
{
"path": "assets/task04-allocator-arena-model.png",
"caption": "SCHEMAT — arena allocbuf ma 64 B; po przydziałach 5 B i 7 B kursor allocp wskazuje offset 12. Odczytaj granice obu obszarów i pierwszy wolny bajt.",
"label": "fig:task04-arena-model",
"alt": "Schemat areny allocbuf 64 B z przydziałami 5 B i 7 B oraz kursorem allocp na offsecie 12.",
"kind": "diagram",
"width": 0.72
},
{
"path": "assets/task04-memory-flow.png",
"html_path": "assets/task04-memory-flow.svg",
"source_path": "assets/task04-memory-flow.puml",
"caption": "UML — sekwencja allocator_reset() → alloc_local(5) → alloc_local(7), ramki aktywacji main()/alloc_local(n) oraz statyczne obiekty allocbuf/allocp.",
"label": "fig:task04-memory-flow",
"alt": "Diagram sekwencji UML Task04: main wywołuje allocator_reset(), a następnie dwukrotnie funkcję alloc_local(), która odczytuje allocbuf i aktualizuje allocp.",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 938,
"page_height": 1184,
"overview": true,
"step_tiles": {
"reset-call": 1,
"reset-read-buffer-address": 1,
"reset-buffer-address-result": 1,
"reset-store-cursor": 1,
"reset-return": 1,
"alloc5-call": 1,
"alloc5-read-cursor": 1,
"alloc5-cursor-result": 1,
"alloc5-read-buffer-address": 1,
"alloc5-buffer-address-result": 1,
"alloc5-used": 1,
"alloc5-commit": 1,
"alloc5-return": 1,
"alloc7-call": 1,
"alloc7-read-cursor": 1,
"alloc7-cursor-result": 1,
"alloc7-used": 1,
"alloc7-commit": 1,
"alloc7-return": 1
}
},
"interactive": {
"kind": "uml-sequence",
"storage_key": "task04-memory-flow",
"title": "Alokator liniowy — sekwencja wywołań",
"task": {
"id": "task04",
"label": "Task04 · Linear Memory Allocator"
},
"block": {
"id": "allocator-flow",
"label": "Sekwencja wykonania",
"description": "Diagram przedstawia kolejno allocator_reset(), alloc_local(5) i alloc_local(7). Wybór numerowanej strzałki synchronizuje Nvim view z odpowiadającym jej stanem wykonania."
},
"snapshot_context": {
"target": "hazard3-sim · RV32I",
"captured_at": "2026-07-16T14:24:29+02:00",
"captured_with": "gdb-multiarch + Hazard3 tb_gdb; świeży przebieg, zatrzymania po zatwierdzeniu instrukcji",
"elf": "/workspace/.stem/instances/hazard3-sim-inf-pointers-t4/build/hazard3/task04_address_arithmetic_alloc/prog.elf",
"stack_top": "0x80100000"
},
"terminal_view": {
"path": "assets/task04-first-allocation-annotated.png",
"title": "Termdebug — cztery połączone dowody",
"alt": "Adnotowany widok Termdebug: wywołanie alloc_local w C, li i jal w listingu, argument pięć w rejestrze a0 oraz bajty allocbuf.",
"caption": "Numery 14 łączą linię C, instrukcje RV32, ABI i pamięć. Dokładny stan wybranego kroku jest odtwarzany w Nvim view."
},
"phases": [
{
"id": "reset",
"label": "RESET",
"description": "Ustanowienie inwariantu allocp = allocbuf i offsetu 0.",
"svg_label": "RESET",
"steps": [
{
"id": "reset-call",
"number": 1,
"label": "allocator_reset()",
"svg_label": "01",
"progress_id": "UML04-S01",
"description": "main ma już własną ramkę i stoi przed wywołaniem resetu; allocp jest jeszcze zerem z inicjalizacji .bss.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:62",
"snapshot_ref": "task04.reset.call",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.main.reset-call", "align": "center"},
"annotations": [
{"id": "ann.reset.call", "anchor_ref": "src.task04.main.reset-call", "label": "1 · reset", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "allocator_reset();", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x8000124c",
"code": {
"source": "allocator_reset();",
"source_ref": "task04_address_arithmetic_alloc.c:62",
"assembly": "0x8000124c auipc ra,0x0\n0x80001250 jalr ra,-284(ra) # allocator_reset",
"note": "PC wskazuje pierwszą instrukcję pary wywołującej; skok wykona się dopiero w następnym kroku procesora."
},
"registers": [{"name": "sp", "value": "0x800fffd0"}, {"name": "s0/fp", "value": "0x800ffff0"}, {"name": "ra", "value": "0x80001030"}, {"name": "a0", "value": "0x800014b0", "note": "wartość zastana; allocator_reset nie ma argumentów"}, {"name": "a4", "value": "0x00000000"}, {"name": "a5", "value": "0x00000000"}],
"frame": {"name": "main", "sp": "0x800fffd0", "fp": "0x800ffff0", "size_bytes": 32, "fields": [{"name": "first", "address": "0x800fffdc", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "second", "address": "0x800fffd8", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "out_of_memory", "address": "0x800fffd4", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "zero_request", "address": "0x800fffd0", "value": "raw 0x00000000", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x00000000", "note": "jeszcze nie jest poprawnym kursorem"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x00000000", "offset": null, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "To stan wywołującego. Ramka main zajmuje 32 B; cztery sloty lokalne istnieją fizycznie, ale ich wartości C nie zostały jeszcze ustalone."
}
},
{
"id": "reset-read-buffer-address",
"number": 2,
"label": "odczytaj adres &allocbuf[0]",
"svg_label": "02",
"progress_id": "UML04-S02",
"description": "Po prologu allocator_reset rejestr a4 zawiera świeżo wyliczony adres początku areny.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:20",
"snapshot_ref": "task04.reset.address",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.reset.assign", "align": "center"},
"annotations": [
{"id": "ann.reset.address", "anchor_ref": "src.task04.reset.assign", "label": "adres areny", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "allocp = allocbuf;", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x8000114c",
"code": {
"source": "allocp = allocbuf;",
"source_ref": "task04_address_arithmetic_alloc.c:20",
"assembly": "0x80001144 lui a4,0x80001\n0x80001148 addi a4,a4,1104 # allocbuf\n0x8000114c sw a4,1168(a5) # allocp",
"note": "Adres początku areny jest już w a4; instrukcja sw wskazywana przez PC nie została jeszcze zatwierdzona."
},
"registers": [{"name": "sp", "value": "0x800fffc0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001254"}, {"name": "a0", "value": "0x800014b0", "note": "reset nie używa a0"}, {"name": "a4", "value": "0x80001450", "note": "&allocbuf[0]"}, {"name": "a5", "value": "0x80001000", "note": "baza adresowania symbolu allocp"}],
"frame": {"name": "allocator_reset", "sp": "0x800fffc0", "fp": "0x800fffd0", "size_bytes": 16, "fields": [{"name": "saved s0", "address": "0x800fffc8", "value": "0x800ffff0", "state": "saved"}, {"name": "saved ra", "address": "0x800fffcc", "value": "0x80001254", "state": "saved"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x00000000"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x00000000", "offset": null, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Adres 0x80001450 został wyliczony w a4, ale zapis do zmiennej allocp jeszcze się nie wykonał."
}
},
{
"id": "reset-buffer-address-result",
"number": 3,
"label": "początek areny",
"svg_label": "03",
"progress_id": "UML04-S03",
"description": "Ta przerywana strzałka interpretuje ten sam stabilny stan: wynikiem odczytu adresu jest 0x80001450 w a4.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:20",
"snapshot_ref": "task04.reset.address",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.reset.assign", "align": "center"},
"annotations": [
{"id": "ann.reset.a4", "anchor_ref": "reg.a4", "label": "a4 = &allocbuf[0]", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a4 0x80001450", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x8000114c",
"code": {
"source": "allocp = allocbuf;",
"source_ref": "task04_address_arithmetic_alloc.c:20",
"assembly": "a4 = 0x80001450 # &allocbuf[0]\npc = 0x8000114c # przed sw do allocp",
"note": "Strzałka zwrotna UML interpretuje wartość a4; nie odpowiada osobnej instrukcji."
},
"registers": [{"name": "sp", "value": "0x800fffc0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001254"}, {"name": "a0", "value": "0x800014b0"}, {"name": "a4", "value": "0x80001450", "note": "początek areny"}, {"name": "a5", "value": "0x80001000"}],
"frame": {"name": "allocator_reset", "sp": "0x800fffc0", "fp": "0x800fffd0", "size_bytes": 16, "fields": [{"name": "saved s0", "address": "0x800fffc8", "value": "0x800ffff0", "state": "saved"}, {"name": "saved ra", "address": "0x800fffcc", "value": "0x80001254", "state": "saved"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x00000000"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x00000000", "offset": null, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Krok 03 nie wykonuje dodatkowej instrukcji; pokazuje wartość adresu zwróconą logicznie przez uczestnika allocbuf."
}
},
{
"id": "reset-store-cursor",
"number": 4,
"label": "zapisz allocp = &allocbuf[0]",
"svg_label": "04",
"progress_id": "UML04-S04",
"description": "Instrukcja sw zakończyła zapis do symbolu allocp; od tej chwili kursor ma poprawny offset 0.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:20",
"snapshot_ref": "task04.reset.store",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.reset.assign", "align": "center"},
"annotations": [
{"id": "ann.reset.store", "anchor_ref": "asm.task04.reset.store-allocp", "label": "allocp ← allocbuf", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a4,1168(a5)", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x80001150",
"code": {
"source": "allocp = allocbuf;",
"source_ref": "task04_address_arithmetic_alloc.c:20",
"assembly": "0x8000114c sw a4,1168(a5) # allocp\n0x80001150 addi zero,zero,0 # PC po zapisie",
"note": "PC przesunął się za sw, więc pamięć pod symbolem allocp zawiera już 0x80001450."
},
"registers": [{"name": "sp", "value": "0x800fffc0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001254"}, {"name": "a0", "value": "0x800014b0"}, {"name": "a4", "value": "0x80001450"}, {"name": "a5", "value": "0x80001000"}],
"frame": {"name": "allocator_reset", "sp": "0x800fffc0", "fp": "0x800fffd0", "size_bytes": 16, "fields": [{"name": "saved s0", "address": "0x800fffc8", "value": "0x800ffff0", "state": "saved"}, {"name": "saved ra", "address": "0x800fffcc", "value": "0x80001254", "state": "saved"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001450"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001450", "offset": 0, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Pomiar pamięci pod 0x80001490 daje 0x80001450, więc allocp - allocbuf = 0."
}
},
{
"id": "reset-return",
"number": 5,
"label": "return void",
"svg_label": "05",
"progress_id": "UML04-S05",
"description": "Ramka allocator_reset zniknęła, sp wrócił do ramki main, a statyczny allocp zachował offset 0.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:21",
"snapshot_ref": "task04.reset.return",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.main.alloc5-call", "align": "center"},
"annotations": [
{"id": "ann.reset.return", "anchor_ref": "asm.task04.main.alloc5-arg", "label": "powrót do main", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a0,5", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x80001254",
"code": {
"source": "}",
"source_ref": "task04_address_arithmetic_alloc.c:21",
"assembly": "0x80001154 lw ra,12(sp)\n0x80001158 lw s0,8(sp)\n0x8000115c addi sp,sp,16\n0x80001160 ret\n0x80001254 li a0,5",
"note": "Po ret aktywna jest ponownie ramka main; następna instrukcja przygotuje argument pierwszego przydziału."
},
"registers": [{"name": "sp", "value": "0x800fffd0"}, {"name": "s0/fp", "value": "0x800ffff0"}, {"name": "ra", "value": "0x80001254"}, {"name": "a0", "value": "0x800014b0", "note": "void: a0 nie jest wynikiem resetu"}, {"name": "a4", "value": "0x80001450"}, {"name": "a5", "value": "0x80001000"}],
"frame": {"name": "main", "sp": "0x800fffd0", "fp": "0x800ffff0", "size_bytes": 32, "fields": [{"name": "first", "address": "0x800fffdc", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "second", "address": "0x800fffd8", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "out_of_memory", "address": "0x800fffd4", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "zero_request", "address": "0x800fffd0", "value": "raw 0x00000000", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001450"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001450", "offset": 0, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Powrót usuwa tylko ramkę aktywacji. allocbuf i allocp w .bss pozostają dostępne przez cały czas działania programu."
}
}
]
},
{
"id": "alloc-5",
"label": "ALLOC(5)",
"description": "Pierwsza ramka alloc_local: n=5, used=0, result=allocbuf i końcowy offset 5.",
"svg_label": "ALLOC(5)",
"steps": [
{
"id": "alloc5-call",
"number": 6,
"label": "first = alloc_local(5)",
"svg_label": "06",
"progress_id": "UML04-S06",
"description": "Po instrukcji li argument 5 jest widoczny w a0, a PC stoi przed jalr; ramka main nadal zawiera cztery lokalne wskaźniki.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:64",
"snapshot_ref": "task04.alloc5.enter",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.main.alloc5-call", "align": "center"},
"annotations": [
{"id": "ann.alloc5.source", "anchor_ref": "src.task04.main.alloc5-call", "label": "1 · wywołanie", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "first = alloc_local(5);", "padding_cells": 1}},
{"id": "ann.alloc5.asm", "anchor_ref": "asm.task04.main.alloc5-arg", "label": "2 · li / jal", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "main+24 li a0,5", "padding_cells": 1}},
{"id": "ann.alloc5.a0", "anchor_ref": "reg.a0", "label": "3 · a0 = 5", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a0 0x00000005", "padding_cells": 1}},
{"id": "ann.alloc5.arena", "anchor_ref": "memory.allocbuf", "label": "4 · arena", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "allocbuf[0]", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x80001258",
"code": {
"source": "first = alloc_local(5);",
"source_ref": "task04_address_arithmetic_alloc.c:64",
"assembly": "0x80001254 li a0,5\n0x80001258 auipc ra,0x0 # PC\n0x8000125c jalr ra,-244(ra) # alloc_local",
"note": "To stan tuż przed wywołaniem: li ustawiło a0=5, ale prolog alloc_local jeszcze się nie wykonał."
},
"registers": [{"name": "sp", "value": "0x800fffd0"}, {"name": "s0/fp", "value": "0x800ffff0"}, {"name": "ra", "value": "0x80001254"}, {"name": "a0", "value": "0x00000005", "note": "pierwszy argument RV32 ABI"}, {"name": "a4", "value": "0x80001450"}, {"name": "a5", "value": "0x80001000"}],
"frame": {"name": "main", "sp": "0x800fffd0", "fp": "0x800ffff0", "size_bytes": 32, "fields": [{"name": "zero_request", "address": "0x800fffd0", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "out_of_memory", "address": "0x800fffd4", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "second", "address": "0x800fffd8", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "first", "address": "0x800fffdc", "value": "raw 0x00000000", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001450"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001450", "offset": 0, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Przed jalr aktywna jest wyłącznie ramka main: sp=0x800fffd0, a0=5 i allocp nadal wskazuje allocbuf+0."
}
},
{
"id": "alloc5-read-cursor",
"number": 7,
"label": "odczytaj bieżący kursor",
"svg_label": "07",
"progress_id": "UML04-S07",
"description": "Stabilny stan po odczycie pokazuje a5=0x80001450, zgodne z wartością zapisaną pod symbolem allocp.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:28",
"snapshot_ref": "task04.alloc5.cursor",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.alloc.null-check", "align": "center"},
"annotations": [
{"id": "ann.alloc5.cursor-read", "anchor_ref": "asm.task04.alloc.load-allocp", "label": "allocp", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a5,1168(a5)", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x8000118c",
"code": {
"source": "if (allocp == NULL) {\n return NULL;\n}",
"source_ref": "task04_address_arithmetic_alloc.c:28-30",
"assembly": "0x80001178 lui a5,0x80001\n0x8000117c lw a5,1168(a5) # allocp\n0x80001180 bne a5,zero,0x8000118c\n0x8000118c lui a5,0x80001",
"note": "Użyto stabilnego stanu po gałęzi: a5 zawiera architektonicznie zatwierdzony odczyt allocp."
},
"registers": [{"name": "sp", "value": "0x800fffa0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001260"}, {"name": "a0", "value": "0x00000005"}, {"name": "a4", "value": "0x80001450"}, {"name": "a5", "value": "0x80001450", "note": "odczytana wartość allocp"}],
"frame": {"name": "alloc_local", "sp": "0x800fffa0", "fp": "0x800fffd0", "size_bytes": 48, "fields": [{"name": "n", "address": "0x800fffac", "value": "5", "state": "initialised"}, {"name": "used", "address": "0x800fffbc", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "result", "address": "0x800fffb8", "value": "raw 0x00000000", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001450"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001450", "offset": 0, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Hazard3 tb_gdb pokazuje wartość ładowania dopiero w stabilnym stanie po gałęzi; dlatego snapshot jest przypięty do PC 0x8000118c, a nie do chwilowego stanu potoku na 0x80001180."
}
},
{
"id": "alloc5-cursor-result",
"number": 8,
"label": "&allocbuf[0]",
"svg_label": "08",
"progress_id": "UML04-S08",
"description": "Wynik logicznego odczytu kursora to początek areny; a5 i pamięć allocp zawierają ten sam adres.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:33",
"snapshot_ref": "task04.alloc5.cursor",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.alloc.used", "align": "center"},
"annotations": [
{"id": "ann.alloc5.cursor-value", "anchor_ref": "reg.a5", "label": "&allocbuf[0]", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a5 0x80001450", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x8000118c",
"code": {
"source": "used = allocp - allocbuf;",
"source_ref": "task04_address_arithmetic_alloc.c:33",
"assembly": "a5 = 0x80001450 # wartość allocp\npc = 0x8000118c # stabilny stan po lw/bne",
"note": "Strzałka zwrotna UML nazywa wartość odczytaną w kroku 07; nie wykonuje dodatkowej instrukcji."
},
"registers": [{"name": "sp", "value": "0x800fffa0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001260"}, {"name": "a0", "value": "0x00000005"}, {"name": "a4", "value": "0x80001450"}, {"name": "a5", "value": "0x80001450"}],
"frame": {"name": "alloc_local", "sp": "0x800fffa0", "fp": "0x800fffd0", "size_bytes": 48, "fields": [{"name": "n", "address": "0x800fffac", "value": "5", "state": "initialised"}, {"name": "used", "address": "0x800fffbc", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "result", "address": "0x800fffb8", "value": "raw 0x00000000", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001450"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001450", "offset": 0, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Strzałka zwrotna nie dodaje instrukcji; wiąże wartość a5=0x80001450 z pojęciem pierwszego wolnego bajtu."
}
},
{
"id": "alloc5-read-buffer-address",
"number": 9,
"label": "odczytaj adres początku areny",
"svg_label": "09",
"progress_id": "UML04-S09",
"description": "Po zbudowaniu adresu allocbuf oba rejestry robocze a4 i a5 mają 0x80001450.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:33",
"snapshot_ref": "task04.alloc5.buffer-address",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.alloc.used", "align": "center"},
"annotations": [
{"id": "ann.alloc5.buffer-address", "anchor_ref": "asm.task04.alloc.address-allocbuf", "label": "&allocbuf[0]", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a5,a5,1104", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x8000119c",
"code": {
"source": "used = allocp - allocbuf;",
"source_ref": "task04_address_arithmetic_alloc.c:33",
"assembly": "0x8000118c lui a5,0x80001\n0x80001190 lw a4,1168(a5) # allocp\n0x80001194 lui a5,0x80001\n0x80001198 addi a5,a5,1104 # allocbuf\n0x8000119c sub a5,a4,a5",
"note": "Tuż przed sub oba operandy mają adres 0x80001450."
},
"registers": [{"name": "sp", "value": "0x800fffa0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001260"}, {"name": "a0", "value": "0x00000005"}, {"name": "a4", "value": "0x80001450", "note": "allocp"}, {"name": "a5", "value": "0x80001450", "note": "allocbuf"}],
"frame": {"name": "alloc_local", "sp": "0x800fffa0", "fp": "0x800fffd0", "size_bytes": 48, "fields": [{"name": "n", "address": "0x800fffac", "value": "5", "state": "initialised"}, {"name": "used", "address": "0x800fffbc", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "result", "address": "0x800fffb8", "value": "raw 0x00000000", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001450"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001450", "offset": 0, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Następna instrukcja odejmie a5 od a4. Równe adresy przewidują wynik used=0."
}
},
{
"id": "alloc5-buffer-address-result",
"number": 10,
"label": "&allocbuf[0]",
"svg_label": "10",
"progress_id": "UML04-S10",
"description": "Początek areny używany w odejmowaniu adresów ma adres 0x80001450.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:33",
"snapshot_ref": "task04.alloc5.buffer-address",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.alloc.used", "align": "center"},
"annotations": [
{"id": "ann.alloc5.buffer-result", "anchor_ref": "reg.a5", "label": "początek areny", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a5 0x80001450", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x8000119c",
"code": {
"source": "used = allocp - allocbuf;",
"source_ref": "task04_address_arithmetic_alloc.c:33",
"assembly": "a4 = 0x80001450 # allocp\na5 = 0x80001450 # &allocbuf[0]\npc = 0x8000119c # przed sub",
"note": "Strzałka zwrotna UML eksponuje drugi operand odejmowania i dzieli stan z krokiem 09."
},
"registers": [{"name": "sp", "value": "0x800fffa0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001260"}, {"name": "a0", "value": "0x00000005"}, {"name": "a4", "value": "0x80001450"}, {"name": "a5", "value": "0x80001450"}],
"frame": {"name": "alloc_local", "sp": "0x800fffa0", "fp": "0x800fffd0", "size_bytes": 48, "fields": [{"name": "n", "address": "0x800fffac", "value": "5", "state": "initialised"}, {"name": "used", "address": "0x800fffbc", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "result", "address": "0x800fffb8", "value": "raw 0x00000000", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001450"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001450", "offset": 0, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Krok 10 jest odpowiedzią logiczną allocbuf i dzieli snapshot z krokiem 09."
}
},
{
"id": "alloc5-used",
"number": 11,
"label": "used = allocp - allocbuf = 0",
"svg_label": "11",
"progress_id": "UML04-S11",
"description": "Odejmowanie adresów dało 0, a wynik został zapisany do pola used w ramce.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:33",
"snapshot_ref": "task04.alloc5.used",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.alloc.used", "align": "center"},
"annotations": [
{"id": "ann.alloc5.used", "anchor_ref": "src.task04.alloc.used", "label": "used = 0", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "used = allocp - allocbuf;", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x800011a4",
"code": {
"source": "used = allocp - allocbuf;",
"source_ref": "task04_address_arithmetic_alloc.c:33",
"assembly": "0x8000119c sub a5,a4,a5\n0x800011a0 sw a5,-20(s0) # used\n0x800011a4 lw a5,-36(s0) # n",
"note": "PC znajduje się za zapisem, dlatego slot used i a5 z wyniku odejmowania potwierdzają offset 0."
},
"registers": [{"name": "sp", "value": "0x800fffa0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001260"}, {"name": "a0", "value": "0x00000005"}, {"name": "a4", "value": "0x80001450"}, {"name": "a5", "value": "0x00000000", "note": "wynik odejmowania"}],
"frame": {"name": "alloc_local", "sp": "0x800fffa0", "fp": "0x800fffd0", "size_bytes": 48, "fields": [{"name": "n", "address": "0x800fffac", "value": "5", "state": "initialised"}, {"name": "used", "address": "0x800fffbc", "value": "0", "state": "initialised"}, {"name": "result", "address": "0x800fffb8", "value": "raw 0x00000000", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001450"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001450", "offset": 0, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Pole used pod 0x800fffbc zawiera już 0. Pole result nadal nie ma wartości języka C."
}
},
{
"id": "alloc5-commit",
"number": 12,
"label": "result = allocp; allocp += 5",
"svg_label": "12",
"progress_id": "UML04-S12",
"description": "result zachował stary kursor 0x80001450, a zapis do allocp przesunął kursor na 0x80001455.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:39-40",
"snapshot_ref": "task04.alloc5.commit",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.alloc.commit", "align": "center"},
"annotations": [
{"id": "ann.alloc5.commit", "anchor_ref": "src.task04.alloc.commit", "label": "offset 0 → 5", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "allocp += n;", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x80001200",
"code": {
"source": "result = allocp;\nallocp += n;",
"source_ref": "task04_address_arithmetic_alloc.c:39-40",
"assembly": "0x800011e4 sw a5,-24(s0) # result\n0x800011ec lw a4,1168(a5) # allocp\n0x800011f0 lw a5,-36(s0) # n\n0x800011f4 add a4,a4,a5\n0x800011fc sw a4,1168(a5) # allocp\n0x80001200 lw a5,-24(s0) # result",
"note": "Stary kursor trafia do result, natomiast suma allocp+n zostaje zapisana jako nowy kursor."
},
"registers": [{"name": "sp", "value": "0x800fffa0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001260"}, {"name": "a0", "value": "0x00000005"}, {"name": "a4", "value": "0x80001455", "note": "nowy kursor"}, {"name": "a5", "value": "0x80001000"}],
"frame": {"name": "alloc_local", "sp": "0x800fffa0", "fp": "0x800fffd0", "size_bytes": 48, "fields": [{"name": "n", "address": "0x800fffac", "value": "5", "state": "initialised"}, {"name": "used", "address": "0x800fffbc", "value": "0", "state": "initialised"}, {"name": "result", "address": "0x800fffb8", "value": "0x80001450", "state": "initialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001455"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001455", "offset": 5, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Przydział rezerwuje pięć bajtów bez zapisywania ich treści. Dlatego offset zmienia się na 5, lecz podgląd areny nadal zawiera zera."
}
},
{
"id": "alloc5-return",
"number": 13,
"label": "return first = &allocbuf[0]",
"svg_label": "13",
"progress_id": "UML04-S13",
"description": "Po powrocie a0 i lokalne first mają 0x80001450; ramka alloc_local zniknęła, a allocp pozostał na offsecie 5.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:41",
"snapshot_ref": "task04.alloc5.return",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.main.alloc5-call", "align": "center"},
"annotations": [
{"id": "ann.alloc5.return", "anchor_ref": "src.task04.main.alloc5-call", "label": "first = &allocbuf[0]", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "first = alloc_local(5);", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x80001264",
"code": {
"source": "return result;\n/* main: */ first = alloc_local(5);",
"source_ref": "task04_address_arithmetic_alloc.c:41,64",
"assembly": "0x80001200 lw a5,-24(s0) # result\n0x80001204 mv a0,a5\n0x80001214 ret\n0x80001260 sw a0,-20(s0) # first\n0x80001264 li a0,7",
"note": "Wartość wróciła w a0 i została zapisana do lokalnej first w ramce main."
},
"registers": [{"name": "sp", "value": "0x800fffd0"}, {"name": "s0/fp", "value": "0x800ffff0"}, {"name": "ra", "value": "0x80001260"}, {"name": "a0", "value": "0x80001450", "note": "wartość zwrotna"}, {"name": "a4", "value": "0x80001455"}, {"name": "a5", "value": "0x80001450"}],
"frame": {"name": "main", "sp": "0x800fffd0", "fp": "0x800ffff0", "size_bytes": 32, "fields": [{"name": "first", "address": "0x800fffdc", "value": "0x80001450", "state": "initialised"}, {"name": "second", "address": "0x800fffd8", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "out_of_memory", "address": "0x800fffd4", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "zero_request", "address": "0x800fffd0", "value": "raw 0x00000000", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001455"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001455", "offset": 5, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "first jest pierwszą zainicjalizowaną lokalną main. second oraz dwa późniejsze wyniki nadal są nieustalone."
}
}
]
},
{
"id": "alloc-7",
"label": "ALLOC(7)",
"description": "Druga ramka alloc_local: n=7, used=5, result=allocbuf+5 i końcowy offset 12.",
"svg_label": "ALLOC(7)",
"steps": [
{
"id": "alloc7-call",
"number": 14,
"label": "second = alloc_local(7)",
"svg_label": "14",
"progress_id": "UML04-S14",
"description": "Po instrukcji li argument 7 jest widoczny w a0, first jest już zapisany w ramce main, a PC stoi przed drugim jalr.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:65",
"snapshot_ref": "task04.alloc7.enter",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.main.alloc7-call", "align": "center"},
"annotations": [
{"id": "ann.alloc7.source", "anchor_ref": "src.task04.main.alloc7-call", "label": "alloc(7)", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "second = alloc_local(7);", "padding_cells": 1}},
{"id": "ann.alloc7.a0", "anchor_ref": "reg.a0", "label": "a0 = 7", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a0 0x00000007", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x80001268",
"code": {
"source": "second = alloc_local(7);",
"source_ref": "task04_address_arithmetic_alloc.c:65",
"assembly": "0x80001264 li a0,7\n0x80001268 auipc ra,0x0 # PC\n0x8000126c jalr ra,-260(ra) # alloc_local",
"note": "To stan przed drugim wywołaniem: pierwsze zwróciło allocbuf+0 i przesunęło kursor do offsetu 5."
},
"registers": [{"name": "sp", "value": "0x800fffd0"}, {"name": "s0/fp", "value": "0x800ffff0"}, {"name": "ra", "value": "0x80001260"}, {"name": "a0", "value": "0x00000007"}, {"name": "a4", "value": "0x80001455"}, {"name": "a5", "value": "0x80001450"}],
"frame": {"name": "main", "sp": "0x800fffd0", "fp": "0x800ffff0", "size_bytes": 32, "fields": [{"name": "zero_request", "address": "0x800fffd0", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "out_of_memory", "address": "0x800fffd4", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "second", "address": "0x800fffd8", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "first", "address": "0x800fffdc", "value": "0x80001450", "state": "initialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001455"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001455", "offset": 5, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Ramka main pokazuje już first=0x80001450, lecz second pozostaje niezainicjalizowany aż do powrotu drugiego alloc_local."
}
},
{
"id": "alloc7-read-cursor",
"number": 15,
"label": "odczytaj bieżący kursor",
"svg_label": "15",
"progress_id": "UML04-S15",
"description": "Stabilny odczyt allocp daje 0x80001455, czyli pięć bajtów za początkiem areny.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:28",
"snapshot_ref": "task04.alloc7.cursor",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.alloc.null-check", "align": "center"},
"annotations": [
{"id": "ann.alloc7.cursor-read", "anchor_ref": "asm.task04.alloc.load-allocp", "label": "allocbuf + 5", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a5,1168(a5)", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x8000118c",
"code": {
"source": "if (allocp == NULL) {\n return NULL;\n}",
"source_ref": "task04_address_arithmetic_alloc.c:28-30",
"assembly": "0x80001178 lui a5,0x80001\n0x8000117c lw a5,1168(a5) # allocp\n0x80001180 bne a5,zero,0x8000118c\n0x8000118c lui a5,0x80001",
"note": "Stabilny stan po gałęzi zawiera bieżący kursor 0x80001455, czyli allocbuf+5."
},
"registers": [{"name": "sp", "value": "0x800fffa0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001270"}, {"name": "a0", "value": "0x00000007"}, {"name": "a4", "value": "0x80001455"}, {"name": "a5", "value": "0x80001455", "note": "odczytana wartość allocp"}],
"frame": {"name": "alloc_local", "sp": "0x800fffa0", "fp": "0x800fffd0", "size_bytes": 48, "fields": [{"name": "n", "address": "0x800fffac", "value": "7", "state": "initialised"}, {"name": "used", "address": "0x800fffbc", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "result", "address": "0x800fffb8", "value": "raw 0x80001450", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001455"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001455", "offset": 5, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "a5 i pamięć pod symbolem allocp są zgodne. Snapshot używa stabilnego PC 0x8000118c z tego samego powodu co krok 07."
}
},
{
"id": "alloc7-cursor-result",
"number": 16,
"label": "&allocbuf[5]",
"svg_label": "16",
"progress_id": "UML04-S16",
"description": "Wynik odczytu kursora to adres 0x80001455, czyli allocbuf + 5.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:33",
"snapshot_ref": "task04.alloc7.cursor",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.alloc.used", "align": "center"},
"annotations": [
{"id": "ann.alloc7.cursor-value", "anchor_ref": "reg.a5", "label": "&allocbuf[5]", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "a5 0x80001455", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x8000118c",
"code": {
"source": "used = allocp - allocbuf;",
"source_ref": "task04_address_arithmetic_alloc.c:33",
"assembly": "a5 = 0x80001455 # wartość allocp\npc = 0x8000118c # stabilny stan po lw/bne",
"note": "Strzałka zwrotna UML interpretuje kursor jako &allocbuf[5] i nie dodaje instrukcji."
},
"registers": [{"name": "sp", "value": "0x800fffa0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001270"}, {"name": "a0", "value": "0x00000007"}, {"name": "a4", "value": "0x80001455"}, {"name": "a5", "value": "0x80001455"}],
"frame": {"name": "alloc_local", "sp": "0x800fffa0", "fp": "0x800fffd0", "size_bytes": 48, "fields": [{"name": "n", "address": "0x800fffac", "value": "7", "state": "initialised"}, {"name": "used", "address": "0x800fffbc", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "result", "address": "0x800fffb8", "value": "raw 0x80001450", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001455"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001455", "offset": 5, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Krok 16 interpretuje adres: 0x80001455 - 0x80001450 = 5."
}
},
{
"id": "alloc7-used",
"number": 17,
"label": "used = allocp - allocbuf = 5",
"svg_label": "17",
"progress_id": "UML04-S17",
"description": "Po odejmowaniu a5=5 i slot used=5 dowodzą, że pierwszy przydział zajął pięć bajtów.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:33",
"snapshot_ref": "task04.alloc7.used",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.alloc.used", "align": "center"},
"annotations": [
{"id": "ann.alloc7.used", "anchor_ref": "src.task04.alloc.used", "label": "used = 5", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "used = allocp - allocbuf;", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x800011a4",
"code": {
"source": "used = allocp - allocbuf;",
"source_ref": "task04_address_arithmetic_alloc.c:33",
"assembly": "0x80001190 lw a4,1168(a5) # allocp\n0x80001198 addi a5,a5,1104 # allocbuf\n0x8000119c sub a5,a4,a5\n0x800011a0 sw a5,-20(s0) # used\n0x800011a4 lw a5,-36(s0) # n",
"note": "Różnica adresów 0x800014550x80001450 daje pięć bajtów i trafia do pola used."
},
"registers": [{"name": "sp", "value": "0x800fffa0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001270"}, {"name": "a0", "value": "0x00000007"}, {"name": "a4", "value": "0x80001455"}, {"name": "a5", "value": "0x00000005"}],
"frame": {"name": "alloc_local", "sp": "0x800fffa0", "fp": "0x800fffd0", "size_bytes": 48, "fields": [{"name": "n", "address": "0x800fffac", "value": "7", "state": "initialised"}, {"name": "used", "address": "0x800fffbc", "value": "5", "state": "initialised"}, {"name": "result", "address": "0x800fffb8", "value": "raw 0x80001450", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x80001455"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x80001455", "offset": 5, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "used jest już zainicjalizowane. result wciąż pokazuje jedynie surową pozostałość w slocie i pozostaje oznaczone znakiem zapytania."
}
},
{
"id": "alloc7-commit",
"number": 18,
"label": "result = allocp; allocp += 7",
"svg_label": "18",
"progress_id": "UML04-S18",
"description": "result przyjmuje 0x80001455, a allocp przesuwa się o siedem bajtów do 0x8000145c, czyli offsetu 12.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:39-40",
"snapshot_ref": "task04.alloc7.commit",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.alloc.commit", "align": "center"},
"annotations": [
{"id": "ann.alloc7.commit", "anchor_ref": "src.task04.alloc.commit", "label": "offset 5 → 12", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "allocp += n;", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x80001200",
"code": {
"source": "result = allocp;\nallocp += n;",
"source_ref": "task04_address_arithmetic_alloc.c:39-40",
"assembly": "0x800011e4 sw a5,-24(s0) # result\n0x800011ec lw a4,1168(a5) # allocp\n0x800011f0 lw a5,-36(s0) # n\n0x800011f4 add a4,a4,a5\n0x800011fc sw a4,1168(a5) # allocp\n0x80001200 lw a5,-24(s0) # result",
"note": "Stary kursor 0x80001455 staje się result, a zapis 0x8000145c ustala końcowy offset 12."
},
"registers": [{"name": "sp", "value": "0x800fffa0"}, {"name": "s0/fp", "value": "0x800fffd0"}, {"name": "ra", "value": "0x80001270"}, {"name": "a0", "value": "0x00000007"}, {"name": "a4", "value": "0x8000145c", "note": "nowy kursor"}, {"name": "a5", "value": "0x80001000"}],
"frame": {"name": "alloc_local", "sp": "0x800fffa0", "fp": "0x800fffd0", "size_bytes": 48, "fields": [{"name": "n", "address": "0x800fffac", "value": "7", "state": "initialised"}, {"name": "used", "address": "0x800fffbc", "value": "5", "state": "initialised"}, {"name": "result", "address": "0x800fffb8", "value": "0x80001455", "state": "initialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x8000145c"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x8000145c", "offset": 12, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Stan pamięci potwierdza 5 + 7 = 12. Arena nadal zawiera zera, ponieważ sam alokator przesuwa kursor, ale nie inicjalizuje danych użytkownika."
}
},
{
"id": "alloc7-return",
"number": 19,
"label": "return second = &allocbuf[5]",
"svg_label": "19",
"progress_id": "UML04-S19",
"description": "Po powrocie second=0x80001455, first=0x80001450, a statyczny allocp pozostaje na 0x8000145c.",
"code_ref": "src/tasks/task04_address_arithmetic_alloc.c:41",
"snapshot_ref": "task04.alloc7.return",
"view": {
"connection_ref": "task04.debug.auto",
"layout": "termdebug.source-asm-dashboard-memory",
"reveal": {"anchor_ref": "src.task04.main.alloc7-call", "align": "center"},
"annotations": [
{"id": "ann.alloc7.return", "anchor_ref": "src.task04.main.alloc7-call", "label": "second = &allocbuf[5]", "tone": "danger", "shape": "outline", "anchor": {"kind": "screen-text", "text": "second = alloc_local(7);", "padding_cells": 1}}
]
},
"snapshot": {
"pc": "0x80001274",
"code": {
"source": "return result;\n/* main: */ second = alloc_local(7);",
"source_ref": "task04_address_arithmetic_alloc.c:41,65",
"assembly": "0x80001200 lw a5,-24(s0) # result\n0x80001204 mv a0,a5\n0x80001214 ret\n0x80001270 sw a0,-24(s0) # second\n0x80001274 li a0,64",
"note": "Wartość 0x80001455 wróciła w a0 i została zapisana do second; kolejna instrukcja rozpoczyna już test braku pamięci."
},
"registers": [{"name": "sp", "value": "0x800fffd0"}, {"name": "s0/fp", "value": "0x800ffff0"}, {"name": "ra", "value": "0x80001270"}, {"name": "a0", "value": "0x80001455", "note": "wartość zwrotna"}, {"name": "a4", "value": "0x8000145c"}, {"name": "a5", "value": "0x80001455"}],
"frame": {"name": "main", "sp": "0x800fffd0", "fp": "0x800ffff0", "size_bytes": 32, "fields": [{"name": "first", "address": "0x800fffdc", "value": "0x80001450", "state": "initialised"}, {"name": "second", "address": "0x800fffd8", "value": "0x80001455", "state": "initialised"}, {"name": "out_of_memory", "address": "0x800fffd4", "value": "raw 0x00000000", "state": "uninitialised"}, {"name": "zero_request", "address": "0x800fffd0", "value": "raw 0x00000000", "state": "uninitialised"}]},
"memory": {"items": [{"name": "allocbuf", "address": "0x80001450", "value": "char[64]"}, {"name": "allocp", "address": "0x80001490", "value": "0x8000145c"}], "arena": {"base": "0x80001450", "size_bytes": 64, "cursor": "0x8000145c", "offset": 12, "bytes": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"}},
"description": "Ramka alloc_local zniknęła. Ramka main zawiera oba wyniki, a stan alokatora w .bss zachowuje offset 12."
}
}
]
}
]
}
},
{
"path": "assets/task04-first-allocation-annotated.png",
"caption": "KOD + DEBUG — zatrzymanie przed pierwszym przydziałem: (1) wywołanie w C, (2) li/jal w RISC-V, (3) argument n=5 w a0, (4) allocbuf przed zapisem. Połącz te cztery miejsca z komunikatem alloc(5) na UML.",
"label": "fig:task04-first-allocation",
"alt": "Termdebug Task04: GDB Dashboard po lewej, kod C i listing RISC-V po prawej oraz pusty allocbuf",
"kind": "screenshot",
"width": 1.0
}
]
}
],
"tasks": {
"task01": {
"prompt_tex": "\\textbf{Adres, \\texttt{\\&} i dereferencja.} Przewidź i zmierz wartości \\texttt{x}, \\texttt{y}, \\texttt{z[0]}, \\texttt{z[1]} oraz relację \\texttt{iq == \\&z[0]}. Oczekiwane: \\texttt{x=0 y=1 z0=7 z1=12 same=1}.",
"criterion": "Wartości są zgodne, iq wskazuje z[0], a g_task01_pass ma wartość 1.",
"educational_requirement_refs": ["PTR.WE01", "PTR.WE02"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01", "PTR.EK02"],
"assessment_criterion_ref": "PTR.KW01"
},
"task02": {
"prompt_tex": "\\textbf{Wskaźnik jako argument funkcji.} Prześledź \\texttt{swap\\_int} i \\texttt{parse\\_int}; porównaj ramkę funkcji z ramką \\texttt{main} oraz początkowe argumenty w \\texttt{a0/a1}. Oczekiwane: \\texttt{a=19 b=7 parsed=-42 status=1}.",
"criterion": "Zmiana obiektów wywołującego i przesunięcie wskaźnika wejściowego są wyjaśnione; g_task02_pass = 1.",
"educational_requirement_refs": ["PTR.WE01", "PTR.WE02"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01", "PTR.EK02"],
"assessment_criterion_ref": "PTR.KW01"
},
"task03": {
"prompt_tex": "\\textbf{Tablica i arytmetyka wskaźnika.} Wykaż równoważność \\texttt{a[i]}, \\texttt{*(a+i)} i \\texttt{pa[i]}; zmierz różnicę adresów w elementach i bajtach. Oczekiwane: \\texttt{first=3 p2=8 i2=8 sum=42 len=5}.",
"criterion": "Wyniki i skala indeksu są wyjaśnione; g_task03_pass = 1.",
"educational_requirement_refs": ["PTR.WE01", "PTR.WE02"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01", "PTR.EK02"],
"assessment_criterion_ref": "PTR.KW01"
},
"task04": {
"title": "K&R 5.4 -- Linear Memory Allocator",
"uuid": "98dbe323-c624-53d6-9fe2-4ee688c44b38",
"prompt_tex": "\\textbf{K\\&R 5.4 -- czysty alokator liniowy typu bump.} Zrealizuj wyłącznie reset całej areny oraz przydział przesuwający jeden kursor. Przewidź sekwencję reset $\\rightarrow$ alloc(5) $\\rightarrow$ alloc(7), a następnie potwierdź ją w kodzie, ABI RV32 i pamięci.",
"criterion": "Potwierdzono first=allocbuf+0, second=allocbuf+5 i allocp=allocbuf+12, bajty A B x y, sumę 372, odmowę braku pamięci i żądania zerowego oraz różnicę między allocp i sp.",
"conclusion_tex": "Ten alokator nie obsługuje pojedynczego \\texttt{free}; pamięć odzyskuje się przez reset całej areny. Dowolne zwalnianie bloków pojawi się później przy strukturach i \\texttt{heap\\_4}.",
"flow": [
{
"kind": "block",
"id": "schema",
"title": "SCHEMAT — przewidź stan areny",
"content_tex": "Arena \\texttt{allocbuf} ma 64 bajty, a \\texttt{allocp} wskazuje pierwszy wolny bajt. Stan opisuje offset \\texttt{allocp - allocbuf}; bezwzględny adres nie jest częścią wyniku.",
"steps": [
{
"id": "predict-state",
"title": "Zaznacz na Rys. 1 granice przydziałów i zapisz trzy offsety.",
"content_tex": "Obserwowalny wniosek przed uruchomieniem: reset daje 0, \\texttt{alloc(5)} daje 5, a \\texttt{alloc(7)} daje 12."
},
{
"id": "predict-results",
"title": "Przypisz wyniki do początku każdego przydzielonego obszaru.",
"content_tex": "Oczekiwany stan: \\texttt{first = allocbuf + 0}, \\texttt{second = allocbuf + 5}, \\texttt{allocp = allocbuf + 12}."
}
]
},
{
"kind": "block",
"id": "uml",
"title": "UML — połącz wywołania z czasem życia danych",
"content_tex": "Rys. 2 rozdziela statyczne \\texttt{allocbuf/allocp} od logicznych ramek \\texttt{main()} i \\texttt{alloc\\_local(n)}. Paski aktywacji pokazują czas wykonywania funkcji, nie osobny obszar alokatora.",
"steps": [
{
"id": "classify-storage",
"title": "Wybierz blok model i rozdziel .bss, ramkę main() oraz ramkę alloc_local(n).",
"content_tex": "Wniosek: \\texttt{allocbuf/allocp} istnieją przez cały program; \\texttt{first}, \\texttt{second}, \\texttt{out\\_of\\_memory}, \\texttt{zero\\_request} oraz \\texttt{n}, \\texttt{used}, \\texttt{result} mają automatyczny czas życia. Przy \\texttt{-O0} debugger wiąże ramkę z \\texttt{sp/s0}, ale kompilator może przechować wartość w rejestrze."
},
{
"id": "follow-states",
"title": "Przejdź przez pięć stanów UML i dla każdego zapisz jeden sprawdzalny wniosek.",
"content_tex": "Użyj zakładek: model/notacja, reset, alloc(5), alloc(7), kod/debug. Nie opisuj każdej strzałki osobno; zakończ stan konkretną wartością, offsetem albo czasem życia."
}
]
},
{
"kind": "block",
"id": "code-debug",
"title": "KOD + DEBUG — sprawdź przewidywanie",
"content_tex": "Implementacja ma dwie operacje: \\texttt{allocator\\_reset()} oraz \\texttt{alloc\\_local(n)}. Przydział zachowuje stary kursor jako wynik, sprawdza granicę areny i przesuwa kursor o \\texttt{n} bajtów.",
"steps": [
{
"id": "implement-bump",
"title": "Uzupełnij reset i dodatni przydział mieszczący się w arenie.",
"content_tex": "Wniosek z kodu: wynik jest starym \\texttt{allocp}, a nowy \\texttt{allocp} wskazuje pierwszy wolny bajt; żądanie zerowe i brak miejsca zwracają \\texttt{NULL} bez zmiany offsetu 12."
},
{
"id": "run-native",
"title": "Uruchom stemctl test native-amd64 inf pointers 4 i porównaj z przewidywaniem.",
"content_tex": "Dowód kończy się wynikiem \\texttt{first=0 second=5 allocp=12 sum=372 oom=1 zero=1 pass=1}."
},
{
"id": "inspect-hazard3",
"title": "Na Rys. 3 i w Hazard3 połącz C, li/jal, a0, sp/s0 oraz allocbuf.",
"content_tex": "Sprawdź \\texttt{a0=5}, ramkę bieżącej funkcji przy \\texttt{sp/s0}, \\texttt{first-allocbuf}, \\texttt{second-allocbuf}, \\texttt{allocp-allocbuf} i \\texttt{x/16bx allocbuf}. Wniosek: \\texttt{allocp} opisuje arenę w .bss, a \\texttt{sp} ramkę stosu."
},
{
"id": "measure-rp2350",
"title": "Na zajęciach powtórz ten sam pomiar na RP2350.",
"content_tex": "Przez \\texttt{stemctl probe list} wybierz urządzenie. Wniosek ma zachować offsety i znaczenie zmiennych mimo innych bezwzględnych adresów."
}
]
}
],
"educational_requirement_refs": ["PTR.WE02", "PTR.WE03"],
"learning_effect_refs": ["PTR.EN01", "PTR.EN02", "PTR.EK02", "PTR.EK03"],
"assessment_criterion_ref": "PTR.KW02"
},
"task05": {
"prompt_tex": "\\textbf{K\\&R 5.5 -- wskaźniki znakowe.} Przejdź po buforze do kończącego bajtu NUL i zwizualizuj bajty bufora.",
"criterion": "Granica napisu i ruch wskaźnika są poprawnie wskazane.",
"educational_requirement_refs": ["PTR.WE01", "PTR.WE02"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01", "PTR.EK02"],
"assessment_criterion_ref": "PTR.KW01"
},
"task06": {
"prompt_tex": "\\textbf{K\\&R 5.6 -- tablica wskaźników.} Posortuj przez zamianę adresów bez kopiowania treści napisów.",
"criterion": "Uczeń odróżnia tablicę wskaźników od danych, na które wskazuje.",
"educational_requirement_refs": ["PTR.WE01", "PTR.WE02"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01", "PTR.EK02"],
"assessment_criterion_ref": "PTR.KW01"
},
"task07": {
"prompt_tex": "\\textbf{K\\&R 5.7 -- tablica wielowymiarowa.} Zmierz układ kolejnych wierszy w pamięci.",
"criterion": "Uczeń wyjaśnia ciągłość elementów i krok wskaźnika do wiersza.",
"educational_requirement_refs": ["PTR.WE01"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01"],
"assessment_criterion_ref": "PTR.KW01"
},
"task08": {
"prompt_tex": "\\textbf{K\\&R 5.8 -- inicjalizacja tablicy wskaźników.} Porównaj rozmieszczenie tablicy adresów i wskazywanych danych.",
"criterion": "Dwa odrębne obszary pamięci są poprawnie rozpoznane.",
"educational_requirement_refs": ["PTR.WE01", "PTR.WE02"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01", "PTR.EK02"],
"assessment_criterion_ref": "PTR.KW01"
},
"task09": {
"prompt_tex": "\\textbf{K\\&R 5.9 -- tablica 2D kontra tablica wskaźników.} Porównaj typ, rozmiar i sposób adresowania.",
"criterion": "Uczeń nie utożsamia obu reprezentacji i potrafi wskazać koszt dostępu.",
"educational_requirement_refs": ["PTR.WE01", "PTR.WE02"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01", "PTR.EK02"],
"assessment_criterion_ref": "PTR.KW01"
},
"task10": {
"prompt_tex": "\\textbf{K\\&R 5.10 -- argumenty programu.} Przejdź wskaźnikiem po \\texttt{argv} na AMD64.",
"criterion": "Uczeń wyjaśnia zakończenie tablicy argumentów i rozdział wskaźników od napisów.",
"educational_requirement_refs": ["PTR.WE01"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01"],
"assessment_criterion_ref": "PTR.KW01"
},
"task11": {
"prompt_tex": "\\textbf{K\\&R 5.11 -- wskaźnik do funkcji.} Porównaj adres funkcji z pośrednią instrukcją wywołania i przygotuj pojęcie strategii/polityki.",
"criterion": "Adres funkcji i wywołanie pośrednie są odnalezione w źródle, rejestrze i listingu.",
"educational_requirement_refs": ["PTR.WE01", "PTR.WE02"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01", "PTR.EK02"],
"assessment_criterion_ref": "PTR.KW04"
},
"task12": {
"prompt_tex": "\\textbf{K\\&R 5.12 -- złożone deklaracje.} Rozłóż deklarację od identyfikatora na operatory wskaźnika, tablicy i funkcji.",
"criterion": "Deklaracja jest czytana w poprawnej kolejności i powiązana z typem.",
"educational_requirement_refs": ["PTR.WE01"],
"learning_effect_refs": ["PTR.EN01", "PTR.EK01"],
"assessment_criterion_ref": "PTR.KW01"
}
},
"tasks_order": ["task01", "task02", "task03", "task04", "task05", "task06", "task07", "task08", "task09", "task10", "task11", "task12"]
}