User Tools

Site Tools


isu:cv08

[ISU] 8. Funkce & zásobník

cv8_A.asm ukázka

cv8_A.asm
; ukázka funkce (bez zásobníkového rámce)
; v ISU debugeru sleduj "Stack content"
%include "rw32.inc"
 
section .text
f:
fg:
    add eax, 1  ; muzu zacit v jine funkci
asdf:
add_nums:
    add eax, ebx
    ret
 
main:
    mov eax, 10
    mov ebx, 54
    call add_nums   ; prime volani funkci
    call WriteUInt32NewLine
 
    ; nevyhoda, v registrech zustalo to z minulé funkce
    call f
    call WriteUInt32NewLine
 
    ; neprime volani funkce
    mov esi, asdf
    call esi
    call WriteUInt32NewLine
 
    ret

cv8_1.asm

cv8_1.asm
; V cyklu načítej čísla od uživatele.
; Vytvoř funkci, která číslo zdvojnásobí a vypiše do terminálu (předání přes register).
; Pokud uživatel zadá číslo 0, ukonči cyklus i aplikaci.

cv8_1.asm jedno z mnoha řešení

cv8_1.asm jedno z mnoha řešení

cv8_1.asm
; V cyklu načítej čísla od uživatele.
; Vytvoř funkci, která číslo zdvojnásobí a vypiše do terminálu (předání přes register).
; Pokud uživatel zadá číslo 0, ukonči cyklus i aplikaci.
 
%include "rw32.inc"
section .text
double:
    add ax, ax
    call WriteUInt16NewLine
    ret
 
main:
    xor eax, eax
.loop:
    call ReadUInt8Silent ; nebyla definovaná velikost :p
    cmp al, 0
    jz .end
    call double
    jmp .loop
 
.end:
    ret


cv8_2.asm

cv8_2.asm
; Vytvoř si pole 32b znaménkových čísel (alespoň 5) s libovolnými hodnotami.
; Napiš funkci "sumaPole", která bude přistupovat do pole nepřímo přes register ESI
;  a počet prvků pole bude v ECX.
; Výsledkem funkce bude suma všech prvků v registru EAX.
; Ve funkci main pouze nastav registry, zavolej funkci sumaPole a vypiš její výsledek.

cv8_2.asm jedno z mnoha řešení

cv8_2.asm jedno z mnoha řešení

cv8_2.asm
; Vytvoř si pole 32b znaménkových čísel (alespoň 5) s libovolnými hodnotami.
; Napiš funkci "sumaPole", která bude přistupovat do pole nepřímo přes register ESI
;  a počet prvků pole bude v ECX.
; Výsledkem funkce bude suma všech prvků v registru EAX.
; Ve funkci main pouze nastav registry, zavolej funkci sumaPole a vypiš její výsledek.
 
%include "rw32.inc"
section .data
    nums dd 55, 44, 33, 22, 11
    count dd 5
 
section .text
sumaPole:
.loop:
    add eax, [esi+(ecx-1)*4]
    loop .loop
    ret
 
main:
    xor eax, eax   ; zde bude výsledek
    mov esi, nums
    mov ecx, [count]
    call sumaPole
 
    call WriteInt32NewLine
    ret


cv8_B.asm ukázka

cv8_B.asm
; ukázka zásobníku
%include "rw32.inc"
 
section .text
main:
    mov eax, 100
    mov ebx, 200
    mov edx, 300
 
    push eax
    push ebx
    push edx
    mul bx
    ; poradi obnoveni je opacne nez poradi ulozeni
    pop  edx
    pop  ebx
    pop  eax
    nop
 
    mov eax, 1
    mov ebx, 2
    mov ecx, 3
    mov edx, 4
    pushad
    nop
    mov eax, 10
    mov ebx, 20
    mov ecx, 30
    mov edx, 40
    nop
    popad
    ret

cv8_3.asm

cv8_3.asm
; Napiš program, který ze vstupu načte 8b číslo X
;  a X-krát zavolá funkci "vypisRadek".
; Funkce vypisRadek vypíše X hvězdiček a jeden konec řádku.
; Vstupem funkce bude hodnota X, předávaná v registru EAX.
; Funkce musí zachovat hodnotu všech používaných registrů.
; eg:
; X=1
; *
; X=2
; **
; **
%include "rw32.inc"
 
section .text
vypisRadek:
 
; sekundární cyklus, vypisování '*'
 
    ret
 
main:
    call ReadUInt8Silent
 
; hlavní cyklus, volání funkce vypisRadek
    call vypisRadek
 
 
    ret

cv8_3.asm jedno z mnoha řešení

cv8_3.asm jedno z mnoha řešení

cv8_3.asm
%include "rw32.inc"
section .text
vypisRadek:
    push ecx  ; zálohuj počet řádků, ECX hlavního cyklu
    push eax  ; zálohuj číslo X, protože EAX přepíšu symbolem '*'
    mov ecx, eax
    mov eax, '*'
 
.cyclus:
    call WriteChar
    loop .cyclus
 
    call WriteNewLine
    pop eax  ; obnova čísla X
    pop ecx  ; obnova počet řádků
    ret
 
main:
    xor eax, eax
    call ReadUInt8Silent
    mov ecx, eax
 
.cyclus:
    call vypisRadek
    loop .cyclus
 
    ret


cv8_C.asm ukázka

cv8_C.asm
; ukázka stack frame - Předání argumentů přes zásobnik
%include "rw32.inc"
 
section .text
; int add_nums(int a, int b) { return a+b; }
add_nums:
    push ebp  ; záloha
    mov ebp, esp
    sub esp, 8  ; alokace pro 2 lokální proměnné
    ; [ebp - 8] == lokalni2
    ; [ebp - 4] == lokalni1
    ; [ebp] == EBP
    ; [ebp + 4] == EIP  ; návratová hodnota
    ; [ebp + 8] == 5 (a)
    ; [ebp + 12] == 100 (b)
    mov [ebp - 8], dword 42 ; zapis do lokalni2
    mov eax, [ebp + 8]
    add eax, [ebp + 12]
    add esp, 8  ; dealokace 2 lokálních proměnných
    pop ebp  ; obnovení
    ret
 
add_nums2:  ; totez
    enter 8,0
    ; 8 znamená alokaci 2 lokálních proměnných (2*4)
    ; 0 je mode, více v dokumentaci
 
    mov eax, [ebp + 8]
    add eax, [ebp + 12]
    mov [ebp - 4], eax ; zapis do lokalni1
 
    leave
    ret
 
main:
    ; push vložení na zásobnik
                    ;  x  x  x  x
    push dword 100  ; 100  x  x  x
    push dword 5    ;  5  100 x  x
    ; [esp] == 5    <= vrchol zásobniku
    ; [esp + 4] == 100
    ; [esp + 8] == x
    call add_nums   ; změn na add_nums2
 
    ; úklid argumentů ze zásobníku
    add esp, 8  ; posune vrchol zásobníku o 2 byte (2*4)
    ret
; Note: protože používám EBP, měli bychom jej zálohovat i v mainu

cv8_4.asm

cv8_4.asm
; Napiš funkci "obsah" která spočítá obsah obdélníku ze souřadnic
; (X1, Y1) a (X2, Y2) předávaných přes zásobník.
; Funkce musí zachovat hodnotu všech registrů kromě výstupního EAX
; (horních 32b výsledku (EDX) můžete ignorovat).
%include "rw32.inc"
 
section .text
; int obsah(int x1, int y1, int x2, int y2);
obsah:
 
    ret
 
main:
    push dword 20  ; Y2 - 4. parametr
    push dword 15  ; X2 - 3. parametr
    push dword 5   ; Y1 - 2. parametr
    push dword 2   ; X1 - 1. parametr
    call obsah
    add esp, 16    ; úklid zásobníku, 4 parametry
                   ; alternativně můžu 4x zavolat pop
    call WriteInt32
    ret

cv8_4.asm jedno z mnoha řešení

cv8_4.asm jedno z mnoha řešení

cv8_4.asm
%include "rw32.inc"
 
section .text
; int obsah(int x1, int y1, int x2, int y2);
obsah:
    enter 0,0  ; vytvoření zásobníkového rámce
    push edx   ; záloha, protože volající funkce může EDX používat
 
    ; EDX = X2-X1
    mov edx, [ebp+16]
    sub edx, [ebp+8]
 
    ; EAX = Y2-Y1
    mov eax, [ebp+20]
    sub eax, [ebp+12]
 
    ; EAX = EAX*EDX
    mul edx
 
    pop edx  ; obnova
    leave    ; zrušení zásobníkového rámce
    ret
 
main:
    push dword 20  ; Y2 - 4. parametr
    push dword 15  ; X2 - 3. parametr
    push dword 5   ; Y1 - 2. parametr
    push dword 2   ; X1 - 1. parametr
    call obsah
    add esp, 16    ; úklid zásobníku, 4 parametry
                   ; alternativně můžu 4x zavolat pop
    call WriteUInt32  ; 15*13 = 195
    ret


cv8_5.asm

cv8_5.asm
; Napiš funkci "fact" pro výpočet faktoriálu.
; Číslo N zadej jako argument funkce přes zásobník.
; Note: 2 způsoby výpočtu - cyklus nebo rekurze.

isu/cv08.txt · Last modified: 2025/04/05 19:32 by sakin