8086 Assembly végtelen ciklus probléma

8086 Assembly végtelen ciklus probléma
2013-04-29T22:48:26+02:00
2013-05-02T15:36:38+02:00
2022-11-28T23:10:37+01:00
havoc007
Üdv!

Egy egyszerűbb progit kéne megvalósítani (1-től 10 000-ig kiírja a prímszámokat a képernyőre).
A gond az, hogy végtelen ciklusban irogat ki, és csakis memóriaszemetet. A parancssor is elszáll tőle :) Aztán x idő elteltével jön hibaüzi, hogy nem értelmezhető utasítás van a kódban, pedig tudtommal (16 bit, valós mód) egyik sem exkluzív más architektúrához.

Itt a teljes kód, mert az sem 100% hogy a kiiratás eljárás rendben van:

kod segment assume cs:kod,ds:nothing,ss:verem,es:nothing kiiras proc mov bx,10 ;szamrendszer alapja mov cx,0 ;verembe tett szamok szamlaloja k1: cmp ax,0 ;addig osztunk amig nulla nem lesz je v1 ;ha nulla ugrik mov dx,0 ;a kov. ut. dx:ax-et osztja! div bx ;osztas bx push dx ;maradek a verembe inc cx jmp k1 v1: jcxz cxnulla ;ugrik, ha nem tettunk semmit ;a verembe k2: pop ax ;kiveszunk egy erteket a verembol add al,0 ;hozzaadjuk a ’0’ ASCII kodjat call betukiir ;kiirjuk a szamot (mint karaktert) loop k2 ;johet a kovetkezo jmp v2 cxnulla: mov al,0 ;ha ax-ben 0 volt, call betukiir ;irjunk ki egy 0-t v2: ret kiiras endp betukiir proc ;al ben a kiirando betu mov ah,14 ;BIOS rutin parametere int 10h ;10h megszakitas hivasa ret ;visszateres betukiir endp ujsor proc mov ah,02 mov dl,0Dh int 21h mov dl,0Ah int 21h ret ujsor endp prim proc mov cx,2 ;osztok 2-tol kezdodnek mov dx,0 ;16 bites osztasok miatt dx-et mindig nullazzuk fele: mov ax,bx ;aktualis vizsgalando szamot ax-be push cx ;akt. oszto mentese mov cx,2 ;felezeshez (eleg csak az adott szam feleig vizsgalni az osztokat) div cx pop cx ;oszto visszatoltese mov dx,0 cmp cx,ax ;ha az akt. oszto nagyobb mint a szam fele, vegeztunk, a szam primszam jg primsz osztas: mov ax,bx div cx cmp dx,0 ;ha a maradek egy osztas utan nulla, nem primszam je vege mov dx,0 inc cx ;osztot noveljuk jmp fele ;megint megvizsgaljuk, elertuk-e mar a szam felet primsz: mov ax,bx ;ax-be a primszamot, kiirjuk call kiiras call ujsor vege: ret prim endp start: mov bx,2 ;1 megegyezes szerint nem primszam, 2-vel inicializalunk vizsg: mov bp,sp ;bx-et(aktualis szamot) mentjuk, mert a kiirasnal felhasznaljuk a regisztert push bx call prim mov bx,2[bp] ;aktualis szamot visszatoltjuk inc bx cmp bx,10000 ;ha elertuk a veget jng vizsg kod ends verem segment stack db 1024 dup (1) verem ends end start

Gyanítom a vermekkel csinálok valamit rosszul, de annyira nem tudom belőni még kezdő vagyok :) Fordítás MASM-mal megy.
Mutasd a teljes hozzászólást!
Írd be a végére nyugodtan, hogy
mov ax,4c00h int 21h
és visszatér a promptba. Megjegyzem nálam nem okozott kivételt a programod csak a végén kiírta, hogy osztási túlcsordulás.
Arrowsoft-al sikerült lefordítanod?
Mutasd a teljes hozzászólást!

  • Nem fogtam fel végig a kódot, de van pár észrevételem.

    vizsg: mov bp,sp ;bx-et(aktualis szamot) mentjuk, mert a kiirasnal felhasznaljuk a regisztert push bx call prim mov bx,2[bp] ;aktualis szamot visszatoltjuk inc bx cmp bx,10000 ;ha elertuk a veget jng vizsg

    Itt miért "mov bx,2[bp]"-t használtál a sima "pop bx" helyett? De egyébként sem +2 a helyes offszet a bp-hez képest, hanem -2, mert a verem x86-on lefelé bővül.

    De egyébként ez se jó:
    add al,0 ;hozzaadjuk a ’0’ ASCII kodjat
    ez így simán nullát ad hozzá, nem a 0 karakter kódját. A MASM szintaxist nem ismerem, de gondolom így kellene:
    add al,'0' ;hozzaadjuk a '0' ASCII kodjat

    A kettővel való osztáshoz nem kell drága, lassú DIV utasítás. Ehelyett:
    push cx ;akt. oszto mentese mov cx,2 ;felezeshez (eleg csak az adott szam feleig vizsgalni az osztokat) div cx pop cx
    elég ennyi:
    shr ax, 1

    Hirtelen ennyit vettem észre, lehet van más is.
    Mutasd a teljes hozzászólást!
  • Szia. Régen használtam assemblyt, de megpróbálkoztam vele.
    Ami számomra hiányzik, az a karakteres képernyő beállítása a kód elején. Ehelyett
    mov bx,2[bp] ;aktualis szamot visszatoltjuk
    inkább pop bx-et javasolnék. dx regiszter törléséhez pedig xor dx,dx-et. De mellékelem a javított kódot nézd át.

    kod segment ;szegmensdefiníció assume cs:kod,ds:kod,ss:verem,es:nothing ;cs,ds beállítása a szegmens elejére KIIRAS proc mov bx,10 ;számrendszer alapja mov cx,0 ;verembe tett számok számlálója K1: cmp ax,0 ;addig osztunk amig nulla nem lesz je V1 ;ha nulla ugrik xor dx,dx ;a következő utasítás dx:ax-et osztja div bx ;osztás bx push dx ;maradék a verembe inc cx jmp K1 V1: jcxz CXNULLA ;ugrik, ha nem tettünk semmit ;a verembe K2: pop ax ;kiveszünk egy értéket a veremből add al,"0" ;hozzáadjuk a nulla ASCII kódját call BETUKIIR ;kiírjuk a számot (mint karaktert) loop K2 ;jöhet a következő jmp V2 CXNULLA: mov al,0 ;ha ax-ben 0 volt, call BETUKIIR ;írjunk ki egy 0-t V2: ret KIIRAS endp BETUKIIR proc ;al ben a kiirandó betű mov ah,14 ;BIOS rutin paramétere int 10h ;10h megszakítas hívása ret ;visszatérés BETUKIIR endp UJSOR proc mov ah,02 mov dl,0Dh int 21h mov dl,0Ah int 21h ret UJSOR endp PRIM proc mov cx,2 ;osztók 2-től kezdődnek xor dx,dx ;16 bites osztások miatt dx-et mindig ;nullázzuk ;xor művelettel lehet nullázni az adott ;regisztert FELE: mov ax,bx ;aktuális vizsgálandó számot ax-be push cx ;aktuális osztó mentése mov cx,2 ;felezéshez (elég csak az adott div cx ;szám feléig vizsgálni az osztokat) pop cx ;osztó visszatöltése xor dx,dx ;dx regiszter törlése (nulla értékű ;lesz) cmp cx,ax ;ha az aktuális osztó nagyobb mint a ;szám fele, jg PRIMSZ ;végeztünk, a szám primszám OSZTAS: mov ax,bx ;aktuális számot ax-be div cx ;elosztjuk a számot cx értékével cmp dx,0 ;ha a maradék egyetlen osztás után ;nulla, je VEGE ;a vizsgált szám, nem prímszám xor dx,dx ;dx-et töröljük inc cx ;osztót növeljük jmp FELE ;megint megvizsgáljuk, elértük-e már a ;szám felét PRIMSZ: mov ax,bx ;ax-be a primszamot, kiirjuk call KIIRAS call UJSOR VEGE: ret PRIM endp start: mov ax,kod ;ds regiszter beállítása mov ds,ax mov ax,0B800h ;képernyő-memória szegmens címének mov es,ax ;beállítása mov ax,3 ;80x25-s karakteres mód és képernyő ;törlés int 10h mov bx,2 ;1 megegyezés szerint nem prímszám,ezért ;2-vel inicializálunk VIZSG: push bx ;bx-et(aktuális számot) mentjük, mert a ;kiirásnál ;felhasználjuk a regisztert call PRIM pop bx ;aktuális számot visszatöltjük inc bx cmp bx,10000 ;ha elértük a végét jng VIZSG mov ax,4C00h ;kilépés a DOS-ba int 21h KOD ends verem segment stack db 1024 dup (1) verem ends end start
    Mutasd a teljes hozzászólást!
  • Még annyi javaslatom lenne, hogy ne a szám feléig nézd az osztókat, hanem a gyökéig. És persze érdemes a párosságot külön nézni, aztán csak a páratlan osztókkal próbálkozni. De ezek már általános algoritmikus javításai a prímkeresésnek, nem a kódodhoz kapcsolódnak.

    Szóval én így írnám a prímtesztelőt:
    prim proc test bx, 1 jnz paratlan cmp bx, 2 ;a 2 az egyetlen paros szam je primsz ret paratlan: mov cx,3 ;osztok 3-tol kezdodnek gyoke: mov ax,cx ;oszto az ax-be imul ax, ax ;negyzetre emeljuk cmp ax, bx ja primsz ;ha az oszto negyzete nagyobb a szamnal, vegeztunk osztas: mov ax,bx xor dx, dx div cx test dx, dx ;ha a maradek egy osztas utan nulla, nem primszam jz vege add cx, 2 ;osztot noveljuk jmp gyoke ;megint megvizsgaljuk, elertuk-e mar a szam gyoket primsz: mov ax,bx ;ax-be a primszamot, kiirjuk call kiiras call ujsor vege: ret prim endp

    De ha a 2-t speciálisan kezeled és kiírod a többi prím előtt bedrótozva, akkor még egyszerűbb lehet a prímtesztelés, és a páros számokra már meg se kell hívnod a prim függvényt.

    (Nem tudom kipróbálni a kódot, remélem nincs benne bug )
    Mutasd a teljes hozzászólást!
  • Köszi, sokat segítettetek. A xor-ról, testről tudtam, csak lebutítottam a kódomat a hibaüzenet miatt. A kompaktabb alg. is jól jött csak nem gondoltam végig :) A képernyő beállítás új, valahogy kimaradt a levelezős pdf-ből :)

    Mostmár az alg. úgy néz ki jól működik, de még mindig nem azt csinálja a progi amit kell. A legutolsó 23 prímszámot írja csak ki (9781-től), képernyőbuffer cmd-ben nagyra van rakva, nem azzal van a gond :) A veremszegmens inicializálása nem lenne jó?

    Amúgy tisztázás végett, nem a sima visual-os MASM-ot hanem a masm32-t használom, az x86 valós módhoz talált linkerrel felülírva (az ASCII kódhoz is "0" kellett nem '0').
    Mutasd a teljes hozzászólást!
  • A képernyő beállítás új, valahogy kimaradt a levelezős pdf-ből :)


    Azt nem én írtam, de mondjuk az értelmét sem látom. Az, hogy az ES-be bepakol az ember egy címet, magában nem állít be semmit. Max. akkor lenne értelme, ha az ES-en keresztül direktben írnád a képernyőmemóriát, de akkor se a képernyőt állítaná be, csak megkönnyítené a képernyőhöz való hozzáférést.

    A legutolsó 23 prímszámot írja csak ki (9781-től), képernyőbuffer cmd-ben nagyra van rakva, nem azzal van a gond :)


    Hát ha az utolsó számot ki tudja írni, akkor szerintem csak jól működik. Ha hibára futna, akkor csak az első számokat tudná kiírni. A képernyőpuffer állításának meg lehet, hogy nincs hatása, mert te ugye egy DOS programot írtál, amit a Windows kénytelen egy emulált DOS környezetben futtatni, a DOS-ban meg nem volt ilyen visszagörgethető képernyő. Az alap szöveges felbontás 80x25 volt, ami gyanúsan közel van a te számodhoz.

    Mielőtt jobban nekiállsz debugolni, próbáld meg fájlba átirányítani a program kimenetét:
    programod.exe > valami.txt
    és a fájlban megnézni, hogy megvan-e minden. Mondjuk lehet, hogy az átirányítás nem fog hatni a BIOS-hívásokra (int 10h), és le kell cserélni őket DOS-hívásokra (int 21h). Ez nem lesz nagy gond, hiszen már úgyis használod a DOS-os kiírató függvényt is.

    A másik megközelítés, hogy valami késleltetést iktatsz be két kiírás közé, hogy szemmel tudd követni, ahogy kiíródnak, akkor is, ha később kigördülnek a képből.
    Mutasd a teljes hozzászólást!
  • Szia. Csak egy kis kiigazítás, nem kötözködés.
    mindig nem azt csinálja a progi amit kell
    Ez nem egyenlő azzal, hogy mit szeretnél Nagy különbség! De a lényeg. Az, hogy miért csak 23 számot jelenít meg? A válasz ott van a programban.
    mov ax,3 ;80x25-s karakteres mód
    ami annyit jelent, hogy a képernyődet beállítod 80 oszlopra (x tengely) és 25 sorra (y tengely). Ezért jelenik meg csak az utolsó 23 sor. Tehát, ha te látni szeretnéd a számokat, azt neked kell leprogramoznod. Pl számolod, hogy 25 számot kiírtam, akkor várok egy billentyűzet leütésre és tovább lépek a következő 25 számra. És így tovább, a végéig.
    Pl. ha jól emlékszem valahogy így:
    KEYPRESS: mov ax,100h ;billentyű leütésének figyelése int 16h jz KEYPRESS ;ha nincs,vissza KEYPRESS-hez xor ax,ax int 16h cmp al,27 ;Esc billentyű figyelése->kilépés jz VEGE ;ha,nem akkor figyeljük újra cmp ah,1Ch ;az ENTER scan códja jz EMEL ;ha ENTER,akkor ugrunk soremelésre
    Legutoljára pedig, a windows parancssora (consol) nem ugyanaz , mint a DOS karakteres képernyője.
    Mutasd a teljes hozzászólást!
  • Szia. A megjelölt op rendszer DOS.
    Ezt pedig én nem értem:
    Azt nem én írtam, de mondjuk az értelmét sem látom. Az, hogy az ES-be bepakol az ember egy címet, magában nem állít be semmit. Max. akkor lenne értelme, ha az ES-en keresztül direktben írnád a képernyőmemóriát, de akkor se a képernyőt állítaná be, csak megkönnyítené a képernyőhöz való hozzáférést.

    Ezért (Idézet László József: VGA-kártya programozása pascal és assembly nyelven c könyvéből):
    A számítógép képernyője a memóriában helyezkedik el, mint különleges felhasználású memóriaterület. A videókártya valamilyen módszerrel (általában DMA hozzáféréssel) rendszeresen kiolvassa ezt a területet és az ott található adatokat valamilyen formában megjeleníti. ... A karakteres képek a VGA-n a B800:0000 címen kezdődnek. ... Ha tehát a B800:000, címre beírunk egy 16 bites kódot, akkor a karakteres kép bal felső sarkában megjelenik a kódhoz tartozó karakter a megadott színnel.

    Ez így szebb megfogalmazás, mint ahogy le tudtam volna írni.
    Mutasd a teljes hozzászólást!
  • Lemaradt. A karakteres képernyő beállítását az
    mov ax,3 ;80x25-s karakteres mód és képernyő törlés int 10h
    funkcióval állítjuk be.
    Annak idején amikor assembly-t tanultam, a képernyő memória címét használva-beállítva (es:di) írattuk és pozicionáltuk a szövegeket.
    Lehet, hogy tévedek. Egy újabb segítség a kérdezőnek itt.
    A könyv írója tanított ezekre.
    Mutasd a teljes hozzászólást!
  • Annyira nem mélyedtem bele, de ha a standard outputra akarunk kiirni valamit akkor miért nem a dos megszakitást használod?
    Azaz az uj sor az dos
    ujsor proc mov ah,02 mov dl,0Dh int 21h mov dl,0Ah int 21h ret ujsor endp

    a szöveg kiirása viszont bios szinten megy
    betukiir proc ;al ben a kiirando betu mov ah,14 ;BIOS rutin parametere int 10h ;10h megszakitas hivasa ret ;visszateres betukiir endp

    Ezt a kettőt nem kelene keverni. Azaz a betű kiirást az operációs rendszerre kell rábízni.
    Mutasd a teljes hozzászólást!
  • A kérdező nem én voltam Én anno mindkettőre BIOS hívásokat használtam Próbáltam kerülni a DOS hívásokat amíg csak lehetett.
    Mutasd a teljes hozzászólást!
  • Úgy tűnik túlbonyolódtak a dolgok. Kiderült, a beadandó Windows alatt lesz fordítva (Arrowsoft) és futtatva, szimpla parancssorból, igen standard kimenet lesz használva, de Windows kezelése alatt... Dos-sal a program sehol sem fog találkozni, Dosbox se jön be a képbe sehol. Így hát a Dos-os képernyő felparaméterezés se fog kelleni, se Dos-os megszakítások.

    Utólag is elnézést hogy Dos platform meg lett jelölve témakörnek, én is most tudtam meg a helyzetet. Maximum annyiból releváns hogy ott használt nyelv az x86-hoz írt assembly, de itt csak az assemblernek és a linkernek kell majd ehhez alkalmazkodnia, a progot nem Dosra kell írni.

    Az ujsor-t is kijavítottam, hogy bios megszakításokat használjon.

    Összegezve:
    Az eredetileg felvetett probléma azért volt, mert rosszul vettem vissza a veremből a bx-et.
    A gyér kiírás azért volt, mert a 25 soros DOS képernyőbeállítás volt használva.

    Még 1 gond fennáll. Kiírja nagyjából a végéig a számokat, aztán 9781 után (ami érdekes módon korábban az első kiírt szám volt) kicsit random lesz a működés. Néha kiírja nagyjából a végéig, hibaüzenet nélkül, de nem végig, néha itt jön a hibaüz. (NTVDM CPU nem megengedett utasítást talált, CS:0000 IP:0077 ...), pár Kihagyás-ra nyomkodás után végigfut de a prompt-ba nem lép vissza, hanem jön egy "FCB nem érhető el, Kilépés/Mégse?".

    Kiszedtem a kódból a korábbi, feleslegessé vált képernyőbeállításokból a maradványokat, de őszintén szólva nem tudom, hogy kéne debuggolni hogy megtudjam melyik utasítás van ezen a címen, gondolom nem szimplán a 77. a sorban, mert vannak többrészes utasítások is. Gyanús hogy a prim eljárásban van a szemantikai hiba.

    Itt a restaurált kód

    kod segment para public 'code' assume cs:kod,ds:adat,ss:verem,es:nothing ;------------------------------------------------- PRIMGYUJTO proc far mov ax,adat mov ds,ax xor ax,ax mov si,offset szoveg call UJSOR intro: lodsb cmp al,0 je inic call KARKIIRAS jmp intro inic: call UJSOR mov bx,1 vizsg: push bx call PRIM pop bx inc bx cmp bx,10000 ;ha elertuk a veget ja veg jmp vizsg veg: ret PRIMGYUJTO endp ;------------------------------------------------- SZAMKIIRAS proc mov bx,10 ;szamrendszer alapja mov cx,0 ;verembe tett szamok szamlaloja k1: cmp ax,0 ;addig osztunk amig nulla nem lesz je v1 ;ha nulla ugrik xor dx,dx ;a kov. ut. dx:ax-et osztja! div bx ;osztas bx push dx ;maradek a verembe inc cx jmp k1 v1: jcxz cxnulla ;ugrik, ha nem tettunk semmit ;a verembe k2: pop ax ;kiveszunk egy erteket a verembol add al,48 ;hozzaadjuk a ’0’ ASCII kodjat call KARKIIRAS ;kiirjuk a szamot (mint karaktert) loop k2 ;johet a kovetkezo jmp v2 cxnulla: mov al,0 ;ha ax-ben 0 volt, call KARKIIRAS ;irjunk ki egy 0-t v2: ret SZAMKIIRAS endp ;------------------------------------------------- KARKIIRAS proc ;al ben a kiirando betu mov ah,14 ;BIOS rutin parametere int 10h ;10h megszakitas hivasa ret ;visszateres KARKIIRAS endp ;------------------------------------------------- UJSOR proc mov ah,14 mov al,13 int 10h mov ah,14 mov al,10 int 10h ret UJSOR endp ;------------------------------------------------- PRIM proc mov ax,bx mov cx,3 ;paratlan szamok osztoi 3-al kezdodnek xor dx,dx cmp ax,1 ;1 megegyezes szerint nem primszam je vege cmp ax,2 ;a 2 az egyetlen paros prim, spec. kezeljuk le je primsz test ax,1 ;logikai ES 1-el: ha 0 az utolso bit, paros a szam, es az egesz nulla lesz jz vege gyoke: mov ax,cx ;aktualis osztot ax-be mul ax ;negyzetre emeljuk az osztot xor dx,dx cmp ax,bx ;ha az akt. oszto negyzete nagyobb mint a szam, vegeztunk, a szam primszam ja primsz osztas: mov ax,bx div cx cmp dx,0 ;ha a maradek egy osztas utan nulla, nem primszam je vege xor dx,dx add cx,2 ;paratlan szamoknak csak paratlan osztoi vannak jmp gyoke ;megint megvizsgaljuk, elertuk-e mar a szam felet primsz: mov ax,bx ;ax-be a primszamot, kiirjuk call SZAMKIIRAS call UJSOR vege: ret PRIM endp kod ends ;------------------------------------------------- adat segment para public 'data' szoveg db 'PRIMSZAMOK:',0 adat ends ;------------------------------------------------- verem segment para stack db 1024 dup (1) verem ends ;------------------------------------------------- end PRIMGYUJTO
    Mutasd a teljes hozzászólást!
  • Utóirat:
    Az IP hexa de így sem mond többet.
    Mutasd a teljes hozzászólást!
  • Bocsi, a képernyőmódot inicializáló interrupt hívás elkerülte a figyelmemet.

    Mondjuk azt fenntartom, hogy ebben az esetben nincs sok értelme (a program nem tartalmaz semmi olyat, ami speciálisan 80x25-ös módot igényelne, ezért nem látom az értelmét, hogy ebbe a módba akarjon váltani), valamint az ES-t felesleges beállítani a képernyőmemória kezdőcímére, ha utána nem használod ténylegesen a képernyőmemória írására.
    Mutasd a teljes hozzászólást!
  • No problemo. Egészséges vita Nem kötözködés volt. Magam részéről nyitott vagyok az érdekes vitákra (amiből még tanulhatok is). Az es beállítása íly módon tényleg felesleges és a 80x25 is.
    Mutasd a teljes hozzászólást!
  • k2: pop ax ;kiveszunk egy erteket a verembol add al,48 ;hozzaadjuk a ’0’ ASCII kodjat push cx call KARKIIRAS ;kiirjuk a szamot (mint karaktert) pop cx loop k2 ;johet a kovetkezo
    csak a biztonság kedvéért. elvileg a 14-es funckció nem bántja cx-et, de azért nem árt.
    szvsz veremhiba lesz. vmelyik ret rossz ip-t vesz ki a veremből, így elkószál a proci.
    Mutasd a teljes hozzászólást!
  • Próbáld meg ezt:
    test ax,1 ;logikai ES 1-el: ha 0 az utolsó bit, páros a ;szám, és az egész nulla lesz jz vege

    kicserélni erre:

    and ax,0001h ; cmp ax,0 ;ha 0 az utolsó bit, páros a ;szám, és az egész nulla lesz je vege
    Mutasd a teljes hozzászólást!
  • mi a baj a test-tel?
    akkor mar inkabb
    shr al,1 jnc vege
    Mutasd a teljes hozzászólást!
  • Semmi változás. Változtatgattam a kódon, feltételes ugrásokat megfogalmaztam másképp, számokat átírtam hexába, lodsb-nél nullázgattam ah-t, bár tudom hogy nem bántja. Semmi.
    Mutasd a teljes hozzászólást!
  • A cx ott elvileg csak az osztásokra van felhasználva, ha bántaná nem jól számolna. Egyébként megcsináltam hogy mindenütt mentse írás előtt, de ez sem a gond.

    A max. számmal arányosan tolódik el amúgy a hely ahol elromlik, ha csökkentem a 10 ezret, úgy hamarább is vándorol el. A 0000:0077h-s című IP romlik el mindig viszont.

    Ha ret vesz ki rosszat, akkor meg nem értem hogy egy adott ciklusszámig miért vesz ki jót, és tartja a bűvös 23 prímszám távolságot (ami nem tudom kb. hány lefutás). Alsó és felső részeit a regisztereknek nem is használom külön, egyedül az intro szövegnél, ott meg minden stimt, és az adatszegmens sincs másutt használva. Szóval sehol sem számolgat és elvileg sehol nem csúszik a veremcím.
    Mutasd a teljes hozzászólást!

  • lodsb-nel nullazgattam ah-t, bar tudom hogy nem bantja

    lodsb elott inkabb cld kellene, hogy jo legyen az irany.
    si ertekenek megorzese nincs garantalva int 10-ben.
    ezert inkabb igy:
    call UJSOR mov si,offset szoveg cld intro: lodsb
    de nem ez lesz a gond.


    A cx ott elvileg csak az osztásokra van felhasználva

    nem. ott a verembe push-olt maradekok szamat tarolod cx-ben.
    viszont, ha int 10 megvaltoztatna cx-et es nem garantalna
    annak megorzeset (amit egyebkent cx-re garantaltal a
    video bios), akkor a pop-ok szama rossz lenne, így a ret mar rossz ip-t venne ki a verembol. ezert irtam, hogy nem artana
    menteni cx-et a karakter kiirasa elott.
    de ez sem lesz gond.

    lehet, hogy a kilepesre hasznalt veg: ret lesz a hiba
    forrasa. mit pakol ip-be? irasd ki:
    pop ax
    push ax
    call szamkiiras
    ret
    Mutasd a teljes hozzászólást!
  • Bocs, cx-et ott elnéztem. De akkor mindegy.
    Feltételeztem a flag alapból 0, és SI növekszik load-al, de így se jó.

    A fő eljárás végére raktam amit írtál, ezúttal az utolsó szám után halom memóriaszemét jött, és akart még jönni, az első pár kar. se volt értelmes. Ami vicc, hogyha nem írom oda, akkor is ezt csinálja mostmár, az FCB-s hülyeség végképp eltűnt. A különbség csak annyi, ha odaírom, egy rakás sortörés jön előbb.

    Egyébként kiiktattam teszt jelleggel az összes kiirató eljárást és a hívásaikat, és ugyanúgy jön a hiba. Szóval tényleg a fő eljárással vagy a prím eldöntővel van a gond.
    Mutasd a teljes hozzászólást!
  • Az utolsó szám érdekelt volna, mert azon a címen folytatja a cpu a végrehajtást az utolsó ret után.
    Próbáld a vermedet nullákkal feltölteni, ne eggyel.
    verem segment para stack db 1024 dup (0) verem ends
    vagy írj int 20h-t a ret helyett.
    Mutasd a teljes hozzászólást!
  • Utolsó prímszám 9973, ezután most egy szimpla 0-t ír, nem memóriaszemetet, de a promptba nem tér vissza, gyanítom random ami odakerül.

    Verem nullás feltöltés nem változtat semmin.

    int20h-tól annyi változik, hogy csak egyszer hozza a hibaüzit, kihagyás után is bezárja.

    Próbáltam külön prím eljárást írni ami az ominózus szám után van hívogatva, bár mivel bx feltételével arányosan tolódik ez el, nyilván ez se működött (remélem nem a gépemmel vagy a fordítóval van a gond ).

    Lehet nincs jelentősége, de a 'code' classt eltávolítva a szegmensdefinícióból egyáltalán nincs hibaüzenet. Szimplán megáll és leáll annál a számnál, promptba visszatérve.
    Mutasd a teljes hozzászólást!
  • Jogos az shr csak egy gondolat volt.
    Mutasd a teljes hozzászólást!
  • Írd be a végére nyugodtan, hogy
    mov ax,4c00h int 21h
    és visszatér a promptba. Megjegyzem nálam nem okozott kivételt a programod csak a végén kiírta, hogy osztási túlcsordulás.
    Arrowsoft-al sikerült lefordítanod?
    Mutasd a teljes hozzászólást!
  • Köszönet, ez megoldotta Megy arrowsoft-tal is, masm-el is. Nálam nincs túlcsordulás sem. Mondjuk azt nem tudom, miért kellett neki Dos megszakítás ret előtt hogy ne csússzon el az IP és rendesen lefusson.

    Még egyszer köszönet mindenkinek a segítségért.
    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