Portál AbcLinuxu, 10. května 2025 08:28

Dotaz: asm: vypis pole

29.3.2009 19:37 asm
asm: vypis pole
Přečteno: 598×
Odpovědět | Admin
Zdravim, mam napsat funkci v asm, ktera prijme parametry pocet a adresu zacatku pole a ona vypise vsechny prvky pole:
void vypis(int pocet, int * pole) {
   for(int i=0; i<pocet; i++) {
      printf("%i", pole[i]);
   }
}
Prepsano do asm:
.486
.model flat,c
.const
frm byte "%i", 13, 10, 0
pole byte 1, 2, 3, 4, 5, 6, 7, 8, 9
pocet dword 9
.code
extern printf:proc
public main
vypis:
	push ebp
	mov ebp, esp
	mov eax, 0
zacatek:
	cmp eax, [ebp+8]
	jae konec
	push eax
	push [ebp+12]
	push offset frm
	call printf
	add esp, 8
	pop eax
	inc eax
	jmp zacatek
konec:
	pop ebp
	ret
main:
	push dword ptr pocet
	push offset pole
	call vypis
	add esp, 8
	ret
end
Namisto toho mi to stale cykli a vypisuje 9. Poradi mi nekdo? dekuji.
Nástroje: Začni sledovat (1) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

30.3.2009 03:58 Michal Ludvig | skóre: 16
Rozbalit Rozbalit vše Re: asm: vypis pole
Odpovědět | | Sbalit | Link | Blokovat | Admin

Myslím že máš trochu hokej v tom jak funguje adresování. Například:

    cmp     eax, [ebp+8]

Nejen že máš blbě offset (proměnná "pocet" je na ebp+12, nikoliv +8), ale hlavně "[ebp+12]" vezme ze zásobníku adresu proměnné "pocet" nikoliv její hodnotu. Takže to musíš dereferencovat ještě jednou abys dostal co potřebuješ:

    mov     ecx, [ebp+12]
    mov     ecx, [ecx]      ; ecx = pocet

Je dobrý si ten počet zjistit před cyklem a nechat třeba v ECX protože to je konstantní hodnota. Akorát jí budeš muset uložit před printf a pak obnovit, jinak o ni přijdeš.

Stejně tak pro counter (lokální proměnná 'i') použij ESI místo EAX - alespoň ti printf tu hodnotu nezničí:

    mov     esi, 0          ; esi = i  (counter)

Podobně i tohle je nesmysl:

    push    [ebp+12]

Jednak pole je na EBP+8, za druhý [EBP+8] vezme ze zásobníku adresu začátku pole přičemž ty potřebuješ adresu toho konkrétního prvku v každém cyklu a za třetí musíš provést konverzi z bajtového pole na int než to znova plácneš na zásobník jako parametr pro printf. Když tuhle konverzi neuděláš vypíše ti to čtyři prvky pole najednou.

    xor     edx, edx
    mov     ebx, [ebp+8]    ; ebx = &pole
    mov     dl, [ebx+esi]   ; edx = pole[i]
    push    edx             ; parametry na zasobnik pro printf

S těmito radami už bys měl být schopen dát ten program dohromady. Kdyby ne ozvi se ;-)

30.3.2009 05:28 luky
Rozbalit Rozbalit vše Re: asm: vypis pole
Odpovědět | | Sbalit | Link | Blokovat | Admin
Minimální úpravy by byly asi takto:

1. Máš tam pole bytů místo intů.

místo

pole byte 1, 2, 3, 4, 5, 6, 7, 8, 9
použij
pole dword 1, 2, 3, 4, 5, 6, 7, 8, 9

2. Parametry máš ve špatném pořadí a místo počtu předáváš adresu.

místo

push dword ptr pocet
push offset pole
použij
push offset pole
push pocet

3. Vypisuješ adresu pole místo jeho jednotlivých prvků.

místo

push [ebp+12]
použij třeba
mov esi, [ebp+12]    ; adresa pole
lea esi, [esi+eax*4] ; adresa prvku (pole + poradi * velikost)
push [esi]           ; hodnota prvku

Nezkoušel jsem to, ale mělo by to chodit.

30.3.2009 05:35 luky
Rozbalit Rozbalit vše Re: asm: vypis pole
Hopla, už vidím případnou chybku :)
30.3.2009 09:42 asm
Rozbalit Rozbalit vše Re: asm: vypis pole
Odpovědět | | Sbalit | Link | Blokovat | Admin
ahoj, diky vsem, nakonec jsem to vyresil sam ;) odpoledne sem pastnu reseni...

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.