Lasagne

Lasagne

Tanulófeladat

Bevezetés

Alapok

Megjegyzések

Az Exercism x86-64 kurzusa a NASM-et (The Netwide Assembler) használja assemblerként. A NASM-ben a megjegyzések pontosvesszővel (;) kezdődnek.

A megjegyzések a program bármely pontján elhelyezhetők, és mindent, ami egy ; után következik, figyelmen kívül hagy az assembler.

Konstansok

A NASM-ben definiálhatsz assembler-időben kiértékelt konstanst az equ használatával. Például ez egy UNIVERSE nevű konstanst definiál 42 értékkel:

UNIVERSE equ 42

A konstansok kiértékelése egyszer történik meg, a definiálásukkor, és később nem definiálhatók újra.

Általános célú regiszterek (GPR-ek)

Assemblyben a változók helyett általában regisztereket használunk az értékek tárolására. A CPU-regiszter egy gyors memóriaterület a számítógép processzorán belül. A legtöbb számítás a CPU regisztereiben történik.

Néhány regisztert különféle számításokhoz használunk, ezeket általános célú regisztereknek (GPR-eknek) nevezzük. Mások speciális vagy dedikált feladatot látnak el.

Az x86-64-ben 16 darab 64 bites általános célú regiszter (GPR) van, amelyek 32, 16 vagy 8 bitesként is elérhetők. A GPR-eket alább ismertetjük, ahol az rn-ben az n 8-tól 15-ig terjed: r8, r9, r10, r11, r12, r13, r14 és r15.

64 bites 32 bites 16 bites 8 bites
rax eax ax ah/al
rbx ebx bx bh/bl
rcx ecx cx ch/cl
rdx edx dx dh/dl
rsi esi si sil
rdi edi di dil
rbp ebp bp bpl
rsp esp sp spl
rn rnd rnw rnb

Ha 64 bitnél kevesebbet használunk, az elért bitek általában a regiszter alsó részéből származnak. Ez alól kivétel az ah, bh, ch és dh, amelyek a regiszter 16 bites részének felső 8 bitjét érik el.

Ábra arról, hogyan érhetők el a bitek a rax regiszter esetében:

+--------+---------------------------------------+
| 64-bit |                  rax                  |
+--------+-------------------+-------------------+
| 32-bit |                   |        eax        |
+--------+-------------------+---------+---------+
| 16-bit |                             |    ax   |
+--------+-----------------------------+----+----+
| 8-bit  |                             | ah | al |
+--------+-----------------------------+----+----+

Ezek közül néhány regisztert meg kell őrizni a függvényhívások során: rbp, rsp, rbx, r12, r13, r14 és r15. Ha nem őrizzük meg őket, az hibához vagy nem definiált viselkedéshez vezethet.

A többieket nem kell megőrizni, és szabadon használhatók: rax, rcx, rdx, rdi, rsi, r8, r9, r10 és r11.

Caution

A tanterv későbbi részében megtanulod, hogyan kell megőrizni a regisztereket. Egyelőre csak a második típusú regisztereket használd: rax, rcx, rdx, rdi, rsi, r8, r9, r10 és r11.

Utasítások

Az utasítások olyan számítási műveletek, amelyeket a CPU végre tud hajtani. Általában a következő formájuk van:

name destination, source

Az utasítás neve tehát az első, utána legalább egy szóköz következik, majd a céloperandus, egy vessző (,) és végül a forrásoperandus. Az utasítás általában nem módosítja a forrásoperandust, csak a céloperandust.

Mindkét operandusnak ugyanakkora méretűnek kell lennie, hacsak másképp nem jelezzük. Például ha a forrásoperandus 16 bites, akkor a céloperandusnak is 16 bitesnek kell lennie.

Például egy érték regiszterben való tárolásához használhatjuk a mov utasítást:

mov rax, rdx  ; rax = rdx
              ; mov is the name, rax is the destination operand and rdx is the source operand

A fenti kódrészlet a rdx forrásoperandus mind a 64 bitjének tartalmát átmásolja a rax mind a 64 bitjére, amely az utasítás céloperandusa.

A legtöbb utasításban lehet konstans egész számokat használni forrásoperandusként (de céloperandusként nem):

mov rcx, 42 ; rcx = 42
            ; rcx is the destination operand and 42 is the source operand

Vedd figyelembe, hogy a 32 bites regiszterbe írás a felső biteket is törli, így a mov eax, 42 ugyanaz, mint a mov rax, 42. Ez nem igaz a 16 bites és 8 bites regiszterekre.

Az összeadás, kivonás és szorzás aritmetikai műveleteihez használhatjuk az add, sub és imul utasításokat:

add rax, rsi ; rax = rax + rsi
imul rax, rdi ; rax = rax * rdi
sub rax, r8 ; rax = rax - r8

Függvények

Az utasítások függvényekbe szerveződnek. Minden függvény a forrásfájl section .text részében található.

Egy függvény deklarációja a következőkből áll:

  1. Egy címke a függvény nevével, amelyet egy : követ.
  2. A függvényt meghatározó utasítások.
  3. A visszatérő utasítás, ret.

Ez a kurzus a System V AMD64 ABI hívási konvenciót használja, és az első hat egész argumentum regiszterekben kerül átadásra a függvénynek. A sorrend a következő: rdi, rsi, rdx, rcx, r8 és r9.

A függvény egy egész értéket a rax regiszterben ad vissza.

Egy függvény meghívásához a call utasítást használjuk. Egy függvény ugyanazon forrásfájl bármely pontjáról meghívható. Ahhoz, hogy egy függvényt más forrásfájlok is láthassanak, a global direktívát kell használni.

Például ez deklarál egy sum függvényt:

section .text ; functions are placed here

global sum ; sum is visible to other source files

sum:
    ; first argument is passed in rdi
    ; second argument is passed in rsi
    ; return value is placed in rax

    mov rax, rdi ; rax is now equal to rdi
    add rax, rsi ; rax = rax + rsi

    ret ; function return

És ez meghívja a sum függvényünket a 3 és 5 argumentumokkal:

mov rdi, 3  ; First argument in rdi
mov rsi, 5  ; Second argument in rsi
call sum

; The rax register now contains the value 8 (3 + 5), after sum returns

Utasítások

Ebben a feladatban olyan kódot írsz, amely segít elkészíteni egy remek lasagnét a kedvenc szakácskönyvedből.

Négy részfeladatot kapsz, amelyek mind a lasagne elkészítésével töltött időhöz kapcsolódnak.

Note

Ezek az utasítások szerepelnek a fogalomban:

Utasítás Leírás
mov a, b átmásolja b tartalmát a-ba
add a, b a = a + b
sub a, b a = a - b
imul a, b a = a * b
call a meghívja az a függvényt
ret visszatér egy függvényből

1. Határozd meg a sütőben töltendő várható időt percekben

Definiáld az expected_minutes_in_oven függvényt, amely nem vesz át egyetlen paramétert sem, és visszaadja, hogy hány percig kell a lasagnének a sütőben lennie. A szakácskönyv szerint a sütőben töltendő várható idő 40 perc:

expected_minutes_in_oven();
// => 40

2. Számítsd ki a sütőben hátralévő időt percekben

Definiáld a remaining_minutes_in_oven függvényt, amely paraméterként megkapja, hogy a lasagne hány perce van már a sütőben, és visszaadja, hogy az előző részfeladatban megadott várható sütési idő alapján hány percig kell még a sütőben maradnia.

remaining_minutes_in_oven(30);
// => 10

3. Számítsd ki az előkészítési időt percekben

Definiáld a preparation_time_in_minutes függvényt, amely paraméterként megkapja, hogy hány réteget tettél a lasagnére, és visszaadja, hogy hány percet töltöttél a lasagne elkészítésével, feltéve, hogy egy réteg elkészítése 2 percet vesz igénybe.

preparation_time_in_minutes(2);
// => 4

4. Számítsd ki az eltelt időt percekben

Definiáld az elapsed_time_in_minutes függvényt, amely két paramétert vesz át, ebben a sorrendben:

  1. A lasagnére tett rétegek száma.
  2. A lasagne sütőben töltött perceinek száma.

A függvény adja vissza, hogy hány percet dolgoztál a lasagne elkészítésén. Ez az előkészítési idő percben és a lasagne által a sütőben eddig eltöltött idő összege.

elapsed_time_in_minutes(3, 20);
// => 26
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
x86-64 Assembly Exercism

Készen állsz elkezdeni a(z) Lasagne feladatot?

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