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)
%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 funkci
    mov esi, asdf
    call esi
    call WriteUInt32NewLine
 
    ret

cv8_1.asm

cv8_1.asm
; V cyklu načítej čísla od užitele.
; 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_2.asm jedno z mnoha řešení

cv8_2.asm jedno z mnoha řešení

cv8_2.asm
%include "rw32.inc"
; V cyklu načítej čísla od užitele.
; 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.
section .text
 
double:
	add ax,ax
	call WriteInt16
	ret
 
main:
	xor eax, eax
.loop:
	call ReadInt8_Silent ; nebyla definovaná velikost :p
	cmp ax,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á jako vstup využije adresu pole v ESI
; a počet jeho prvků v ECX a jako výstup vrátí jejich sumu v EAX.
; Ve funkce main 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
%include "rw32.inc"
; Vytvoř si pole 32b znaménkových čísel (alespoň 5) s libovolnými hodnotami.
; Napiš funkci "sumaPole", která jako vstup využije adresu pole v ESI
; a počet jeho prvků v ECX a jako výstup vrátí jejich sumu v EAX.
; Ve funkce main zavolej funkci sumaPole a vypiš její výsledek.
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
 
	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 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]
 
    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
    ; vrchol zásobniku: [esp] == 5
    ; [esp + 4] == 100
    ; [esp + 8] == x
    call add_nums   ; 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: 2024/03/28 19:47 by sakin