Kurzusok
/
Lean
Lean
/
Feladatok
/
Összeállítás
Összeállítás

Összeállítás

Nehéz

Utasítások

Ebben a feladatban egy kicsi, az x86-64 assembly nyelvből ihletett nyelv szintaxisát és végrehajtási modelljét definiálod.

A cél, hogy formalizáld, hogyan írjuk le, dolgozzuk fel és hajtjuk végre a kódot egy korlátozott környezetben.

Végrehajtási modell

Az assembly kódodat egy különleges szerkezetbe írod:

let program := assemble!(
    -- assembly code here
)

Ennek a szerkezetnek egy programot kell létrehoznia, ami egy olyan függvényt szimulál, amely végrehajtja az assembly kódot, és visszaad egy értéket. Ezt a programot ezután a következő szintaxissal hívod meg, ahol az a, b, c stb. argumentumok:

let result := program(a, b, c, ...)

Minden argumentum és a visszatérési érték is 64 bites előjeles egész szám. Legfeljebb 6 argumentum engedélyezett.

Regiszterek

A visszatérési érték és az összes argumentum is regisztereken keresztül adódik át. A nyelvednek a következő regisztereket kell támogatnia:

regiszter szerep
rdi 1. argumentum
rsi 2. argumentum
rdx 3. argumentum
rcx 4. argumentum
r8 5. argumentum
r9 6. argumentum
rax visszatérési érték

A regiszterek alapértelmezett értéke 0, kivéve, ha a függvény argumentumainak átadására szolgálnak.

Például a következő programban minden regiszter értéke 0, kivéve a rdi-t, amelynek kezdőértéke 10, és az rsi-t, amelynek kezdőértéke -20:

program(10, -20)

A program visszatérési értéke mindig az rax regiszterben tárolódik.

Note

A regiszterneveknél nem számít a kis- és nagybetű. Ez azt jelenti, hogy a rax, a RAX és az rAx mind ugyanarra a regiszterre utal.

Assembly kód

Az assembly kód minden sora kétféle formájú lehet:

  • Címkék jelölik ki a program azon helyeit, amelyeket egyes utasítások használnak.
  • Utasítások olyan műveleteket jelölnek, amelyeket a program végrehajt.

Ha egy utasítás nem módosítja, a program végrehajtása lineárisan halad. Ez azt jelenti, hogy egy sor teljesen végrehajtódik, mielőtt a következő sor végrehajtódna.

Címkék

A címkék szintaxisa a következő:

<label>:

Nem módosítják egyetlen regiszter értékét sem, és semmilyen más hatásuk nincs a programra, mint hogy kijelölik a kód bizonyos helyeit, hogy az utasítások használhassák őket.

Note

A címkéknél számít a kis- és nagybetű. Ez azt jelenti, hogy a Start, a start és az sTart három különböző címke.

Kétoperandusú utasítások

A legtöbb utasítás szintaxisa a következő:

<opcode> <destination>, <source>

Az opcode jelöli a végrehajtandó műveletet, a destination és a source operandus értékeit felhasználva. A művelet eredménye a destination operandusban tárolódik.

Például az add utasítás összeadja a destination és a source operandus értékét, és az eredményt a destination operandusban tárolja.

A destination operandus mindig regiszter, a source operandus viszont lehet regiszter vagy literál szám.

Az alábbi utasításokat kell támogatnia a programodnak:

opcode végrehajtott művelet
mov destination := source
add destination := destination + source
sub destination := destination - source
mul destination := destination * source
div destination := destination / source
xor destination := destination ^^^ source
and destination := destination &&& source
or destination := destination ||| source
shl destination := destination <<< source
shr destination := destination >>> source

Ezeken kívül a programodnak támogatnia kell a kétoperandusú cmp utasítást is.

Ez az utasítás nem módosít egyetlen regisztert sem, hanem összehasonlítja a destination és a source operandust, és a program egy belső állapotát három lehetőség egyikére állítja:

  • nagyobb, mint, ha destination > source
  • egyenlő, ha destination == source
  • kisebb, mint, ha destination < source

Hogyan tartod nyilván belül ezt az állapotot, az rád van bízva.

Egyoperandusú utasítások

Van néhány utasítás, amely megváltoztatja a program folyamatát, és a végrehajtást a kód egy másik pontjára viszi át. Ezeket ugró utasításoknak nevezzük.

Mindegyikük egyetlen operandust kap, egy címkét, amely az ugrás célját jelöli, vagyis a kód azon pontját, ahol a végrehajtás folytatódik:

<opcode> <label>

A jmp utasítás mindig végrehajtja az ugrást a célcímkére.

A többi ugró utasítás csak akkor ugrik, ha a program belső állapota egy adott értékre van állítva. Ez azt jelenti, hogy általában egy cmp utasítás előzi meg őket.

Az alábbi ugró utasításokat kell támogatnia a programodnak:

utasítás végrehajtott művelet
jmp feltétel nélküli ugrás. Az ugrás mindig megtörténik
je ugrik, ha a belső állapot egyenlő
jl ugrik, ha a belső állapot kisebb, mint
jg ugrik, ha a belső állapot nagyobb, mint
Note

Az utasítások opcode-jainál nem számít a kis- és nagybetű, akár kétoperandusú, akár egyoperandusú utasításról van szó. Ez azt jelenti, hogy a add, az ADD és az aDd mind ugyanarra az utasításra utal.

Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Lean Exercism

Készen állsz elkezdeni a(z) Összeállítás feladatot?

Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Lean nyelvet 100 feladat segítségével, valódi emberi mentorálással, mindez ingyen.