_start, syscall hívásMielőtt bármelyik fejezetbe belekezdenél, két kérdésre érdemes néhány perc alatt válaszolni: van-e meg a szükséges C-alapom, és hol érdemes belépnem a könyvbe. Ha ezt kihagyod, két tipikus veszteség ér: vagy olyan alfejezeteken rágsz át heteket, amelyeket már tudsz (például a számrendszereket), vagy olyan szerződéseket (hívási konvenció, NVIC-regiszterek) ugrasz át „ismerősnek tűnik” alapon, amelyeket a könyv később mindenhol feltételez. Ez az alfejezet ezért nem technikai tananyag, hanem útvonalterv: önellenőrző listát, konkrét tanulási kimeneteket és belépési pontokat ad.
Előismeret-küszöb: a minimális, cselekvésben mérhető C-tudás (nem „közepes szintű C”, mert az nem mérhető), amellyel a könyv technikai alfejezetei a C nyelv újratanítása nélkül értelmezhetők.
Belépési pont: a könyvtérkép alfejezete, ahonnan az olvasó a meglévő tudásához igazítva kezdheti a tanulást — a küszöb mindenkire érvényes, a belépési pont csak a kezdőpozíciót választja meg.
A következő állításoknak kell igaznak lennie rád. Ha valamelyik nem az, azt előbb pótolni kell; a könyv ezeket nem tanítja újra, csak használja.
int tömböt és annak hosszát kapja, és mutatóaritmetikával
(nem indexeléssel) járja be. Érted a különbséget int *p[4]
és int (*p)[4] között.sizeof(struct) a mezők méreteinek összege, és
miért számít a mezők sorrendje..c és egy .h fájlból álló
programot saját Makefile-lal, all és
clean céllal; a fejlécbe deklarációt, egyetlen fordítási
egységbe definíciót teszel, és érted, miért nem elég a
#include: a linkernek a definíciót tartalmazó objektumra is
szüksége van..o fájl egy futtatható állományba.Ami nem része a küszöbnek: assembly, regiszterek, ISA, NEON/SIMD, megszakításkezelés, bare-metal fejlesztés, QEMU. Ezeket a könyv nulláról építi fel.
| Rész | A rész végére önállóan… |
|---|---|
| I. rész – AArch64 | A64 assembly függvényt írsz, assemblersz, linkelsz és GDB-vel hibakeresel; a függvényt C-ből hívod az AAPCS64 szerződés szerint; felismered a fordító tipikus optimalizálási mintázatait; egy skaláris ciklust NEON-nal vektorizálsz, és a gyorsulást Amdahl-korláttal értelmezed; felismered a verem-biztonsági mintákat (canary, ASLR, NX, PAC). |
| II. rész – Cortex-M | Bare-metal startup kódot és linker scriptet írsz; vektortáblát és
NVIC-vezérelt megszakításkezelőt állítasz be; memory-mapped
perifériadrivert (GPIO, UART, timer) implementálsz; a firmware-t
qemu-system-arm alatt reprodukálhatóan futtatod és
mérőponttal igazolod. |
| Olvasóprofil | Belépési pont | Átugorható | Nem átugorható |
|---|---|---|---|
| Assembly-kezdő, C-tudás megvan | Miért assembly: amit a C elrejt | — | semmi |
| ISA/architektúra-alapokat ismer, assemblyben kezdő | Az A64 regiszterkészlet áttekintése | Számrendszerek és bitszintű reprezentáció (az elején lévő belépőteszt alapján), részben Számítógép-architektúra fogalmai | I. rész: Az AAPCS64 regiszterszerződés; II. rész: az AAPCS32 hívási szabályai (A-profile és M-profile különbségei) és NVIC konfiguráció: engedélyezés és prioritás |
| AArch64-et ismer, csak Cortex-M kell | Thumb-2, a Cortex-M futási modell és a minimal runtime, az A-profile és M-profile különbségei áthidaló példájával | I. RÉSZ – AArch64 nagy része; Az AAPCS64 regiszterszerződés csak összehasonlításként ajánlott | az AAPCS32 hívási szabályai (alkalmazásuk: A-profile és M-profile különbségei, ISR írása: C és assembly vegyesen), Memóriatérkép és a bare-metal futási modell, NVIC konfiguráció: engedélyezés és prioritás |
Az átugorható szakaszok is alap-ISA-ismeretek: ha a kettes komplemens, a bináris jelölés vagy az ISA/mikroarchitektúra megkülönböztetése már biztos, a Számrendszerek és bitszintű reprezentáció és a Számítógép-architektúra fogalmai valóban kihagyható.
Az át nem ugorható szerződések más okból kötelezők, és útvonalanként különböznek:
| Útvonal | Át nem ugorható szerződés | Nem előfeltétel |
|---|---|---|
| AArch64 (I. rész) | Az AAPCS64 regiszterszerződés | az NVIC és az AAPCS32 |
| Cortex-M (II. rész) | az AAPCS32 hívási szabályai (A-profile és M-profile különbségei, ISR írása: C és assembly vegyesen), Memóriatérkép és a bare-metal futási modell, NVIC konfiguráció: engedélyezés és prioritás | az AAPCS64 (csak összehasonlításként ajánlott) |
Egyik sem a könyv saját konvenciója:
Ezeket el kell választani a választott labor saját
szerződésétől — például a QEMU-célgéptől (mps2-an385) és az
azon érvényes perifériacímektől —, amely csak a könyv példáira érvényes.
A választott útvonal szerződését azért kell tapasztalt olvasóként is
végigvenni, mert az útvonal későbbi példái rá épülnek, nem azért, mert a
könyv találta ki: az I. rész C-ből hívható assembly függvényei az
AAPCS64-re, a II. rész megszakításos laborjai az AAPCS32-re és az
NVIC-re.
A kizárólag Cortex-M-et tanuló olvasó kötelező PCS-belépője az AAPCS32 (Procedure Call Standard for the Arm Architecture), a 32 bites Arm architektúra, köztük az M-profile eljáráshívási szabványa. Az Az AAPCS64 regiszterszerződés ilyenkor hasznos összehasonlítás, de nem helyettesíti az AAPCS32-t: eltér a regiszterszélesség (32 vs. 64 bit), az argumentumregiszterek köre (R0–R3 vs. X0–X7), a hívott által megőrzendő regiszterek halmaza (R4–R11 vs. X19–X28) és a verem igazítási követelménye (nyilvános interfészen 8 vs. 16 bájt).
Ez az útmutató a könyv minden feladatsorára és megoldására érvényes; az alfejezetek nem ismétlik meg.
Munkakönyvtár: ~/arm-labor/a64/a000/ —
az alfejezet minden laborfájlja ide kerül, és minden parancs innen
futtatandó (a könyvtárrendet a Labor-alapkörnyezet alfejezet írja le).
mkdir -p ~/arm-labor/a64/a000
cd ~/arm-labor/a64/a000Az alábbi háromfájlos program a küszöb elemeit (mutató, struktúra,
többfájlos build) gyakorolja: két külön fordítási egységből
(lab-main.c, lab-sum.c) és egy közös fejlécből
(lab-sum.h) áll. A fejléc a struct pair típust
és a sum_values deklarációját adja, a
függvény definíciója egyetlen fordítási egységben, a
lab-sum.c-ben van. Célja nem a funkcionalitás, hanem hogy
te tudd összeilleszteni és lefordítani.
/* lab-sum.h */
#ifndef LAB_SUM_H
#define LAB_SUM_H
struct pair { int key; int value; };
int sum_values(const struct pair *p, int n); /* deklaráció */
#endif/* lab-sum.c */
#include "lab-sum.h"
int sum_values(const struct pair *p, int n) { /* definíció */
int s = 0;
for (const struct pair *q = p; q < p + n; ++q) s += q->value;
return s;
}/* lab-main.c */
#include <stdio.h>
#include "lab-sum.h"
int main(void) {
struct pair v[3] = {{1,10},{2,20},{3,30}};
printf("%d %zu\n", sum_values(v, 3), sizeof(struct pair));
return 0;
}A Makefile mindkét objektumot linkeli, és mindkét
objektum függőségei között szerepel a fejléc:
# Makefile
CC = gcc
CFLAGS = -Wall -Wextra -O2 -std=c11
OBJS = lab-main.o lab-sum.o
.PHONY: all clean
all: lab-a000
lab-a000: $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
lab-main.o: lab-main.c lab-sum.h
$(CC) $(CFLAGS) -c -o $@ $<
lab-sum.o: lab-sum.c lab-sum.h
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f lab-a000 $(OBJS)Futtatás (target: x86_64 host, natív gcc; a kód
hordozható, AArch64-en azonos kimenet várható):
make
./lab-a000
echo $?Várt kimenet: 60 8, majd a kilépési
állapot 0. Az 60 a három value
összege; a 8 a struct pair mérete ezen az
ABI-n (két 4 bájtos int, igazítás miatt hézag nélkül). A
pontos méret ABI-függő; a sizeof kiíratása éppen ezért
része az ellenőrzésnek.
Elfogadási próbák. A futó program önmagában még nem bizonyítja, hogy a többfájlos build szerkezete helyes. Két próbának is teljesülnie kell:
A definíció valóban a másik objektumban van. Linkeld a
programot a lab-sum.o nélkül. Ez egy negatív
próba: itt a nem nulla kilépési állapot az
elvárt eredmény.
make -B OBJS=lab-main.o
echo "make kilépési állapot: $?" # elvárt: nem nulla (GNU Make: 2)A -B kapcsoló kötelező. Egy sikeres make
után a lab-a000 újabb, mint minden függősége, és a Make az
időbélyegek alapján dönt: az OBJS lista megváltozása
önmagában nem kényszerít új linkelést. A -B nélkül a
parancs Nothing to be done for 'all'. üzenettel, 0-s
állapottal érne véget, és a próba semmit sem bizonyítana. Ugyanezt a
próbát a Make megkerülésével is elvégezheted:
gcc -o lab-missing lab-main.o.
Valódi linkerhibát kell kapnod, nem fordítási hibát: a
lab-main.c a fejléc deklarációja miatt hibátlanul lefordul,
csak a definíció hiányzik.
gcc -Wall -Wextra -O2 -std=c11 -c -o lab-main.o lab-main.c
gcc -Wall -Wextra -O2 -std=c11 -o lab-a000 lab-main.o
/usr/bin/ld: lab-main.o: in function `main':
lab-main.c:(.text.startup+0x39): undefined reference to `sum_values'
collect2: error: ld returned 1 exit status
make: *** [Makefile:10: lab-a000] Error 1
make kilépési állapot: 2
(A +0x39 eltolás fordítóverziótól és kapcsolóktól függ.)
Ezután térj vissza a helyes objektumlistához, és ellenőrizd újra a
kimenetet:
make -B && ./lab-a000 # elvárt: 60 8A fejléc módosítása az érintett objektumokat
újrafordítja. Egy sikeres make után:
touch lab-sum.h
makeMindkét gcc -c sornak (lab-main.o és
lab-sum.o) meg kell jelennie, majd a linkelésnek.
Ellenpróbaként touch lab-sum.c után csak a
lab-sum.o fordul újra.
A két eltéréstípust érdemes külön kezelni. Ha az összeg nem
60, vagy bármelyik elfogadási próba eltér a fentitől, a
build szerkezete vagy a küszöb valamelyik eleme
bizonytalan; azt pótolni kell a továbblépés előtt. Ha viszont csak a
második szám tér el a 8-tól, az nem build-hiba, hanem a
cél-ABI tulajdonsága. Ilyenkor azt kell ellenőrizni,
hogy a kapott méret megfelel-e az adott ABI int-méretének
és igazítási szabályának (két int mező, hézag nélkül:
2 * sizeof(int)).
q < p + n feltétel bizonytalan.
Hipotézis: a mutatóaritmetika léptéke nem tiszta.
Adatgyűjtés: írasd ki (char*)q - (char*)p
értékét a ciklusban. Egy változtatás: cseréld a ciklust
indexelésre, és hasonlítsd össze. Ellenőrzés: a két
változat azonos eredményt adjon.clean után nem épül újra. Hipotézis:
hiányzó vagy hibás függőségi sor. Ellenőrzés:
make -n száraz futtatással nézd meg, mit tenne.struct pair-t
lát. Hipotézis: a .h hiányzik az
objektumok függőségi sorából. Ellenőrzés:
touch lab-sum.h, majd make -n — mindkét
objektum fordítását ki kell írnia.Az előismeret-küszöb az a cselekvésben mérhető C-tudáshalmaz (mutató, struktúra, Makefile, fordítási lánc), amely nélkül a könyv technikai fejezetei nem értelmezhetők. A belépési pont a könyvtérkép azon alfejezete, ahonnan a küszöböt teljesítő olvasó a tudásához igazítva indul: assembly-kezdőnek Miért assembly: amit a C elrejt, ISA-alapokat ismerőnek Az A64 regiszterkészlet áttekintése, AArch64-ismerőnek Thumb-2, a Cortex-M futási modell és a minimal runtime. Az át nem ugorható szerződések útvonalanként különböznek. Az AArch64-útvonalon ez Az AAPCS64 regiszterszerződés, az NVIC itt nem előfeltétel. A Cortex-M-útvonalon az AAPCS32, a memóriatérkép és az NVIC konfiguráció: engedélyezés és prioritás; az AAPCS64 itt csak összehasonlításként hasznos, és nem helyettesíti az M-profile hívási szabályait. Egyik sem a könyv saját konvenciója: az AAPCS64 és az AAPCS32 eljáráshívási szabvány (PCS), vagyis az ABI hívási szabályokat rögzítő része; az NVIC architekturális komponens, amelyhez implementáció- és panelspecifikus beállítások társulnak. Ezeket el kell választani a választott labor saját szerződésétől.
A könyv egészében hivatkozott elsődleges források élő linkjét és aktuális verzióját ennek az átdolgozásnak a részeként ellenőriztük:
developer.arm.com/documentation/... linkek élnek (a
support.arm.com-ra irányított átirányítás megerősített), de
az oldal JavaScript-renderelésű, ezért a pontos fejezetszám/kiadásbetű
automatikus lekéréssel nem volt kinyerhető.dsk-arm-assembly-tools-1.0.tar.gz, github.com/gellistvan/dsk-arm-assembly-tools,
v1.0; tartalmát, ellenőrzőösszegét és futtatását az A-profile és M-profile különbségei alfejezet
Források-szakasza írja le. A könyvben tools/… alakban
hivatkozott fájlok ennek a csomagnak a fájljai.master ág dokumentációja,
nem egy konkrét kiadott verzióé; a ténylegesen telepített QEMU ettől
eltérhet.Ellenőrzési hiányok, amelyek a fenti ellenőrzés után is
fennmaradnak: (1) a telepített Ubuntu 24.04 LTS csomagolt
GCC/binutils/GDB/QEMU pontos verziószáma ebben a munkafolyamatban nincs
lekérdezve; (2) a qemu-system-arm -machine mps2-an385
memóriatérkép mezőnevei a QEMU forráskódjából
(hw/arm/mps2.c) ellenőrizendők, ezt a fenti dokumentációs
linkek önmagukban nem igazolják; (3) a lab-a000 példa
kimenete (60 8), a lab-sum.o elhagyásakor
kapott undefined reference hiba és a fejlécmódosítás utáni
újrafordítás x86_64 hoston, GCC 13.3.0-val (Ubuntu 24.04)
mért; más fordítón és AArch64-en nem mértük, és a
sizeof(struct pair) értéke az adott ABI-tól függ, ezért a
hallgató laborjában validálandó.
Az alfejezetek „Források és ellenőrzési hiányok” szakaszai ezekre a jelölésekre hivatkoznak, és csak a saját példájuk feltételeit sorolják fel. A forrásállapot a fenti listára épül (ellenőrzés: 2026-10):
| Forrás | Állapot | Közös korlát |
|---|---|---|
Arm-dokumentáció (developer.arm.com: DDI0487, DDI0403E,
architektúra-oldalak) |
a link él | JavaScript-renderelés miatt a fejezetszám és a kiadásbetű nem ellenőrzött; a konkrét fejezetet a laborban kell visszakeresni |
| AAPCS64 | ellenőrizve: 2025Q4 (2026-01-23), Release | az SME-részek Beta minőségűek |
| AAPCS32 | a link él | az aktuális kiadás nincs ellenőrizve |
| GNU binutils, GCC, GDB kézikönyv | ellenőrizve: binutils 2.47, GCC 16.2; GDB „current” | a GDB „current” fejlesztői pillanatkép; a telepített eszközök verziója eltérhet |
QEMU dokumentáció (docs/master) |
ellenőrizve | a master ág dokumentációja, nem egy kiadott verzióé; a
telepített (Ubuntu 24.04: QEMU 8.2.2) változat eltérhet |
| „dokumentációs kiindulópont” | megnevezett forrás, ebben a kiadásban nem megnyitott | tartalmi állítás nem épül rá ellenőrzöttként |
A mérésállapot jelölései eszközverzióhoz és bizonyítékhoz kötöttek:
| Jelölés a szövegben | Eszközök és verzió | Bizonyíték |
|---|---|---|
| „helyettesítő eszközlánccal mérve” (I. rész) | zig cc 0.17.0 (Clang + ld.lld,
-target aarch64-linux-musl), lab-run.py 1.1
(unicorn 2.1.4) |
kísérőcsomag v1.0, tests/run.sh substitute,
logs/substitute-1.0-20261020.log |
| „helyettesítő eszközlánccal mérve” (II. rész) | zig cc 0.17.0
(-target thumb-freestanding-eabi -mcpu=cortex_m3),
cm-run.py 1.2 (unicorn 2.1.4, capstone 5.0.7, pyelftools
0.33) |
ugyanott; a II. rész laboronkénti állapota az A-profile és M-profile különbségei közös táblázatában |
host-mérés („host gcc”, „GNU ld/readelf 2.42”) |
x86_64, Ubuntu 24.04, gcc 13.3, GNU binutils 2.42 | a helyben közölt kimenet; a csomag hostpróbái ugyanabban a naplóban |
| fő út (GNU eszközlánc + QEMU) | aarch64-linux-gnu-*, arm-none-eabi-*,
qemu-aarch64,
qemu-system-arm -machine mps2-an385 |
csak ott állítjuk, ahol a szöveg kifejezetten így jelöli; a
kísérőcsomag tests/run.sh gnu-qemu naplója; a v1.0
csomagban ilyen napló még nincs |
| „levezetett”, „illusztratív”, „hipotetikus” | — | a levezetés maga; nem mérés |