1286 lines
89 KiB
JSON
1286 lines
89 KiB
JSON
{
|
||
"$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 1–4 łą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 0x80001455−0x80001450 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"]
|
||
}
|