[ del-boy @ 27.03.2006. 20:39 ] @
Treba da uradim program koji celobrojno deli dva broja u dvostrukoj preciznosti. Uradio sam ga, ali nešto mi je čudno i čini mi se da možda ima neka logička greška, pa ako može neko da pogleda...

Code:

#potprogam za deljenje u dvostrukoj preciznosti (a:b) (greska ide u eax)
#Autor: Delic Bojan

#############################################
#    NAPOMENA
#Ukoliko program treba da racuna i ostatak on se nalazi u registarskom
#paru edx:eax
#############################################

.section .data 
    a_gornji: .long 0x8000
    a_donji: .long 0
    b_gornji: .long 0x8000
    b_donji: .long 0
    c: .long 0
.section .text
.globl main

deljenje:
    push %ebp
    movl %esp, %ebp
    subl $4, %esp            #za gresku
    movl $0, -4(%ebp)        #postavlja gresku na nula
    xorl %ecx, %ecx            #anulira %ecx
    movl 24(%ebp), %ebx        #adresa rezultata

deljenje_provera_a:
    movl 12(%ebp), %eax        #smeska se broj a u registarski par edx:eax radi provera
    movl 8(%ebp), %edx        
    andl %edx, %edx            #uporedjuje znacajnije cifre broja a
    jnz deljenje_provera_b    #ako je %edx nula, proverava broj b
deljenje_proveri_donji_a:
    andl %eax, %eax            #a ako jeste %edx jeste nula, proverava manje znacajne cifre
    jz deljenje_kraj            #ako su manje znacajne cifre nula zavrsava program

deljenje_provera_b:
    movl 20(%ebp), %eax        #smeska se broj b u registarski par edx:eax radi provera
    movl 16(%ebp), %edx
    andl %edx, %edx            #uporedjuje znacajnije cifre broja b
    jnz deljenje_deli            #ako je %edx nula prelazimo na deljenje
deljenje_provera_donji_b:
    andl %eax, %eax            #a ako %edx jeste nula, proveravamo manje znacajne cifre
    jz i_greska                #ako su i manje znacajne cifre nula povecavamo gresku i zavrsavamo program

deljenje_deli:
    movl 12(%ebp), %eax        #postavljamo broj a u ragistarski par edx:eax, sada radi deljenja
    movl 8(%ebp), %edx
deljenje_ponovo:
    cmpl b_gornji, %edx        
    jb deljenje_kraj            #ako su znacajnije cifre broja a manje od znacajnijih cifara broja b zavrsavamo program
    cmpl b_donji, %eax
    jb deljenje_kraj            #ako su manje znacajne cifre boja a manje od manje znacajnih cifara broja b zavrsavamo program
    subl b_donji, %eax        #ako je broja a veci od broja b, oduzimamo b od a i smestamo u a
    sbbl b_gornji, %edx
    incl %ecx                #povecavamo rezultat za jedan
    jmp deljenje_ponovo        #i ponavljamo proces
i_greska:
    incl -4(%ebp)            #povecanje greske za jedan
deljenje_kraj:
    movl %ecx, (%ebx)        #postavljanje rezultata u promenljivu c (njena adresa se nalazi u %ebx)
    movl -4(%ebp), %eax        #postavljanje greske u %eax
    addl $4, %esp            #unistavanje lokalne promenljive
    pop %ebp                #ucitavanje stare vrednosti %ebp
    ret                        #povratak iz potprograma


main:
    push $c                    #postavljanje parametara potprograma na stek
    push b_donji
    push b_gornji
    push a_donji
    push a_gornji
    call deljenje                #pozivanje potprogama
    addl $20, %esp            #unistavanje argumenata sa steka
kraj:
    nop                        #kraj programa


Ja mislim da je greška negde kod deljenje_deli, ali nikako da skontam šta je... Non stop mi je na vrh jezika, ako znate na šta mislim...

PS: Nije domaći , samo vežbam
[ del-boy @ 28.03.2006. 00:07 ] @
Uradio sam nešto, sad mislim da bi trebalo da bude OK!

Problem je bio to što je manje značajne cifre proveravao uvek nezavisno od više značajnih što ne treba uvek da radi! Evo ispravljenog koda, možda nekom bude trebao:

Code:

#potprogam za deljenje u dvostrukoj preciznosti (a:b) (greska ide u eax)
#Autor: Delic Bojan

#############################################
#    NAPOMENA
#Ukoliko program treba da racuna i ostatak on se nalazi u registarskom
#paru edx:eax
#############################################

.section .data 
    a_gornji: .long 0x8000
    a_donji: .long 0
    b_gornji: .long 0x8000
    b_donji: .long 0
    c: .long 0
.section .text
.globl main

deljenje:
    push %ebp
    movl %esp, %ebp
    subl $4, %esp            #za gresku
    movl $0, -4(%ebp)        #postavlja gresku na nula
    xorl %ecx, %ecx            #anulira %ecx
    movl 24(%ebp), %ebx        #adresa rezultata

deljenje_provera_a:
    movl 12(%ebp), %eax        #smeska se broj a u registarski par edx:eax radi provera
    movl 8(%ebp), %edx        
    andl %edx, %edx            #uporedjuje znacajnije cifre broja a
    jnz deljenje_provera_b    #ako je %edx nula, proverava broj b
deljenje_proveri_donji_a:
    andl %eax, %eax            #a ako jeste %edx jeste nula, proverava manje znacajne cifre
    jz deljenje_kraj            #ako su manje znacajne cifre nula zavrsava program

deljenje_provera_b:
    movl 20(%ebp), %eax        #smeska se broj b u registarski par edx:eax radi provera
    movl 16(%ebp), %edx
    andl %edx, %edx            #uporedjuje znacajnije cifre broja b
    jnz deljenje_deli            #ako je %edx nula prelazimo na deljenje
deljenje_provera_donji_b:
    andl %eax, %eax            #a ako %edx jeste nula, proveravamo manje znacajne cifre
    jz i_greska                #ako su i manje znacajne cifre nula povecavamo gresku i zavrsavamo program

deljenje_deli:
    movl 12(%ebp), %eax        #postavljamo broj a u ragistarski par edx:eax, sada radi deljenja
    movl 8(%ebp), %edx
deljenje_ponovo:
    cmpl b_gornji, %edx        
    jb deljenje_kraj            #ako su znacajnije cifre broja a manje od znacajnijih cifara broja b zavrsavamo program
    ja deljenje_oduzmi
    cmpl b_donji, %eax
    jb deljenje_kraj            #ako su manje znacajne cifre boja a manje od manje znacajnih cifara broja b zavrsavamo program
deljenje_oduzmi:
    subl b_donji, %eax        #ako je broja a veci od broja b, oduzimamo b od a i smestamo u a
    sbbl b_gornji, %edx
    incl %ecx                #povecavamo rezultat za jedan
    jmp deljenje_ponovo        #i ponavljamo proces
i_greska:
    incl -4(%ebp)            #povecanje greske za jedan
deljenje_kraj:
    movl %ecx, (%ebx)        #postavljanje rezultata u promenljivu c (njena adresa se nalazi u %ebx)
    movl -4(%ebp), %eax        #postavljanje greske u %eax
    addl $4, %esp            #unistavanje lokalne promenljive
    pop %ebp                #ucitavanje stare vrednosti %ebp
    ret                        #povratak iz potprograma


main:
    push $c                    #postavljanje parametara potprograma na stek
    push b_donji
    push b_gornji
    push a_donji
    push a_gornji
    call deljenje                #pozivanje potprogama
    addl $20, %esp            #unistavanje argumenata sa steka
kraj:
    nop                        #kraj programa