Kivonás nagy számokkal Assemblyben

Kivonás nagy számokkal Assemblyben
2011-05-01T17:38:09+02:00
2011-05-08T08:49:40+02:00
2022-11-21T19:45:40+01:00
paz
Sziasztok! Szeretnék segítséget kérni..
Nagy számokkal (20 jegyig) kell dolgoznom assemblyben..
Összeadásról és kivonásról van szó..
Egész pontosan a kivonással akadtak gondjaim:
elküldeném a kódrészleteimet

ez adja ossze a két számot
osszeadas proc push bx push di push si push ax push cx mov bl, 20 mov si, offset op1 add si, 19 mov di, offset op2 add di, 19 mov carry, 0 ;a végéről haladunk az elejére, osszeadogatjuk a szamokat + az atvitelt _ciklus: mov al, byte ptr [di] sub al, 30h ;al-be és ah-ba rakjuk a megfelelő számjegyeket mov ah, byte ptr [si] sub ah, 30h add al, ah ;AL-be osszeadjuk a szamokat add al, carry ;az eredmény al-ben mov ah, 0 mov cl, 10 div cl ;AL carry, AH számjegy add ah, 30h ;számmá konvertáljuk mov byte ptr[di], ah ;eredmény visszatöltése dec bl dec di dec si mov carry, al ;aktuális carryt elmentjük cmp bl, 0 ; ha az elsot is beolvastuk akkor vege jne _ciklus pop cx pop ax pop si pop di pop bx ret osszeadas endp
amelyeket az adatszegmensben tárolok:
muvjel db 1 dup("+") ;elso karakter olvasakor osszeadjuk a 0val az op1-t így 0+op1 kerul op2-be, szóval ezért kell +-t tenni ide temp db 20 dup(0) ;ideiglenes tároláshoz, ezt használjuk a beolvasott számok "eltolásánál" count db 1 dup("0") op1 db 20 dup("00000000000000000000") op2 db 20 dup("00000000000000000000") carry db 1 dup(0)
egy számot így olvasok be:
szambeolvas proc push ax ;beolvasashoz push dx ;kiirashoz push si ;szamlalo push di ;mujvel[0] cimzesehez ;init mov si,1 ;index 1tol kezdodik xor ax,ax xor dx,dx mov di,0 szambeolvas_eleje: ;bekerunk egy szamot cmp si,20 je szambeolvas_vege mov ah, 07h int 21h ;mielott szamot neznek meg, elotte megnezzuk a "spec" karaktereket ;enter, esc, muveleti jelek.. cmp al, 0Dh ;ENTER? je _eredmenykiir cmp al, 1Bh ;ESC je _terminal cmp al, 2Bh ;+ esetén vége a számolvasásnak je _muvtarol cmp al, 2Dh ;- je _muvtarol ;al-ben tárolt karakter cmp al, 30h jb szambeolvas_eleje ;ha nem szam cmp al, 39h ja szambeolvas_eleje ;ha nem szam ;ellenben ha szamrol van szo ;akkor ki is irjuk ;es eltaroljuk a temp valtozoban mov dl, al mov ah, 02h int 21h mov temp[si],al inc si jmp szambeolvas_eleje _muvtarol: mov dl, al mov ah, 02h int 21h mov muvjel[di],al jmp szambeolvas_vege _terminal: ; program terminálása 0-ás kóddal mov ax, 4c00h int 21h _eredmenykiir: mov dl, 3Dh mov ah, 02h int 21h mov count[di],al jmp szambeolvas_vege szambeolvas_vege: ;vegen a temp valtozobol az op1 valtozoba masoljuk a szamot, ugy, hogy megfeleloen eltoljuk a szamjegyeket ;hogy a temp utolso szamjegye az op1[20]-ba keruljon pl: 123->00000000000000000123 lesz ;si-ben szamjegyek szama +1 dec si mov di,19 ;goto op1vege _masol: cmp si,0 je _tvege ;teljesen vege :) mov al, temp[si] mov op1[di], al dec si dec di jmp _masol _tvege: pop di pop si pop dx pop ax ret szambeolvas endp
továbbá ez maga a program MAIN része:
_ithasbegun: call szambeolvas cmp muvjel, 2Dh je _nem_ad_ossze je _ossze_adja _ossze_adja: call osszeadas jmp _muvelet_utan _nem_ad_ossze: call kivonas jmp _muvelet_utan _muvelet_utan: ;bevertük-e neki az egyenlőt? cmp count, 3Dh je _tov jmp _ithasbegun _tov: mov ax, offset ujsor ;szoveg paraméterbe call szovegkiir mov ax, offset op2 ;szoveg paraméterbe call sumkiir retf ;visszatérés a hívó programhoz

A problémám a kivonó művelet megírásával van :(
Sajnos nem tudom lekódolni..
Arra gondoltam, hogy megnézem a mind a részösszeg, mind az aktuális beolvasott szám számjegyét, kivonom a részösszegből az aktuálist, ha <0 akkor carry=1 és a végéről kezdve az elejéig végigmegyek a számokon. Kb mint az összeadásnál.. csak nem akar összejönni :(
Help me!
Köszönöm!
Mutasd a teljes hozzászólást!
Mit is nyerek vele?

de ha optimalizalunk

mov ebx,_len mov eax,0 mov esi,offset szam1 mov edi,offset szam2 mov edx,offset convtab mov ecx,7 mov ebp,"00" .repeat dec ebx mov al,[esi+ebx] add ah,[edi+ebx] sub ax,bp add ah,al shr ax,cl mov ax,[edx+eax] mov [esi+ebx],al .until ebx <0
Mutasd a teljes hozzászólást!

  • a végéről kezdve az elejéig végigmegyek a számokon. Kb mint az összeadásnál.. csak nem akar összejönni :(


    Jó gondolat. A két művelet teljesen hasonló. Miért nem megy?
    Mutasd a teljes hozzászólást!
  • A kivonást csinálhatod így (ugyanilyen primitív módszerrel):

    Mész hátulról számjegyenként,
    sub
    -bal kivonod az egyikből a másikat (előtte a másodikhoz hozzáadot az előző átvitelt, ami az elején 0). Ha a kivonásnál a második nagyobb az elsőnél, akkor a carry 1-re billen, ezt
    jc/jnc
    -vel meg tudod vizsgálni.
    Ha nincs carry, akkor a számjegyet egyszerűen kiírod, nullára állítod az előző átvitelt és mész a következő számjegyre.
    Ha van carry, akkor az eredmény egy negatív szám, mely kettes komplemensben van a regiszterben. Pl. 4-ből kivontál 6-ot, az -2 (0FEh), ehhez egyszerűen
    add
    -dal hozzáadsz 10-et, az 8. Ezt a számjegyet kiírod, és 1-re állítod azt a változót, ami az átvitelt jelzi.

    Ilyen egyszerű, később lehet optimalizálni.
    Mutasd a teljes hozzászólást!
  • Én javaslom pl. egy kicsit utánanézni a processzor utasításkészletének.

    Az AAA (Ascii Adjust after an Addition) és az AAS (Ascii Adjust after a Subtraction) utasítások éppen az általad kívánt műveleteket segítik!


    Negatív számok tárolásához pedig ajánlom a 10-es komplemens kódolást.
    Mutasd a teljes hozzászólást!
  • Elég randa a kódod!

    Itt egy összeadás, ennek mintájára csináld a kivonást.

    _len = 16 ; itt a hossz .data szam0 db "0" szam1 db "1234567812345678" szam2 db "1234567887654321" convtab label word db 0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,0,1,1,1,2,1,3,1,4,1,5,1,6,1,7,1,8,1 .code superAdd proc mov ebx,_len mov eax,0 .repeat dec ebx mov al,[szam1+ebx] add ah,[szam2+ebx] sub ax,"00" add ah,al shr ax,7 mov ax,[convtab+eax] or al,"0" mov [szam1+ebx],al .until ebx <0 ret superAdd endp
    Mutasd a teljes hozzászólást!
  • Javítok, még lehetett rajta optimalizálni.

    _len = 16 ; itt a hossz .data szam0 db "0" szam1 db "1234567812345678" szam2 db "1234567887654321" convtab label word db "0",0,"1",0,"2",0,"3",0,"4",0,"5",0,"6",0,"7",0,"8",0,"9",0, db "0",1,"1",1,"2",1,"3",1,"4",1,"5",1,"6",1,"7",1,"8",1 .code superAdd proc mov ebx,_len mov eax,0 .repeat dec ebx mov al,[szam1+ebx] add ah,[szam2+ebx] sub ax,"00" add ah,al shr ax,7 mov ax,[convtab+eax] mov [szam1+ebx],al .until ebx <0 ret superAdd endp
    Mutasd a teljes hozzászólást!
  • akkor lehetne:

    and ax,NOT '00'

    is, ha optimalizálsz...
    Mutasd a teljes hozzászólást!
  • Mit is nyerek vele?

    de ha optimalizalunk

    mov ebx,_len mov eax,0 mov esi,offset szam1 mov edi,offset szam2 mov edx,offset convtab mov ecx,7 mov ebp,"00" .repeat dec ebx mov al,[esi+ebx] add ah,[edi+ebx] sub ax,bp add ah,al shr ax,cl mov ax,[edx+eax] mov [esi+ebx],al .until ebx <0
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd