X86 NASM čtení z terminálu a vypsání znovu na terminál ale pouze půlka každého řádku – Assembler – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

X86 NASM čtení z terminálu a vypsání znovu na terminál ale pouze půlka každého řádku – Assembler – Fórum – Programujte.comX86 NASM čtení z terminálu a vypsání znovu na terminál ale pouze půlka každého řádku – Assembler – Fórum – Programujte.com

 

anonym
~ Anonymní uživatel
454 příspěvků
9. 1. 2023   #1
-
0
-

Dobrý den, chtěl bych se zeptat zda by mi někdo nepomohl z tímto problémem:

Přečtěte řádky textu z terminálu. Vypište na terminál první polovinu načtených řádků a z každého řádku jen první polovinu načtených bajtů.

Polovinu počítáte celočíselně. Polovina např. z 5 jsou 2. Potom první polovina bude obsahovat 2 řádky nebo bajty a druhá polovina 3 řádky nebo bajty.

Řádků na vstupu může být až 600, každý řádek může být dlouhý až 100 bajtů.
I prázdné řádky se musí předat na výstup.
Na výstupu musí být každý řádek ukončen znaky CR LF bez ohledu na to, jakým oddělovačem řádků byl ukončen na vstupu.
V načtených datech se pro jednoduchost vyskytují jen písmena bez diakritiky, číslice a mezery.

Můj kód je zde, ale nefunguje tak jestli někdo neví jak pomoci:

cpu 8086
segment code
..start mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,dno
mov es, ax
start mov ah, 0x0a
mov dx, buffer
int 21h
cmp al, 0
je print_lines
inc word [count]
mov si, buffer
mov di, line
mov cx, 100
rep movsb
jmp print_lines
print_lines mov ax, [count]
shr ax, 1
mov [half], ax
mov bx, [half]
mov cx, [half]
print_line mov dx, line
mov ah, 9
int 21h
mov si, line
mov di, line_end
mov cx, 2
rep movsb
mov ax, 100
shr ax, 1
mov [half_byte], ax
add si, [half_byte]
mov cx, 100
rep movsb
dec bx
jz end
jmp print_line
empty_line mov ah, 9
mov dx, empty_string
int 21h
jmp print_line

end hlt
segment data
buffer db 100
half dw 0
count dw 0
half_byte dw 0
line_end db 0Ah, 0Dh
line db 100
empty_string db 0Ah, 0Dh
segment stack
resb 100
dno: db ?
 

Nahlásit jako SPAM
IP: ...–
gna
~ Anonymní uživatel
1853 příspěvků
10. 1. 2023   #2
-
0
-

Tak v první řadě pro funkci 0x0a musí být v tom bufferu jeho délka, a pro funkci 0x09 musí být ten řetězec ukončený dolarem.

Nahlásit jako SPAM
IP: 213.211.51.–
anonym
~ Anonymní uživatel
454 příspěvků
10. 1. 2023   #3
-
0
-

#2 gna
Děkuji za radu, a tak myslíte že by bylo lepší použít něco jíného nebo to upravit aby to fungovalo s tímto ?

Myslíte že na to jdu správným směrem, nebo jsem úplně mimo a tímto kódem nejsem schopný vyřešit tento problém ?

Nahlásit jako SPAM
IP: ...–
gna
~ Anonymní uživatel
1853 příspěvků
10. 1. 2023   #4
-
0
-

Pokud to nemusí běžet na DOS 1, tak s funkcemi 0x3F/0x40 to podle mě bude jednodušší.

Nahlásit jako SPAM
IP: 213.211.51.–
anonym
~ Anonymní uživatel
454 příspěvků
10. 1. 2023   #5
-
0
-

#4 gna
Bohužel si myslím, že nebudu moci použít toto z důvodu, že mi to hodí tento error:
CS:IP=0000:0014h, absolutní adresa 20 0x14 024, na řádku 12 00000014 CD21 Int 21h: Neimplementovaný režim AH=63 0x3F 077 simulované služby INT 21h.

Nahlásit jako SPAM
IP: ...–
gna
~ Anonymní uživatel
1853 příspěvků
11. 1. 2023   #6
-
0
-

OK, u té funkce 0x0A je v tom bufferu 1 byte určující kapacitu, pak 1 byte určující délku načtených dat, a pak X byte těch dat.

Nevím, jak s touhle funkcí zjistit konec vstupu. Asi ji používáte tak budeš vědět, jak to děláte.

To, že rovnou máš v paměti [delka, data...] se hodí a použil bych to pro uložení všech řádků. Takže nakonec můžeš mít kompletní data ve formátu:

3, 'abc', 6, 'nazdar', 5, 'bazar'

Ty řetězce pak projdeš a před výpisem doprostřed vložíš ten ukončovací '$' pro funkci 0x09.

V pseudokódu celý program může vypadat nějak takhle:

max_line_count  equ 600
max_line_len    equ 100

segment code

start:
    ...

read_lines:
    if line_count == max_line_count
        goto print_lines

    ; nacteni radku
    buffer.used = 0
    int21.read(buffer)

    ; nevim jak s touto funkci detekovat konec vstupu
    ; dejme tomu, ze to bude zadani <ctrl-z>, <enter>
    ; tj. v bufferu bude jeden znak s hodnotu 26
    if buffer.used == 1 and buffer.data[0] == 26:
        goto print_lines

    ; ulozeni radku. delka + data
    copy_src = @buffer.used
    copy_dst = save.ptr
    copy_len = buffer.used + 1
    copy(copy_dst, copy_src, copy_len)

    line_count += 1
    save.ptr += copy_len

    goto read_lines

; vypsat prvni polovinu nactenych radku
; a z kazdeho radku jen prvni polovinu nactenych bajtu
print_lines:
    line_count = line_count / 2
    save.ptr = @save.data

next_line:
    if line_count == 0
        goto end
    line_count -= 1

    line_length = save.ptr[0]
    line_data = save.ptr + 1
    save.ptr += 1 + line_length

    line_length = line_length / 2
    if line_length == 0
        goto end_line

    line_data[line_length] = '$'
    int21.print(line_data)

end_line:
    int21.print(crlf)

    goto next_line

end:
    int21.exit(0)


segment data

line_count  dw      0
crlf        db      13, 10, '$'

buffer:
.max        db      max_line_len + 1
.used       db      0
.data       resb    max_line_len + 1

save:
.data       resb    (1 + max_line_len + 1) * max_line_count
.ptr        dw      save.data
Nahlásit jako SPAM
IP: 213.211.51.–
gna
~ Anonymní uživatel
1853 příspěvků
11. 1. 2023   #7
-
0
-

Tak mě napadá, že už při načítání můžeš ukládat jen půlku řádku a rovnou s tím ukončovačem. Tím se to dost zjednoduší.

Nahlásit jako SPAM
IP: 213.211.51.–
JerryM0
Věrný člen
11. 1. 2023   #8
-
0
-

To zadání je takový divný. opsal si to zadání správně ??? to je pro MSDOS ? a verze ? 7.0 ? 6.x ???

Někdo po tobě chce 600 řádků po max 100 znacích jenomže .. paměť se přidělovala po paragrafech ... ok, a chce tu paměť na začátku nebo postupně ??? protože tam v tom zadání se píše:

"...Řádků na vstupu může být až 600, každý řádek může být dlouhý až 100 bajtů.
I prázdné řádky se musí předat na výstup..."

což znamená že nejprve zadáš max. 600 řádků po max. 100 znacích a dále je vypíšeš jenomže alokace paměti musí být krapánek větší a to 600 x 104 = 62400 znaků  protože při čtení musí být paměť alokovaná minimálně jako 100 + 2 (délka) + 1 (0Dh) + 1(znak $) znaků při zadávání a  pro tisk se musí vynechat první 2 znaky a znak poslední a místo něj vložit znak $ a pak provést odřádkování sekvenci 0Dh0Ah$ zvlášť ...

"...Na výstupu musí být každý řádek ukončen znaky CR LF bez ohledu na to, jakým oddělovačem řádků byl ukončen na vstupu...."

no to je hezký, ale to budeš mít asi dvojitý odřádkování ne ?  to totiž záleží na použitém terminálu ... ty používáš terminál VT100 ??? nebo přímo tiskeš do konzole MSDosu ??? nebo co ??

a tak ta paměť teda musí bejt alokovaná předem jako statická ??? nebo požádáš o její přidělení službou 48h ???  v příloze máš nějaký další popis ...

a dále
"... V načtených datech se pro jednoduchost vyskytují jen písmena bez diakritiky, číslice a mezery...."

no to je moc hezká věta :) .. to psal kdo to zadání ??? nějakej mamlas ne ? to jako máš používat Unicode ??? nebo UTF8 ???  to asi ne co ? protože pod MSDOSem bylo kodovaní CP852/CP895 ??? kde 1 znak = 1 byte a čeština se řešila "víceméně" :) změnou fontů nikoliv počtem bytů znaku jako je u UTF16 nebo u Unicode

"...Můj kód je zde, ale nefunguje tak jestli někdo neví jak pomoci:..."

tvuj kod nefunguje protože je kompletně celý špatně ...a špatně je proto že si nepochopil zadání ... nebo je zadání špatně nevim co na to mám dodat ... zkus ještě přidat nějaké informace ... třeba v čem to píšeš ? v MSDOSu ? v nějakým emulátoru ? a jaký máš editor ? protože jde o to, čim ukončíš zadávání řádků ? klávesou TAB ? konec řádky je enter

https://stanislavs.org/helppc/int_21.html

dále potřebuješ tuhle knížku

https://www.antikvariat-olomouc.cz/operacni-system-dos-makroasembler-tesla-eltos-1989/

já bych si asi nechal přiděli paměť dynamicky ale mužeš i přes definici struktury staticky a to:

STRMEM DB 62400 DUP(0)

nebo

STRMEM RECR 600 DUP(<0>)

RECR STRUC

STRB DB 104 DUP(0) ; tady by asi mělo bejt zarovnání na paragraf (16 bytů) ale to je fuk

RECR ENDS

a to v tvým programu nikde nevidim..

takže celý postup by měl být nejřív si zajistit paměť na zadavaný text + paměť na další proměnné a pak načíst řádky cyklem a nezapomenout u funkce 4Ah pokaždý zvětšit počáteční offset paměti o např. 104 a nějak si definovat jak rozpoznáš poslední řádek ... třeba nějakým znakem v řetězci .. obvykle se k tomu používal Ctrl+Z ale jestli ti to pude zadat z klávesnice to nevim apod. (a pak ten znak musíš v řetězci najít) a současně při čtení každýho řádku zvýšit čítač řádků o 1 a pak až to budeš mít načtený tak jednoduše ze začátku každýho řádku přečteš počet znaků a zobrazíš jich jen polovinu a současně i jen polovinu řádků ... a to je celé

no a teď bys měl zase něco říct ty :)

Připojen obrázek.

Připojen obrázek.

Připojen obrázek.

Připojen obrázek.

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:7c10:ccea:e0b3:6aa...–
gna
~ Anonymní uživatel
1853 příspěvků
11. 1. 2023   #9
-
0
-

#8 JerryM
Ty vole, ty seš takovej vůl.

Nahlásit jako SPAM
IP: 213.211.51.–
JerryM0
Věrný člen
11. 1. 2023   #10
-
0
-

#9 gna
já víííííím ale já už se narodil jako děsnej prudič :) chápeš jo ? :) :) :) :)  a navíc to má fakt jako špatně .. uplně všechno ...

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:20d8:1ed:e3f2:3fea...–
anonym
~ Anonymní uživatel
454 příspěvků
12. 1. 2023   #11
-
0
-

#8 JerryM
Pracuji ve vlastním emulátoru procesoru od toho kdo mi dal to zadání, zde je popis toho emulátoru:

pro odpovězení: terminál přímo msdos, víc je popsáno v tom textu.

Struktura emulátoru

Emulátor procesoru Intel 8086 v ISu používá pro fázi překladu instrukcí překladač Netwide Assembler (NASM). Překladač dodaný zdrojový kód přeloží do souboru ve formátu Microsoft OMF Object Files (použitím volby -f obj). Překlad z bezpečnostních důvodů neprobíhá na serverech ISu. OMF soubor následně převezme IS. IS pak provede to, co by provedl zavaděč, tj. segmenty umístí do "paměti". Potom IS zahájí interpretaci operačních kódů instrukcí. Program není z bezpečnostních důvodů spuštěn, ale je interpretován instrukce po instrukci.

Proces spuštění programu

Emulátor umísťuje do "paměti" segmenty v pořadí, v jakém jsou v OMF souboru. Segmenty se do paměti umísťují od absolutní adresy 0 (tj. adresy 0000:0000). Chcete-li plnit tabulku přerušovacích vektorů, je nutné ve zdrojovém souboru jako první uvést segment s jejím obsahem.

Pro zjištění adresy, od které se má program spustit, IS v OMF souboru vyhledá první segment s názvem CODE. Do registru CS před spuštěním IS naplní segmentovou část adresy prvního segmentu s názvem CODE a do registru IP vloží offset 0 nebo offset instrukce označené návěštím ..start

Jiné segmentové registry než CS emulátor neplní a musí si je naplnit program sám.

Příklad jednoduchého programu

segment data zprava db "Hura, muj program funguje!",0Dh,0Ah,'$' segment code mov ax,data mov ds,ax ; nastavuji DS na segmentovou část adresy segmentu DATA mov ax,stack mov ss,ax ; nastavuji SS na segmentovou část adresy segmentu STACK mov sp,dno ; nastavuji adresu dna zásobníku do registru SP mov dx,zprava ; služba v DX vyžaduje offset začátku řetězce mov ah,09h ; identifikace služby Řetězec znaků na terminál int 21h ; provedení služby hlt ; ukončení tohoto programu segment stack ; vyhrazení prostoru pro segment se zásobníkem resb 16 ; rezervuji 16 bajtů (pozor, to je malý zásobník) dno db ? ; označuji, kde je dno zásobníku

Zvláštnosti překladače NASM
Direktiva cpu 8086

Emulátor IS podporuje pouze instrukce procesoru 8086. Proto doporučuji použít direktivu překladače
cpu 8086
která už na úrovni překladače nepovolí použít instrukce, které nejsou v repertoáru procesoru 8086. Např. instrukce procesoru 80186 PUSH 1 (tj. PUSH přímá_hodnota), PUSHA, BOUND nebo procesorů vyšších. Také existují instrukce vyšších procesorů, které mají stejnou zkratku, ale jiný operační kód. Uvedením cpu 8086 doporučuji zabránit překladači, aby použil operační kód modernějšího procesoru.

Překladač je case-sensitive

Překladač rozlišuje mezi malými a velkými písmeny. Direktivu segment pište malými písmeny. Neměňte v návěštích velikost písmen.

Odlišení objektu od jeho obsahu (hranaté závorky)

Překladač NASM chce důsledně odlišovat objekt od jeho obsahu. Proto kód:
cpu 8086 segment code mov ax,data mov ds,ax mov bx,promenna mov dx,[promenna] hlt segment data promenna dw 1234h
uloží do registru BX hodnotu 0 (tzn. offset proměnné PROMENNA v segmentu DATA) a uloží do registru DX hodnotu 1234h (tzn. obsah proměnné PROMENNA). Důsledně prosím používejte hranaté závorky u paměťových objektů tam, kde chcete pracovat s obsahem objektu a nikoli s adresou objektu.

Specifikace velikosti objektu (upřesnění byte, word)

Překladač NASM požaduje upřesnit velikost operandu, s nímž má pracovat, pokud velikost není zřejmá např. z druhého parametru instrukce. Proto je třeba psát např.
mov byte[promenna],2 neg byte[promenna] add word[prom],0x20

Alokace prostoru (pseudoinstrukce resb, resw)

Pro vyhrazení (rezervování) např. 1024 bajtů pro zásobník, použijte pseudoinstrukci resb následovně:
segment stack resb 1024 dno db ?
Chceme-li prostor vyhradit v počtu 16bitových slov, použijeme pseudoinstrukci resw.

Některé programovací techniky

Vynulování registru: XOR AX,AX

Služby operačního systému

Emulátor poskytuje programu vybrané služby operačního systému MS-DOS, nebo (historické) služby BIOSu. Volání poskytnutí služeb probíhající přes přerušení (např. INT 21h) nevyžaduje nastavení obsahu tabulky přerušovacích vektorů. Přesněji: pokud byste přerušovací vektor např. 21h nastavili, bude emulátorem ignorován.

Načíst jeden bajt z terminálu (služba MS-DOS)

mov AH,1 ; Identifikace služby Načíst jeden bajt z terminálu int 21h ; resp. int 33 poskytne službu
Služba vrací v registru AL načtený bajt. Pokud byl čtením vstup vyčerpán (už nejsou zadané žádné bajty k načtení), služba nastaví ZF=1 a AL=0. Pokud je předáván bajt v AL, je ZF=0.

Emulátor podporuje i čtení UNICODE znaků v transformaci UTF-8. Pokud je zadán vícebajtový znak, služba předá jen jeden jeho bajt (více se do AL nevejde). Dalším int 21h bude předán další bajt téhož znaku. Nedojde ke ztrátě obsahu.

Vypsat jeden bajt na terminál (služba MS-DOS)

mov AH,2 ; Identifikace služby Vypsat jeden bajt na terminál mov DL,'a' ; Bajt, který se má na terminál vypsat int 21h ; resp. int 33 poskytne službu

Emulátor podporuje i výpis UNICODE znaků v transformaci UTF-8. Pokud má být vypsán vícebajtový znak, musí být postupně vypsán více voláními této služby po jednotlivých bajtech.

Vypsat řetězec bajtů na terminál (služba MS-DOS)

V registrech DS:DX musí být uložena adresa začátku řetězce bajtů. Řetězec končí znakem dolar '$'.
zprava db "Hello, World!", 0Dh,0Ah, '$' ... mov AH,9 ; Identifikace služby Vypsat řetězec bajtů na terminál mov DX,zprava ; Offset začátku řetězce v segmentu dle DS int 21h ; resp. int 33 poskytne službu

Načíst řádek z terminálu (služba MS-DOS)

Nejprve musíte v paměti rezervovat "buffer", do kterého bude služba načtené bajty vkládat. V datovém segmentu vytvořte něco jako:
nacteno db 80, ? resb 80
Buffer nechť obsahuje tři složky: první bajt je vámi zadaná délka bufferu, který dáváte službě k dispozici. V bajtu zadáváte číslo bez znaménka. Číslo odpovídá počtu bajtů, který může služba maximálně načíst. Služba načte jeden celý řádek až do maximální zadané délky.

Dále rezervujete druhý bajt, do kterého služba vloží počet bajtů, které skutečně načetla. Je to číslo bez znaménka v jednom bajtu. Tento počet bajtů nezahrnuje znaky CR a LF. Zdůrazňuji, že se předává počet načtených bajtů, nikoli znaků, protože služba podporuje i čtení vícebajtových UNICODE znaků v transformaci UTF-8.

Od třetího bajtu jsou vloženy načtené bajty.

Adresu bufferu předáváte v DS:DX.

mov AH, 0x0a ; Identifikace služby Načíst řádek z terminálu mov DX,nacteno ; Offset začátku bufferu v segmentu dle DS int 21h ; resp. int 33 poskytne službu
Služba čte vstup po jednotlivých řádcích. Čte řádky, které vepíšete do pole "Zadat vstup z terminálu". Můžete zadat více než jeden řádek. Pokud už byl veškerý vstup čtením vyčerpán, služba vrací ZF=1, načtená délka je 0 a první načtený bajt je 0. Pokud byl načtený řádek (i když prázdný), služba vrací ZF=0. Řádky se oddělují znakem LF, znak CR je ignorován. Oba znaky CR a LF, pokud byly načteny, jsou vlženy do bufferu, ale nejsou započítány do délky ve druhém bajtu.

Zjisti stav čtení z terminálu

mov AH, 0x0b ; Identifikace služby Zjisti stav čtení z terminálu int 21h ; resp. int 33 poskytne službu
Služba vrací AL=0xff, pokud je k dispozici alespoň jeden nepřečtený bajt. Jinak vrací služba AL=0, tzn. že vstup už byl čtením vyčerpán.

Zjisti systémové datum

mov AH, 0x2a ; Identifikace služby Zjisti systémové datum int 21h ; resp. int 33 poskytne službu
Služba vrací rok v registru CX, měsíc v registru DH, den v měsíci v registru DL a pořadí dne v týdnu (neděle je 0) v registru AL.

Nastav systémové datum

mov AH, 0x2b ; Identifikace služby Nastav systémové datum mov AX,2020 ; rok, povoluje se interval 1980-2099 mov DH,1 ; měsíc mov DL,25 ; den v měsíci int 21h ; resp. int 33 poskytne službu
Služba vrací AL=0, pokud bylo datum nastaveno. Vrací AL=0xff, pokud je zadané datum chybné.

Zjisti systémový čas

mov AH, 0x2c ; Identifikace služby Zjisti systémový čas int 21h ; resp. int 33 poskytne službu
Služba vrací hodinu (24hodinový režim) v registru CH, minutu v registru CL, sekundu v registru DH, počet setin sekundy v registru DL.

Nastav systémový čas

mov AH, 0x2d ; Identifikace služby Nastav systémový čas mov CH,23 ; hodina ve 24hodinovém režimu mov CL,59 ; minuta mov DH,59 ; sekunda mov DL,81 ; počet setin sekundy int 21h ; resp. int 33 poskytne službu
Služba vrací AL=0, pokud byl čas nastaven. Vrací AL=0xff, pokud je zadaný čas chybný.

Jeden znak na terminál (služba BIOS)

mov AH,14 ; 14=0Eh Identifikace služby Jeden znak na terminál mov AL,'a' ; ASCII kód znaku, který se má na terminál vypsat int 10h ; resp. int 16 poskytne službu

FAQ
Překladač nasm mi hlásí chybu Line #XXX: error: label `yyyyy' changed during code generation

Problém nastává v případě použití pseudoinstrukcí dw, dd, dq s nedefinovanou hodnotou, tj. např. 'dw ?'. Zkuste nahradit za definovanou hodnotu, např. 'dw 0'.

Překladač nasm mi hlásí chybu "error: no instruction for this cpu level" pro instrukci ROL

Pokud použijete instrukci ROL (či ROR, SHL, SHR, SAL, SAR) s argumentem, kterým je číslo větší než 1, pak skutečně tato instrukce není procesorem 8086 podporována (podporují ji až procesory vyšší řady). Instrukce ROL (apod.) smí rotovat (posouvat) buď o 1 bit, nebo o počet bitů umístěný v registru CL. Tzn. povoleny jsou pouze varianty "ROL reg,1" a "ROL reg,CL".

Ovládání tiskáren

Vizte zvláštní Popis paralelního portu pro tisk na tiskárnu.

Využití přerušovacího systému

Využití přerušovacího systému.

Nahlásit jako SPAM
IP: ...–
JerryM0
Věrný člen
13. 1. 2023   #12
-
0
-

jo, moc hezký.... a jako k čemu ti sou instrukce "Zjisti systémový čas" apod. ??? 

hele MDOS je pro mě už poměrně vzdálená minulost...

je sice pravda, že "NASM - The Netwide Assembler"  je poměrně novej .... ale .... je předpokládám, že vám ten váš mamlas učitel dal i debuger pro MSDOS takže sem ti něco napsal a zkus to přeložit a spustit a zjisti jestli si schopen alokovat dostatek paměti a řekni nám kolik ti ukazuje registr BX těsně před instrukcí: jc error.

Jinak by si to měl přeložit instrukcí: nasm -f bin mujkod.asm -o mujkod.com  a onen .com soubor by měl jít již v msdosu spustit, ale přiznám se že sem to psal tak nějak naslepo :)  :) :) :)  protože sem nenašel debugger :)

org 100h

jmp  setup

setup:

        lea dx, [msg_text]
        mov ah,0x09
        int 0x21

        lea dx, [msg_crlf]
        mov ah,0x09
        int 0x21

        mov ax, 0x4800
        mov bx, 0xffff ; 3900 x 16 bytes
        int 0x21

        jc error

        mov [r1_dw_001], ax
        jmp  freemem

error:  
        mov [msg_mem], bx

        lea dx, [msg_err]
        mov ah, 0x09
        int 0x21

        lea dx, [msg_crlf]
        mov ah,0x09
        int 0x21

        lea dx, [msg_mem]
        mov ah, 0x09
        int 0x21

        lea dx, [msg_crlf]
        mov ah,0x09
        int 0x21

        jmp  endprog

freemem:

        mov ax, 0x4900
        mov es, [r1_dw_001]
        int 0x21

endprog:
        mov ax, 4c00h
        int 21h


section    .data

msg_text DB 'Hello.',0x24
msg_crlf DB 0x0D,0x0A,0x24
msg_err  DB 'Error.',0x24
msg_mem  DB 0x00, 0x00, 0x23, 0x24

r1_dw_001     DW  0
r1_dw_002     DW  0

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:30bd:e8e2:37f1:d41d...–
JerryM0
Věrný člen
13. 1. 2023   #13
-
0
-

aha tak už sem si vzpoměl, už to zkoušet nemusíš. :)

budeš si muset ten blok paměti alokovat jako

data_01  db 62400 DUP(0)

pro .com soubor :) msdos totiž přiděloval při spuštění .com veškerou dostupnou pamě´t :)

no ... ale funguje to ... takže to je ok

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:30bd:e8e2:37f1:d41d...–
JerryM0
Věrný člen
14. 1. 2023   #14
-
0
-

Tak co, už ti to funguje :) Níže je kod pro x86 v modelu tiny. Funguje :)
Je to samozřejmě zjednodušená verze.
Jsou tam hlavní části co potřebuješ. Zbytek si musíš dodělat.
Zkoušel jsem to na DosBox 0.74-3. A v MSDOS 7.1. Funguje to.
V DosBoxu je bohužel stále neopravená chyba v Int21h/0x0A, takže funkce
dovoluje načíst max znaků místo max-1 a když to zadáš tak se
DosBox zhroutí. V MSDosu to funguje normálně.
Ty sice děláš v nějakým "školním emulátoru" ale bylo by rozumný
kdyby sis to si mohl spustit u sebe na počítači :)

1/ Takže máš několik možností. buď si nainstaluješ DosBox
https://www.dosbox.com/download.php?…
a ten funguje pod windows.
po intalaci si někde na disku C uděláš adresář třeba c:\_DOSBOX
a ten pak příkazem mount propojíš s DOsBoxem.
Do konfiguračního souboru, co je ve start menu Windows
přidáš až nakonec do sekce Autoexec tyhle příkazy:

[autoexec]
# Lines in this section will be run at startup.
# You can put your MOUNT lines here.

mount c c:\_DOSBOX
c:
cd nc
nc


tim se ti po každým spuštění DosBoxu automaticky pripojí adresář.
Pokaždé když něco do něj z windows přidáváš, musíš zadat v DosBoxu příkaz
RESCAN
https://www.dosbox.com/wiki/Commands
aby se provedl update.

NASM je staženej z webu a funguje ok.
tady máš obsah toho adresáře _DOSBOX, kterej sem používal,
když si tot tam nakopíruješ a připojíš tak mužeš pomocí
NC5 - norton normálně editovat zdroják přímo v DosBoxu.
Kompilace se dělá příkazem:

nasm -f bin d5.asm -o d5.exe

ano, je tam exe, ale to je proto, aby ti fungoval TurboDebugger.
Tehdy ještě neuměl načítat soubory s příponou .com.
Ten je tam taky

Tady je odkaz ke stažení:
https://uloz.to/…k/dosbox-rar!ZGplZwR1BJMwZQZ0AQZ2ZwD1MGx1n2IDraI+EwO4nQW2MTH2

tim pádem máš vše co potřebuješ, aby sis to mohl spustit a ladit doma
pod windows. Máš tam jak C:\BorlandC\BIN\TD.exe  což je turbodebugger 3.0
tak i samostatný TurboAssembler + Debugger 5.0 v C:\TASM\BIN\TD.EXE

Ty tak nějak nepíšeš co máš za GUI v tom vašem školním systému takže tak.
V debuggeru otevřeš výsledný exe soubor a stiskem F8 krokuješ.
Pomocí Alt+F5 zobrazíš uživatelskou obrazovku a zase zpět.

Jinak ta funkce Int21h/0x0A00 samozřejmě funguje pod msdossem ok.
Zadáš max. počet znaků co chceš načíst včetně <CR> na nultý bajt
paměťové oblasti a ona ti vyplní danou oblast tak, že na první bajt
ti dá počet skutčně načtených znaků a CR se nepočítá io když tam je
takže paměť musí být v tvém případě 100 + 1 + 1 + 1 + 1 neboli
chceš načíst 100 znaků, ale první 2 bajty jsou vyhrazené pro info
o délce počtu znaků a počtu skutečných znaků a poslední znak je <CR>
a zaním musíš dát $, aby si to mohl vytisknout. Já v tom příkladu
dávám $ místo CR protože aby nebyl chaos při tisku na obrazovce
a odřádkování mám zvlášť.

Funkce mov ax, cs a mov ds, ax používat samozřejmě nemusíš protože
všechno se dělá v jednom segmentu kodu.

2/ Další možností jak programovat je dělat to přímo v MSDosu což by bylo
asi nejlepší. Protože emulátor je fakt nahovno.
Tady máš WinImage. Asi bych použil tu
WinImage 6.9.0 Final ( 32-64bit ) Incl Serial - SceneDL
ve verzi x64:
https://uloz.to/…ge-6-a-8-rar!ZGOxBQR2ZGOxAwAvBQSuZmL3ZJL2L0SFG3WmnI9fLJgzGJWzBN==
klíč tam je a tady máš Image, kterou otevšeš v programu WinImage a v menu "disk" navolíš flešku a příkazem
"WriteDisk" zapíšeš image na flešku.
Hotovej bootovatelnej image s MSDOS 7.1 (WinME) je tady:

https://uloz.to/file/xIMmQ8hZOJkO/msdos7-image-for-usbkey-ima#!ZJSzAwR2ZJSxAmEuAJV5ATAzAGWzAH9eFx9DIKL3ERSsHmDmMD==

Takže dělá se to tak, že si někde seženeš USB flešku (všechno na ni smažeš) a zapíšeš na ni ten image.
a pak nabootuješ svuj počítač z tý flešky.
no a pak už pracuješ v originálním MSDOSu. :) takže tam máš adresář NC nebo NS5 a spustíš si Norton
commander abys to měl jako ve windows :)  to se dělá příkazem
cd NC
a pak
nc  
taky mužeš zkusit jestli ti pude myš a ovladač máš v adresáři Mouse
a zkus ten pro USB mouse buď pude OHCI nebo UHCI. musíš to zkusit
když se něco zasekne tak prostě restartuješ pc a je to. :)
Prostě MSDOS :)
Na tom image máš adresáš stejný _DOSBOX ale BorlandC i TurboAssembler si
už z něj musíš nainstalvoat sám z těch adresářů co tam sou - ty instalačky.
To zvládneš. :)

tady máš hromadu Dosovských programů
https://winworldpc.com/…ting-systems


no tak to je všechno.
jak vidíš vubec nepotřebuješ ten váš posranej emulátor klidně mužeš
pracovat na notebooku i na normálním pc doma :)


ještě nějaký drobný popis toho kodu:

org 100h

jmp  setup

setup:
        
       ; změna písmena :)

        lea bx, [msg_text]
        add bx, 3
        mov al, "Z"
        mov [bx], al

       ; tady se vypise uvodni text

        lea dx, [msg_text]
        mov ax,0x0900
        int 0x21

     ; tady se za texten udělá cr lf takže se odřádkuej

        lea dx, [msg_crlf]
        mov ax,0x0900
        int 0x21

loop_strt_01:
; tady se zadává počet znaků který chceme číst včetně CR
; ty tam asi budeš mít 101 takže 0x65 a počet se musí zapsat na první místo bloku paměti
; celkem pro každý řádek musíš mít 104 bytů a pro 600 řádků to je 62400 bytů
        lea bx, [data_rows]
        mov al, 0x12
        mov [bx], al

; tady se znaky načítaj fukci Int21h/0x0A
        mov ax, cs ; tyhle dva řádky tu bejt nemusí protože DS = CS pro com tiny model
        mov ds, ax
        lea dx, [data_rows]
        mov ax, 0x0a00
        int 0x21

;po načtení textu odřádkujeme
        lea dx, [msg_crlf]
        mov ax,0x0900
        int 0x21

; no tady se čte kolik si skutečně zapsal znaků a pak se na konec bloku místo znaku <CR>
; zapíše znak "$" aby se to dalo vytisknout sloužbou 0x09
        xor ax, ax
        lea bx, [data_rows]
        inc bx
        mov al, [bx]
        lea bx, [data_rows]
        add ax, bx
        mov bx, ax
        mov al, "$"
        add bx, 2
        mov [bx], al


; tady si přečteme kolik znaků se načetlo a číslo vytiskneme služnou Int21h/0x02
; protože se počítá od nultého bajtu na kjterým je kolik chceme přečíst
; tak na prvním bajtu je kolik sme skutečně přečetli
; no a proto se adresa musí o 1 zvýšit instrukci Inc bx  , kde bx je pro registr index
        xor ax, ax
        lea bx, [data_rows]
        inc bx
        mov al, [bx]

; chceme tisknout dekadickou číslici od 0 do 9 takže musíme přičíst
; "0" aby se zám zobrazil ASCII znak. tohle funguje JEN pro počet
;načítaných znaků od 0 do 9 .. což je logické ..jinak bych to vynechal
        mov  dl, al
        add  dl, "0"   ; Integer to single-digit ASCII character
        mov  ah, 02h
        int  21h

; zase odřádkujeme

        lea dx, [msg_crlf]
        mov ax,0x0900
        int 0x21

loop_end_01:

loop_strt_02:
; a tady už tiskene znaky so jsme načetli protože jsme již zapsali $ do
; dané oblasti paměti tak mužeme tiskout rovnou
; začíná se od bytu 2 protože nultý a první bajt jsou udaje o počtu
; požadovaých a načtenýc bajtů

        lea dx, [data_rows]
        add dx, 2
        mov ax,0x0900
        int 0x21
loop_end_02:

        jmp  endprog

error:  
       
endprog:

; no a tady končíme klasicky služnou 4c což se musí
        mov ax, 4c00h
        int 21h


section    .data

data_rows  db 100 DUP(0) ; tohle značí že je tu paměť pro 100 znaků ALE !!!
; ty sem musíš dát ve finále 62400 .... chápeš jo ?

msg_text DB 'Nacitani max. 600 radku textu.',0x24
msg_crlf DB 0x0D,0x0A,0x24
msg_err  DB 'Error.',0x24
msg_mem  DB 0x00, 0x00, 0x23, 0x24

r1_dw_001     DW  0
r1_dw_002     DW  0

data_pos_actual dw 0


no tak ten kod neini až tak těžkej ale ty to muší ještě dopsat
protže se po tobě chce nejprve přečíst max. 600 řádků a pak je vytisknout
takže to musíš dát do smyčky
obě smyčky už tam máš naznačený návěstíma loop_strt_01: loop_end_01: loop_strt_02: loop_end_02:
jinak jako koncový znak bych použil CTRL+Z, zkoušel sem to v dosu a funguje to skvěle.
Ctrl+C nebo Ctrl+Break ukončí zápis textu a nic se do paměti nezapíše.
Před návěstí loop_end_01: samozřejmě musíš dát kontorlu jestli v načteném
textu neni Ctrl+Z, čtením znak po znaku
jinak jako ukazatel kde si v bloku dat 62400 bytů bych asi použil proměnnou
data_pos_actual  která pojede od 0 a bude se zvětšovat po 104 bytech což je logické :)

přiznám se, že celou tvojí semestrální práci se mi místo tebe psát nechce
ale z toho co máš napsaný už to určitě zvládneš sám :)
prostě je jen potřeba doplnit ten cyklus pro načítání a kontrolu znaku Ctrl+Z
v načteném textu byte po bytu zase cyklem kterou umístíš před návěstí loop_end_01:

dole máš pár screenshotů třeba TurboDebugger abys viděl jak to vypadá  výhodou je, že vidíš co se do registrů zapisuje a pak tammáš screenshot práce toho kodu v MSDOSu t.j. zadávání několika znaků a zadání Ctrl+Z a taky jak vypadá reakce na Ctrl+C :)

*************************************************************


org 100h

jmp  setup

setup:

        lea bx, [msg_text]
        add bx, 3
        mov al, "Z"
        mov [bx], al

        lea dx, [msg_text]
        mov ax,0x0900
        int 0x21

        lea dx, [msg_crlf]
        mov ax,0x0900
        int 0x21

        lea bx, [data_rows]
        mov al, 0x12
        mov [bx], al

        mov ax, cs
        mov ds, ax
        lea dx, [data_rows]
        mov ax, 0x0a00
        int 0x21

        lea dx, [msg_crlf]
        mov ax,0x0900
        int 0x21

        xor ax, ax
        lea bx, [data_rows]
        inc bx
        mov al, [bx]
        lea bx, [data_rows]
        add ax, bx
        mov bx, ax
        mov al, "$"
        add bx, 2
        mov [bx], al


        xor ax, ax
        lea bx, [data_rows]
        inc bx
        mov al, [bx]

        mov  dl, al
        add  dl, "0"   ; Integer to single-digit ASCII character
        mov  ah, 02h
        int  21h


        lea dx, [msg_crlf]
        mov ax,0x0900
        int 0x21

        lea dx, [data_rows]
        add dx, 2
        mov ax,0x0900
        int 0x21


        jmp  endprog

error:  
       
endprog:
        mov ax, 4c00h
        int 21h


section    .data

data_rows  db 100 DUP(0)

msg_text DB 'Nacitani max. 600 radku textu.',0x24
msg_crlf DB 0x0D,0x0A,0x24
msg_err  DB 'Error.',0x24
msg_mem  DB 0x00, 0x00, 0x23, 0x24

r1_dw_001     DW  0
r1_dw_002     DW  0

Připojen obrázek.

Připojen obrázek.

Připojen obrázek.

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:b9f7:6c67:9e7b:79d4...–
JerryM0
Věrný člen
14. 1. 2023   #15
-
0
-
Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:b9f7:6c67:9e7b:79d4...–
JerryM0
Věrný člen
14. 1. 2023   #16
-
0
-

ještě takováý drobnost jak si mužeš všinout tak počet zadaných znaků se na obrázcích zobrazil jako dvojtečka ":" což je v ascii tabulce hned za 9 ale bohužel ten kod umí odpočítat jen od 0 do 9 :) a pak zohbrazuje další ASCII znaky v pořadí... ale pro jedoduchost to stačí

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:b9f7:6c67:9e7b:79d4...–
JerryM0
Věrný člen
14. 1. 2023   #17
-
0
-

aby tě náhodou nezmátlo "Windows Milenium" tak je to pravdu MSDOS 7.1 a NENI to pod windows .. tohle je jen hláška dosu ve WinME :) prostě tak to MS udělal

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:b9f7:6c67:9e7b:79d4...–
anonym
~ Anonymní uživatel
454 příspěvků
18. 1. 2023   #18
-
0
-

#14 JerryM
Tyjo super, moc děkuji. já dělám poprvé na úrovni procesoru a jsem v tom docela ztracený, a nemám nikoho kdo by mi to moc vysvětlil pořádně.

Jenom dotaz do kódu jsem doplnil ty cykly takže teďka mi to vypíše počet znaků a za to ten řádek pro každý řádek na vstupu, ale potřeboval bych alespoň pošťouchnout jakým směrem mám jít teď aby se vypisovalo pouze půlka toho řádku a půlka všech řádků na vstupu.

zkoušel jsem dělení toho data_rows ale to mi nějak nefunguje a tak nějak nevím jak dál. Díky.

zde můj nynější kód:


cpu 8086
segment code
..start mov bx,data
     mov ds,bx
     mov bx,stack
     mov ss,bx
     mov sp,dno
     jmp setup
     setup lea dx, [msg_text]
     mov ah, 9
     int 21h
     lea dx, [msg_crlf]
     mov ah, 9
     int 21h
loop_01 lea bx, [data_rows]
     mov al, 0x65
     mov [bx], al
     lea dx, [data_rows]
     mov ah, 0x0a
     int 21h
     lea dx, [msg_crlf]
     mov ah, 9
     int 21h
     xor ax, ax
     lea bx, [data_rows]
     inc bx
     mov al, [bx]
     lea bx, [data_rows]
     add ax, bx
     mov bx, ax
     mov al, "$"
     add bx, 2
     mov [bx], al
     xor ax,ax
     lea bx, [data_rows]
     inc bx
     mov al, [bx]
     mov dl, al
     add dl, "0"
     mov ah, 02h
     int 21h
     lea dx, [msg_crlf]
     mov ah, 9
     int 21h
loop_02 lea dx, [data_rows]
     add dx, 2
     mov ah, 09
     int 21h
     mov al, [data_rows+1]
     cmp al, 0
     jne loop_01
     jz end

end hlt
segment data
data_rows dw 62400
msg_text db 'Nacteni max. 600 radku textu',0x24
msg_crlf db 0x0A,0x24
msg_mem db 0x00, 0x00, 0x23, 0x24
r1_dw_001 dw 0
r1_dw_002 dw 0
data_pos_actual dw 0
segment stack
resb 16
dno: db ?
 

Nahlásit jako SPAM
IP: ...–
JerryM0
Věrný člen
18. 1. 2023   #19
-
0
-

pulka znaků na řádku se vypíše tak, že si přečteš počet skutečně zapsaných znaků a podělíš to dvěma instrukcí DIV neboli

MOV AX, pocet_zkutecne_zapsanych_znaků

MOV BL, 2

DIV BL

a výsledek je v AL, takže nastávají následující varianty:

1/ AL = 0 a pocet_zkutecne_zapsanych_znaků = 0  pak nevypíšeš nic

2/ AL = 0 a pocet_zkutecne_zapsanych_znaků > 0 pak nevypíšeš nic

3/ AL = 1 pak vypíšeš 1 znak

4/ AL > 1 pak vypíšeš počet znaků udaných v AL

takže z výše uvedeného vyplívá že stačí vypsat počet znaků, který je jako výsledek v AL :)  protože 1/2=0.5 a to neni celej jeden znak

a co se týče tý paměti data_rows  tak  zápis data_rows dw 62400 je evidentně špatně a má tam bejt data_rows db 62400 DUP(0). Protože alokuješ 62400 bytů a nikoliv 2x62400 bytů jak jsi napsal s použitím dw.

struktura každého řádku z 600 řádků kde každý řádek má 104 bytů je:

X,Y,ZNAKY,<CR>,Z

kde X je jeden byte - kolik znaků chceš načíst mínus 1

Y - kolik znaků si skutečně načel

ZNAKY - za sebou jdoucí sekvence bytů - znaků v ASCII 0..255 co jsi načel

<CR> - znak Enter 1 byte

Z - znak $ 1 byte jestlichceš mít tento znak tady

takže 104 x 600 = 62400 chápeš jo ?

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:5937:ddff:dae8:14b0...–
JerryM0
Věrný člen
18. 1. 2023   #20
-
0
-

je dobré vědět, že do školy chodíš proto aby ses to naučil a ten váš pan učitel vám všechno tohle měl dát

a vysvětlit ... docela by mě zajímalo na jakou školu chodíš sš ? nebo vš ????

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:5937:ddff:dae8:14b0...–
anonym
~ Anonymní uživatel
454 příspěvků
18. 1. 2023   #21
-
0
-

#19 JerryM
přesně toto mě právě napadlo podělit dvěma a vypsat ten počet co mi vyjde, ale problém je v tom zpracování toho. jak píšeš že ten divident má být pocet_zkutecne_zapsanych_znaků tak ten mám v těch 104 bytech na té pozici jak jsi popisoval Y že ? ale problém je že právě nevím jak tu informaci z toho dostat, plus jelikož chci první půlku tak musím po těch X bytech co my vyjde ukončit zase CR a $ ne ? měl jsem za to že vypisování na terminál co mám tak tam hodí takhle celý řádek ukončený tím CR a $ a nevypisuje to po bytech nebo jo ?

Jinak škola SŠ

Nahlásit jako SPAM
IP: ...–
JerryM0
Věrný člen
18. 1. 2023   #22
-
0
-

na sš je to poněkud složité zadání ... možná by si to měl panu učiteli říct ... jde o to , že student by měl být schopen úlohu vypracovat jen s informacemi které dostal v hodině nebo si musíš zajistit doučování ... a pan učitel by ti měl zajistit i konzultace

ty si ve 2 ročníku ? 3 ? 4 ?

aby si to správně pochopil tak v té paměti data_rows jsou jednotlivé řádky po 104 znacích za sebou takže musíš mít někde onen čítač pozice na aktuální řádek takže ten začání od adresy data_rows a pak se zvyšuje po 104 po přečtení každéno nového řádku bez ohledu na to kolik znaků si zpsal

takže dejme tomu že aktuální adresa bude v proměnné data_pos_actual a jak už jsem ti po sílal ten kod tak tam je zapsáno jak přečíst počet skutečně zapsaných znaků podle adresy data_pos_actual a to

        xor ax, ax
        lea bx, [data_pos_actual]
        inc bx
        mov al, [bx]
     

no a v al máš ten počet, a inc bx je zde proto že ten bajt udávající počet skutečně zapsaných znaků je vždy na prvním a nikoliv nulté pozici každého řádku o 104 bajtech

Nahlásit jako SPAM
IP: 90.182.62.–
JerryM0
Věrný člen
18. 1. 2023   #23
-
0
-

pokud je to na tebe příliš složité mužeš se na to jít ještě zeptat zástupce ředitele ... prostě zaklepeš na dveře a řekneš somu pánovi/pani, že si dostal (že dostáváte) na assembler zadání které svojí složitostí neodpovídá 2. ročníku šs a že tomu nerozumíš atd ... a on je povinen ti poradit co máš dělat ... ale podle mého názoru seš totálně dutej :) ...

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:5937:ddff:dae8:14b0...–
JerryM0
Věrný člen
18. 1. 2023   #24
-
0
-

jinak ten kod co si sem dal ti přece nemuže fungovat třeba "loop_02 lea dx, [data_rows]" je špatně.

má tam bejt "loop_02: lea dx, [data_rows]". zkoušel si to vubec ?

p5ekl8d8 se to

nasm  -f bin mujod.asm -o mujkod.com

nebo

nasm  -f bin mujod.asm -o mujkod.exe

1/ jestli ti to nejde zajdi si za školním poradcem

2/ ty máš doma počítač ? s Windows ? nebo doma vubec počítač nemáš ?

3/ přiznám se že nějak přestávám tomu tvýmu stylu rozumět

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:5937:ddff:dae8:14b0...–
anonym
~ Anonymní uživatel
454 příspěvků
18. 1. 2023   #25
-
0
-

#24 JerryM
Tam jde právě o to, že já se snažím dát dokupy to co mi radíš ty s tím jak funguje ten náš emulátor, protože když bych to hodil tak jak jsi mi to napsal ty do toho našeho tak mi to nebude fungovat. Tohle co jsem poslal tak je právě upravená verze toho co jsi poslal ty, aby to fungovalo v tom mém emulátoru. Je v tom zmatek, ale nějak se to snažím dát do kupy

Nahlásit jako SPAM
IP: ...–
anonym
~ Anonymní uživatel
454 příspěvků
18. 1. 2023   #26
-
0
-

#22 JerryM
Třeba toto v tom kódu co jsi poslal právě vůbec nevidiím:
        xor ax, ax
        lea bx, [data_pos_actual]
        inc bx
        mov al, [bx]

Je tam tato část, která mi počítá ten počet znaků ale tam je [data_rows] a ne [data_pos_actual] to nikde nevidím:

        xor ax, ax
        lea bx, [data_rows]
        inc bx
        mov al, [bx]

Nahlásit jako SPAM
IP: ...–
JerryM0
Věrný člen
18. 1. 2023   #27
-
0
-

tak se na ten váš posranej emulátor vyser a normálně to udělej v "normálním" MSDOSu. Pochop, že ten váš emulátor může bejt do značné míry omezenej. Normální MSDOS funguje bez problémů. Ano, děláš to pod NASM  a ten je nepatrně jinej od MASM, ale to nevadí.

Já nechápu, jajk můžeš říct, že ten program co sem ti dal v NASM nefunguje ??? máme přeci oba  stejnej překladač. já sem si ho stahoval odsud: 

https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/

a to verzi 2.16.

a ten muj program samozřejmě přeloží bez chyby. Pro kontrolu tammáš i turbo debugger. S timhle vybavením dělali statisíce lidí po celým světě desítky let a nikdo si až tak moc nestěžoval.

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:5937:ddff:dae8:14b0...–
JerryM0
Věrný člen
18. 1. 2023   #28
-
0
-

#26 user987465
ne tohle:

"        xor ax, ax
        lea bx, [data_pos_actual]
        inc bx
        mov al, [bx]

"

v tom kodu opravdu NENI. Protože ten kod neni celej. ANO, musíš si ho dodělat sám. Už sem ti to psal. Ty asi čekáš, že tvuj ukol do školy tady za tebe někdo udělá celý, ale to asi ne. Budeš muset vyjádřit nějakou vlastní snahu. Na tvém místě bych si nainstaloval ten DosBox a udělal bych to v něm protože to mužeš dělat normálně pod windows. Což je velká výhoda.

Přiznám se, že mě připadáš jako "rozbitá moucha". Občas v létě mi do pokoje vletíé moucha a je tak nějak divná. Moc nelítá a klidně do sebe nechává píchat :)  prostě jako kdyby byla "rozbitá" a moc nechápala svět kolem sebe.

Tvoje zadání sice není uplně jednoznačné, ale máš zadaný překladač NASM a pracovní mod 16 bitů a tím je to dané.

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:5937:ddff:dae8:14b0...–
JerryM0
Věrný člen
18. 1. 2023   #29
-
0
-

protože nemám tvuj emulátor a evidentně tvůj emulátor funguje jinak než standardní dos tak existují jenom dvě možnosti, buď si pomužeš sám nebo si nainstalulješ DOSBox a uděláme to v něm

https://www.dosbox.com/download.php?main=1

předpokládám že máš doma počítač s Windows 10 nebo 11

takže si to nainstaluješ a doplníš do konfiguračního souboru "DosBox Options" kterej má zástupce v menu start

následující řádky

mount c c:\_DOSBOX
c:
cd nc
nc

pak si stáhneš ten adresář _DOSBOX z uloz.to a rozbalíš to na tvuj disk C:

pak spustít dosbox a měl by si vidět něco jako je na obrázku níže

no a pak už mužeš normálně programovat jako v DOSu

postavíš si kurzor na ten soubor D5 a klávesou F4 ho začneš editovat

když ho zabřeš tak příkazem c z příkazový řádky ho přeložíš ... je to tam vidět

podle mě vám pan učitel dal zadání které převyšuje vaše momentální schopnosti ..

bejt tebou bych zašel za tim školním poradcem a stěžoval bych si

Připojen obrázek.

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:5937:ddff:dae8:14b0...–
JerryM0
Věrný člen
19. 1. 2023   #30
-
0
-

hm .. asi to vzdal ... njn ...

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:f52d:9e23:e2ec:a234...–
20. 1. 2023   #31
-
0
-

#30 JerryM
Takže podle toho kódu co jsi poslal, já doplním cyklus který mi naplní daný buffer všemi řádky, v tom cyklu musím do bx přidávat 104 aby se mi to nepřepisovalo a tím budu mít naplněný buffer tedy. tam si dám počítadlo všech řádků, které to naplnilo a podle toho pak vydělím kolik jich chci vypsat.

když mám tedy naplněný buffer všemi řádky, tak jak z toho bufferu budu číst ty dané "segmenty" po těch 104 bytech ?

Nahlásit jako SPAM
IP: 185.209.221.–
JerryM0
Věrný člen
20. 1. 2023   #32
-
0
-

obávám se, že s tvojí znalostí x86 assembleru bude sestavení úlohy téměř nemožné. možná bys měl trochu pár dní dostudovat vše potřebné.  za normálních okolností se základy assembleru na sš učí 1 rok s dotací 50-60 hodin, po 2 hodinách týdně. Po 1 roce výuky a tím pádem i po 1 roce domácího snažení se by si měl být schopen vypracovat úlohu, kterou děláš.

Ano, nejprve do bufferu načteš všech 600 řádků - pokud je uživatel zadá, jinak načteš jen tolik řádků kolik jich zadá a tím logicky nezadané znaky se nezapíší do bufferu a v bufferu budou nuly. Ale to nevadí. To že uživatel zapisuje poslední řádek se zjistí tak, že zadá znak Ctrl+Z neboli dec 26 neboli hex 1A podle

https://ascii.cl/

a symbolicky se to značí SUB.

Teprve po zadání všech řádků začneš řádky vypisovat jeden po druhém. To, že si narazil na konec řádků zjistíš např tím, že na k-tém řádků bude na prvním místě 0 místo požadované hodnoty 101 (neboli 100 znaků podle zadání a znak <CR>)

To co píšu je pouze opis tvého zadání, které si zcela jistě pochopil.

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:f1d3:feed:430e:a665...–
20. 1. 2023   #33
-
0
-

#32 JerryM
Mě jediné co by stačilo je alespoň trochu vysvětlit práci s tím bufferem, pak si myslím že už to zvládnu.

jak načíst do bufferu aby se to nepřepisovalo všechny ty řádky a pak jak číst z toho bufferu od začátku od prvního řádku.

Nahlásit jako SPAM
IP: 185.209.221.–
JerryM0
Věrný člen
20. 1. 2023   #34
-
0
-

kdyby sis nainstaloval ten DosBox a stáhnul ten adresář _DOSBOX a konapíroval ho k sobě na C: tak bychom ooba viděli to samé a bylo by to jednodušší.

Taže v příloze je obrázek, který ti v TurboDebuggeru ukazuje zápis jednoho znaku do prvního řádku bufferu.

A je to kod

        lea bx, [data_rows]
        mov al, 0x12
        mov [bx], al

jak mužeš vidět tak buffer data_rows začíná na adrese 0184h a řádkem

lea bx, [data_rows]

zapíšeš adresu 0184h do registru BX, který je zobrazený vpravo nahoře a hodnota 0184 tam opravdu je

dalším řádkem

mov al, 0x12

zapíšeš do AL hodnotu 12h a pak řádkem

mov [bx], al

zapíšeš hodnotu 12h na adresu udanou v BX takže dole na tam obrázku mužeš vidět že na adrese 0184h v datovém segmentu je už zapsaná hodnota 12 neboli řádek

ds:0180  4C  CD  21  00 12  00  00  00

hodnota 4C je na adrese 0180 a pak zleva doprava jsou adresy 0181, 0182 a 0183 a 0184.

Turbo debugger se používá proto, abys viděl co se děje a co je případně špatně.

takže to byl zápis hodnoty 12 do paměti no a čtení z paměti se dělá opačně neboli

        lea bx, [data_rows]
        mov al, [bx]

tady tedy z adresy na kterou ukazuje hodnota v registru BX - přečteš 1 bajt a zapíšeš ho do registru AL Takže to je čtení.

Protože ty musíš udělat cyklus čtení max. 600 řádků tak si musíš udělat v paměti nějakou pomocnou proměnnou jako čítač adresy a čítač řádků. A pak místo 

        lea bx, [data_rows]
        mov al, 0x12
        mov [bx], al

použiješ

        lea bx, [data_pos_act] 
        mov al, 0x12
        mov [bx], al

kde data_pos_act se počítá od 0 a po každám načteném řádku se zvětší o 104.

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:f1d3:feed:430e:a665...–
JerryM0
Věrný člen
20. 1. 2023   #35
-
0
-
Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:f1d3:feed:430e:a665...–
20. 1. 2023   #36
-
0
-

#34 JerryM
Takže jestli jsem to pochopil tak já si do data_pos_act dám adresu kde začíná ten buffer ještě před tím než tam vložím první řádek a pak tu adresu toho data_rows v každém cyklu zvyšuji o 104 aby se nepřepisovali řádky a když budu chtít číst tak v tom data_pos_act mám adresu začátku a tam z toho budu postupně číst a zase postupně přidávat 104 a tím se budu pohybovat po těch řádcích v bufferu je to tak ?

Nahlásit jako SPAM
IP: 185.209.221.–
JerryM0
Věrný člen
20. 1. 2023   #37
-
0
-

ano přesně tak. Nejprve naplníš data_pos_act adresou začátku datového bloku data_rows a pak k v každém cyklu přičítáš 104 data_pos_act.

               MOV data_pos_act, data_rows

loop_strt_01: 

              ... nějaký kod

             ADD data_pos_act, 104

            skok na loop_strt_01 pokud není splněna podmínka konce jinak skok na loop_end_01

loop_end_01:
 

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:f1d3:feed:430e:a665...–
JerryM0
Věrný člen
20. 1. 2023   #38
-
0
-

data_pos_act je tedy adresa v paměti a v prvním cyklu je identická s data_rows a pak se zvyšuje o 104 ale adresa data_rows se samozřejmě měnit nesmí protože to je počátek toho bloku dat

data_pos_act se deklaruje jako word takže zapíšeš novou proměnou typu:

data_pos_act    dw   0

data_pos_act tedy uchovává adresu v rozsazu 0..65535  ve dvou bajtech

mě jenom nepřestává udivovat co ste to za školu protože tohle je na žalobu .. chápeš jo ? pan učitel vám to musel nejdřív vysvětlit a ta uroveň na jaký si odpovídá min. 1 roku pečlivého studia asembleru x86...

a jestli vám to nevysvetlili tak je to na žalobu a finanční odškodnění ... a ten učitel by měl ze školy odejít ...

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:f1d3:feed:430e:a665...–
JerryM0
Věrný člen
20. 1. 2023   #39
-
0
-

takže ta celá první část by měla vypadat nějak takhle:

             MOV data_pos_act, data_rows

loop_strt_01: 

              načíst znaky pomocí funkce Int21 a ukazatel na začátek paměti je v data_pos_act

             zjistit počet skutečně zapsaných znaků z bajtu na pozici 1 (počítáno od nultého bajtu)

             zapsat za poslední zapsaný znak znak konce řetězce, což je  $ neboli ASCII 36 t.j. přepíšeš <CR>

             zjistit, jestli v zadaném řetězci náhodou není znak SUB (Ctrl+Z) a pokud ano skok na loop_strt_03: 

             přičíst k data_pos_act  hodnotu 104 a tim se posunout v bufferu na další řádek

             skok na loop_strt_01 pokud není splněna podmínka konce t.j. 600 řádků načteno

                   jinak skok na loop_end_01

loop_end_01:

loop_strt_03: 

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:f1d3:feed:430e:a665...–
JerryM0
Věrný člen
21. 1. 2023   #40
-
0
-

uz to máš ? tobě to ale trvá fakt ... podle mě je to docela obtížná uloha na 2. nebo 3. ročník sš.

na obrázku máš efekt zápisu 6 znaků na adresu 1AC, max. pocet znaku je 18 vcetne <CR> takže 17 a je videt že na adrese 1AD je hodnota 6 takže bylo zapsano 6 znaků a to 123456 a MSDOS doplnil posledni znak 0D neboli <CR>.

Připojen obrázek.

org 100h

jmp  run_program


run_program:


        ; nastavime adresu v bufferu na prvni radek a adresu ulozime na adresu [data_pos_act] do pameti 
        lea bx, [data_rows]         ; adresu bufferu uloz do bx
        mov [data_pos_act], bx      ; z bx uloz adresu bufferu na adresu [data_pos_act] v pameti

        ; inicializujeme citac radku ktery je na adrese [data_pos_cnt] v pameti 
        lea bx, [data_pos_cnt]      ; do bx uloz adresu promene data_pos_cnt v pameri
        mov al, 1  
        mov [bx], al                ; hodnotu v al uloz na adresu v pameti co je v registru bx

L_01:
        ; zjistime adresu aktualni radky v bufferu a presuneme ji do bx
        mov bx, [data_pos_act]      ; hodnota co je na adrese [data_pos_act] se presune do bx
        mov al, 101                 ;  max 101 znaku protože potrebujeme nacist 100 znaku + znak <CR>
        mov [bx], al

        ; zapis znaku z klavesnice do bufferu od adresy [data_pos_act]
        ;mov ax, cs
        ;mov ds, ax
        mov dx, [data_pos_act]      ; nebo taky: lds dx, [data_pos_act]
        mov ax, 0x0a00
        int 0x21

        mov ax, cs
        mov ds, ax

        ; odradkujeme na dalsi radek 
        lea dx, [msg_crlf]
        mov ax,0x0900
        int 0x21

        ; zapis $ misto <CR> na konec retezce, jedno misto nam jeste zbyde
        mov ax, cs
        mov ds, ax
        xor ax, ax
        mov bx, [data_pos_act]
        inc bx
        mov al, [bx]                    ; do al presun pocet skutecne nactenych znaku bez <CR>
        mov bx, [data_pos_act]
        add ax, bx
        mov bx, ax
        mov al, "$"
        add bx, 2                       ; tady je jen 2 takže znakem $ prepiseme znak <CR>
        mov [bx], al

        ; zjisti jestli v retezci neni Ctrl+Z a pokud ano ukonci nacitani
        xor ax, ax
        mov bx, [data_pos_act]
        inc bx
        mov al, [bx]                    ; zjisti pocet znaku v retezci 
        xor cx, cx
        mov cl, al                      ; pocet znaku v retezci do cl 
        
        mov si, [data_pos_act]          ; ukazatel na pamet do si a zvysime o 2 byty abychom se dostali na zacatek retezce
        add si, 2

        xor ax, ax 
L_10:
        ; cyklus prochazeni zapsaneho radku znaku, znak po znaku a hledame Ctrl+Z
        mov al, [si] 
        cmp al, 26                      ; znak Ctrl+Z, 26 = 1Ah, SUB, (nesplest si s Ctrl+Y !!!)
        je L_30                         ; ANO, Ctrl+Z detekovan, prechazime na vypis radku, skok na L_30
        dec cl 
        cmp cl, 0
        je L_20                         ; dosahli jsme max poctu zadanych znaku ?, pocitano bez <CR>, ano, skok na L_20
        inc si                          ; nedodahli, posun ukazatel a jdeme na dalsi znak
        jmp L_10
        
L_20:
        ; inkrementace ukazatele v bufferu
        mov bx, [data_pos_act]          ; precteme aktualni adresu v bufferu z adresy [data_pos_act]
        add bx, 104                     ; zvysime o 104 znaku na dalsi radek 
        mov [data_pos_act], bx          ; zapiseme ukazatel na adresu [data_pos_act] v pameti           

        ; kontrola max poctu zadavanych radku, t.j. nesmi byt vetsi nez 600
        mov bx, [data_pos_cnt]          ; precteme hodnotu z adresy [data_pos_cnt] v pameti do bx
        inc bx
        cmp bx, 601                     ; uz bychom v dalsim kole byli na 601 radku ? 
        je L_30                         ; ano, ukonci zadavani a skok na L_30
        mov [data_pos_cnt], bx          ; zapiseme cislo nasledujiciho nacitaneho radku na adresu [data_pos_cnt] v pameti 
       
        jmp L_01 ; opakujeme zadavani dalsim radkem 
        
L_30:
        ; tady vypiseme polovinu radku a polovinu znaku z kazdeho radku  
        ; nyni je tedy buffer plny znaku a na adrese [data_pos_cnt] v pameti je pocet skutecne nactenych radku

        ; nastavime opet adresu v bufferu na prvni znak prvniho radku a adresu ulozime na adresu [data_pos_act] do pameti 
        lea bx, [data_rows]         ; adresu bufferu uloz do bx
        mov [data_pos_act], bx      ; z bx uloz adresu bufferu na adresu [data_pos_act] v pameti

        ; precteme pocet skutecne nactenych radku 
        mov bx, [data_pos_cnt]       ; do bx uloz pocet skutecne nactenych radku 
        

        ; ... a tady bude vypis poloviny poctu nactenych radku a polovina znaku z kazdeho radku
        ; ... 
        ; ...  
L_40:


L_50:

L_60:

L_70:





        jmp  endprog

error:  
       
endprog:
        ; ukonceni programu - povinna sekvence int21h/4c00h 
        mov ax, 4c00h  
        int 21h


section	.data

data_rows  db 62400 DUP(0)  ; souvisly blok pameti 62400 bytu, 600x104=62400, vynulovano=DUP(0)

msg_text DB 'Nacitani max. 600 radku textu.',0x24
msg_crlf DB 0x0D,0x0A,0x24
msg_err  DB 'Error.',0x24
msg_mem  DB 0x00, 0x00, 0x23, 0x24

data_pos_act DW 0
data_pos_cnt DW 0

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:a9d6:2e74:b20d:5e31...–
JerryM0
Věrný člen
21. 1. 2023   #41
-
0
-

jinak pokud pouziješ dosbox a turbodebugger tak použij tu verzi 5, která je lepší , je v adresáři c:\_DOSBOX\TASM\BIN\   no a alt+F5 zobrazuje/skryva uzivatelskou obrazovku a klavesou TAB se presouvas po oknech TD. obcas to v dosboxu blbne ale da se to prezit :)

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:a9d6:2e74:b20d:5e31...–
21. 1. 2023   #42
-
0
-

V pořádku děkuji za ochotu, nechám to teďka chvíli ležet doučím se to, jelikož mám vážně velké mezery a nemá cenu se vtom jen tak plácat a pustím se do toho znovu

Nahlásit jako SPAM
IP: 2.56.253.–
midealer0
Duch
24. 1. 2023   #43
-
0
-

mice

Nahlásit jako SPAM
IP: 2401:4900:1c53:2d8:6821:640d:f92e:8955...–
[url=https://midealership.com.co]MI franchise[/url]
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 19 hostů

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý