Probléma karakterekkel Assemblyben

Probléma karakterekkel Assemblyben
2011-03-30T11:10:14+02:00
2011-04-01T12:19:39+02:00
2022-11-21T09:00:36+01:00
Totoka
Hello!

Két nagy számot kellene összeszoroznom assemblyben (10jegyűeket max). Mivel ugye 1db 10jegyű szám nem fér el 1 regiszterben, ezért úgy csinálom, mint írásban, hogy egyik utolsó számjegyével végig szorzom a másik összesét, ezt az eredményhez adom, és ezt ismétlem minden számjegyére.
Elég kezdő vagyok assemblyből, most ott tartok, hogy szam1-nek és szam2-nek lefoglalom a helyet, és mind a 10 karakter kezdetben - tehát h ott nincs semmi. Beolvasni is sikerül, de pl ha szam1-be beolvasom az 12345-öt, akkor ilyen a szám: 12345-----, de nekem ilyen alakban kéne: -----12345, mivel így szám végéről tudnék haladni, ahogy rendesen a papíron szorzásnál is.
Úgy akarom a megfelelő alakra hozni, hogy di az utolsó akarkterre mutasson, ami valószínűleg -, és si pedig az utolsó olyanra, ami nem -. Ha ezmegvan, akkor kicserélem [si] és [di] tartalmát, majd decrementálom mind a 2t, és megint ezt, ameddig nem ér el si a szam1 első karakteréhez.
Ezt a kódot írtam rá:
ELSORENDEZ PROC
mov di, offset szam1
add di,9
mov al,[di] ;di az utolsó karakterre mutat
call IR
call UjSor
mov si, offset szam1
vegkeres1:
mov al,[si]
cmp al,'-'
je vegkeres1vege
inc si
jmp vegkeres1
vegkeres1vege:
dec si ;si az utolsóra ami nem -
mov al,[si]
call IR
call UjSor
ret
cserel:
xor ax,ax
mov al,[si]
mov [di],al
dec si
dec di
cmp dx,si
je cserelvege
jmp cserel
cserelvege:
ret


ELSORENDEZ ENDP

Azért íratom ki h si és di mire mutat, mert nem működik az eljárás jól, és érdekel hogy egyáltalán tényleg azokra mutatnak-e amire kell. És milyen meglepő, nem azokra...:S Illetve amikor kiíratom si-t, az tényleg az utolsó nem - karakterre, 12345 esetében tehát 5-t ír ki, de pl ugyanebben az esetben di, aminek az utolsó karakterre kéne mutatnia ezt írja ki: -2345 Nem igazán értem h mi a hiba? Valaki tudna segíteni hogy jól működjön?
Előre is köszi!
Mutasd a teljes hozzászólást!
Számítottam valami hasonlóra...

Azt ugyan nem értem miért kell a karaktert BIOS hívással, az újsort pedig DOS funkcióval kiírni, mindenesetre a BIOS hívásnál problémák lehetnek.
A 10h interrupt ősi leírásaiban megjegyzésre kerül, hogy csak a CS, SS, DS, ES, BX, CX, DX regisztereket őrzi meg, a többi változatlan maradására nincs semmi garancia. Tehát az AX, SI, DI, BP regisztereket lehet, hogy elrontja (AX-et nagyon valószínű!). Ezeket vagy mented, vagy itt is a DOS hívást (int 21h) használod. Persze az utóbbinál sincs 100% esély arra, hogy minden DOS hívás megőrzi azokat a regisztereket, amelyek nem paraméter be illetve kimeneti célt szolgálnak, de általában azokkal nincs ilyen gond. Azért a bemenő adatok megváltozására itt is mindenképp számíts!

Megjegyzendő még, hogy az int 10h 14-es funkciója még a BH-ban várja a képernyő lap számát is (szerencséd volt, ha ott 0 lehetett), tehát lehet, hogy meg se jelenik a karakter, mert nem az a lap van megjelenítve. (grafikus módban meg a BL-ben egy színkód kellene).

Persze lehet, hogy más a probléma, de érdemes végigzongorázni...

Továbbá:

A -2345 kiíratásakor lehet, hogy csak a - jelet írja rá a képernyőn már meglévő 12345 karaktersorozatra, tehát elképzelhető, hogy jól működik minden.

A számjegyek helyretolására való algoritmusra pedig számos megoldást ki lehet találni.

Megjegyezném (kizárólag azoknak, akik programozónak akarnak menni), hogy a programozás igen gyakran egyfajta rejtvényfejtés, és csak az fogjon hozzá aki ebben jártas (jó logikájú, kreatív ember), ne pedig az aki valamiféle meggazdagodási lehetőséget lát csak benne. Mai időkben meggazdagodni csak azok fognak akik nagy példányszámban eladható programokkal foglalkoznak, és a programozó meg a vevő között foglalnak helyet (ez ugyan még nem elég, de a többi követelmény nem tartozik ide).

Én egyébként ebben a feladatban (sokszámjegyes szozás) globálisabban gondolkodnék, és nem ragadnék le a bevitel nem kívánt formájának helyrehozásánál. Ugyanis aritmetikai algoritmusokban nagyon gyakran szükséges a számjegyek eltolására (jobbra/balra) valamiféle rutin, s ha ez megvan, akkor a bevitelnél ennek a használata már értelemszerű.

Vagyis: NE prakticista módon, kizárólag egy részprobléma megoldásának módján erölködjünk, hanem folytassunk előtanulmányokat az adott témakörben és csak a gondos tervezést követően fogjunk magához a program megírásához.

Ha valaki - akár házi feladat feladásában is - ezt a prakticista gyakorlatot erölteti, akkor szinte beleégeti a mai "programozókba" a lehető leghibásabb - bár nagyon elterjedt - feladatmegoldási szemléletet.


Neked pedig segítségként pl.:

Ha számot kívánunk beolvasni egy regiszterbe, akkor az algoritmus "ezer éves" módja az, hogy a következő számjegy bejövetelekor a regiszter aktuális tartalmát 10-zel szorozzuk (ez itt egy 1 számjeggyel való balra tolás), majd a bejött számjegyet ehhez a regiszterhez hozzáadjuk (itt az utolsó helyre helyezzük). Vagyis nincs szükség korrekcióra, és felhasználunk egy gyakran szükséges funkciót (tolás).

Mutasd a teljes hozzászólást!

  • muszáj a .286?
    Mutasd a teljes hozzászólást!
  • feltételezem:
    - DS remélhetőleg jól áll

    kérdések:
    - Miért van a cserel cimke előtt ret? Arra ugyanis kilép, és nincs csere! Vagy külön hívod meg?
    - cmp dx, si sorban a dx-ben mi van (mikor került oda és mi?)
    - a call-lal hívott rutinok nem rontják el az SI, DI, AL, DX tartalmát?
    - a "csere" közben miért nem kerülnek minuszok az átpakolt számok helyére? Nem hiányzik egy mov al, '-' és mov [si], al valahonnan?


    megjegyzések (opcionális egyszerűsítések):
    - az első 2 programsor (mov,add) helyett: mov di, offset szam1+9
    - xor ax,ax minek van?
    - je cserelvege és jmp cserel helyett: jne cserel és ret
    Mutasd a teljes hozzászólást!
  • Ha este hazaérek, kipróbálom amiket írtál.
    DS valószínűleg jól van beállítva, mert a tanár által írt keretprogramot kell kiegészítenünk.
    A cserél címke előtt a ret nem tudom miért van, így belegondolva tényleg nem kell :D
    dx-ben a szám első karaktere van, csak azt a sort a próbálgatások közben valószínűleg kitöröltem, illetve a cserélgetésnél is sztem ez történt (elég rossz kódot küldtem be:S)
    Ezeket még ki is tudom javítani, inkább azt nem értem, hogy a si miért találja meg jól az utolsó nem - karaktert, de közben di-ben meg miért nem is csak 1 karakter van, hanem 5?
    Ez a fő problémám, hogy a

    mov di,offset szam1
    add di,9

    után [di] miért nem az tulsó - karakterre mutat? Amikor al-be belerakom [di]-t és kiíratom, akkor 5 karaktert ír ki, ezzel nem tudok igazából semit sem kezdeni,h mitől lehet?
    Mutasd a teljes hozzászólást!
  • "Amikor al-be belerakom [di]-t és kiíratom, akkor 5 karaktert ír ki"

    Ehhez az IR rutin működését kellene tudni, azaz, hogy a call IR hívása mit csinál. Ez lehet csak az AL-ben lévő karakter kivitele, de lehet, hogy összetettebb funkciót csinál, amihez felhasználja más regiszterek tartalmát is. Olyan, hogy "...di-ben meg miért nem is csak 1 karakter van, hanem 5...", egy értelmetlen megfogalmazás (DI egy 16 bites regiszter, és legfeljebb mutat egy bájtra, vagy bájtsorozatra, de több karakterként csak olyan rutin tudja azt értelmezni, ami a DI-ben vár egy memóriacímet).
    Mutasd a teljes hozzászólást!
  • Na jó, mostmár tényleg teljesen tanácstalan vagyok...:D
    Kiír rutin így néz ki:
    IR PROC
    MOV AH,14
    INT 10H
    RET
    IR ENDP

    új sort pedig így írok:
    UjSor PROC ;sortores kiirasa
    PUSH AX
    PUSH DX
    MOV AH,02h
    MOV DL,0Dh
    INT 21h
    MOV DL,0Ah
    INT 21h
    POP DX
    POP AX
    RET
    UjSor ENDP

    Annyi, hogy al-ben lévő karaktert kiírja.

    Így foglaltam helyet a 10 karakternek:
    szam1 db '-','-','-','-','-','-','-','-','-','-'

    Csináltam egy olyat, hogy folyamatosan kiíratom, h mi mire mutat:

    ELSORENDEZ PROC
    mov di, offset szam1+9
    mov al,[di] ;di az utolsó karakterre mutat
    call IR
    call UjSor
    call IR
    call UjSor
    mov si, offset szam1
    mov al,[si]
    call IR
    call UjSor
    call IR
    call UjSor
    vegkeres1:
    mov al,[si]
    cmp al,'-'
    je vegkeres1vege
    inc si
    jmp vegkeres1
    vegkeres1vege:
    dec si ;si az utolsóra ami nem -
    mov al,[si]
    call IR
    call UjSor
    cserel:
    mov al,[si]
    mov ah,[di]
    mov [di],al
    mov [si],ah
    dec si
    dec di
    cmp dx,si
    je cserelvege
    jmp cserel
    cserelvege:
    ret


    ELSORENDEZ ENDP

    Először ugye di-vel mutatok az offset szam1+9 -re, ami ugye az utolsó karakter. Ezt belerakom al-be, és kiíratom, csak úgy próbaképpen 2szer. És itt jön a poén, h ha pl azt írom be h 12345 a számbevitelekor, akkor első kiíratásra azt írja h -2345, majd azt amit tényleg akarok, h -
    Amikor si az offset szam1 -re mutat, és kétszer kiíratom, akkor mind a 2szer csak az 1-est írja ki, tehát 1 karaktert, ahogy akarom. Majd amikor si-vel megkeresem az utolsó nem - karaktert, akkor is kiíratásnál jót ír ki, és csak 1-et.
    Van vmilyen ötletek arra, h ha egymás után 2szer kiíratom ugyanazt, és elvileg nem változik semmi, akkor miért ír mást a 2 alkalommal?
    Tényleg nem értem, elvileg se az IR se az UJSOR nem változtat semmi értékén, mer elején amit használ verembe ment, aztá végén ki is veszi onnan.
    Vagy ha van vmi egyszerű ötletetek arram hogy egy 10 hosszú karakterláncot, aminak az elején van n db szám, végén pedig 10-n - jel, hogy kell átírni úgy, h elején legyen a 10-n - jel, és a végén ugyanabban a sorrendben az n db számjegy, akkor azt is megköszönném.
    Mutasd a teljes hozzászólást!
  • Számítottam valami hasonlóra...

    Azt ugyan nem értem miért kell a karaktert BIOS hívással, az újsort pedig DOS funkcióval kiírni, mindenesetre a BIOS hívásnál problémák lehetnek.
    A 10h interrupt ősi leírásaiban megjegyzésre kerül, hogy csak a CS, SS, DS, ES, BX, CX, DX regisztereket őrzi meg, a többi változatlan maradására nincs semmi garancia. Tehát az AX, SI, DI, BP regisztereket lehet, hogy elrontja (AX-et nagyon valószínű!). Ezeket vagy mented, vagy itt is a DOS hívást (int 21h) használod. Persze az utóbbinál sincs 100% esély arra, hogy minden DOS hívás megőrzi azokat a regisztereket, amelyek nem paraméter be illetve kimeneti célt szolgálnak, de általában azokkal nincs ilyen gond. Azért a bemenő adatok megváltozására itt is mindenképp számíts!

    Megjegyzendő még, hogy az int 10h 14-es funkciója még a BH-ban várja a képernyő lap számát is (szerencséd volt, ha ott 0 lehetett), tehát lehet, hogy meg se jelenik a karakter, mert nem az a lap van megjelenítve. (grafikus módban meg a BL-ben egy színkód kellene).

    Persze lehet, hogy más a probléma, de érdemes végigzongorázni...

    Továbbá:

    A -2345 kiíratásakor lehet, hogy csak a - jelet írja rá a képernyőn már meglévő 12345 karaktersorozatra, tehát elképzelhető, hogy jól működik minden.

    A számjegyek helyretolására való algoritmusra pedig számos megoldást ki lehet találni.

    Megjegyezném (kizárólag azoknak, akik programozónak akarnak menni), hogy a programozás igen gyakran egyfajta rejtvényfejtés, és csak az fogjon hozzá aki ebben jártas (jó logikájú, kreatív ember), ne pedig az aki valamiféle meggazdagodási lehetőséget lát csak benne. Mai időkben meggazdagodni csak azok fognak akik nagy példányszámban eladható programokkal foglalkoznak, és a programozó meg a vevő között foglalnak helyet (ez ugyan még nem elég, de a többi követelmény nem tartozik ide).

    Én egyébként ebben a feladatban (sokszámjegyes szozás) globálisabban gondolkodnék, és nem ragadnék le a bevitel nem kívánt formájának helyrehozásánál. Ugyanis aritmetikai algoritmusokban nagyon gyakran szükséges a számjegyek eltolására (jobbra/balra) valamiféle rutin, s ha ez megvan, akkor a bevitelnél ennek a használata már értelemszerű.

    Vagyis: NE prakticista módon, kizárólag egy részprobléma megoldásának módján erölködjünk, hanem folytassunk előtanulmányokat az adott témakörben és csak a gondos tervezést követően fogjunk magához a program megírásához.

    Ha valaki - akár házi feladat feladásában is - ezt a prakticista gyakorlatot erölteti, akkor szinte beleégeti a mai "programozókba" a lehető leghibásabb - bár nagyon elterjedt - feladatmegoldási szemléletet.


    Neked pedig segítségként pl.:

    Ha számot kívánunk beolvasni egy regiszterbe, akkor az algoritmus "ezer éves" módja az, hogy a következő számjegy bejövetelekor a regiszter aktuális tartalmát 10-zel szorozzuk (ez itt egy 1 számjeggyel való balra tolás), majd a bejött számjegyet ehhez a regiszterhez hozzáadjuk (itt az utolsó helyre helyezzük). Vagyis nincs szükség korrekcióra, és felhasználunk egy gyakran szükséges funkciót (tolás).

    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