📄 e3-16.asm
字号:
;%ifdef ELKSLookBackward: ;set di to 1 before EOL (0Ah) i.e., 2 before start of next line push cx push bx xor bx,bx cmp byte[di-1],NEWLINE ;at BOL ? jz LBa3 cmp byte[di],NEWLINE ;at EOL ? jnz LBa1 dec di ;at EOL ? start search 1 char earlier inc bx ;increase counterLBa1: mov cx,9999 mov al,NEWLINE std repne scasb mov ax,9997 sub ax,cx add ax,bx pop bx pop cx jmp short CheckBOF;-------LBa3: xor ax,ax pop bx pop cx dec di dec di jmp short CheckBOF%elseLookBackward:push cx mov cx,9999 mov al,0ah std repne scasb mov ax,9997 sub ax,cx pop cx jmp short CheckBOF%endifLookForward:push cx mov cx,9999%ifdef ELKS mov al,NEWLINE%else mov al,0dh%endif cld repne scasb mov ax,9998 sub ax,cx pop cx dec diCheckEOF:cmp di,bp ;ptr is eof-ptr? jnz CheckEnd ;Z flag if eof jmp short CheckENumCheckBOF:cmp di,sot ja CheckEndCheckENum:mov byte [numeriere],1 ;if bofCheckEnd:ret;-------LookPgBegin:mov dx,[kurspos2] ;called by DispNewScreen to get sync with 1st char on screen mov cl,dh ;called by KeyCtrlQE (go upper left) mov ch,0 inc cl jmp short LookPU2;-------LookLineUp:mov cx,2 ;2 lines: THIS line and line BEFORE dec word [linenr] jmp short LookPU2;-------LookLineDown:mov cx,2 ;2 lines: THIS and NEXT line inc word [linenr] jmp short LookPD2;-------LookPageUp:mov cx,[lines] sub [linenr],cx inc word [linenr] ;PgUp,PgDown one line lessLookPU2:call LookBackward jb LookPUEnd ;if BOF%ifdef ELKS inc di%endif loop LookPU2 ;after loop di points to char left of 0ah%ifdef ELKS dec di%endifLookPUEnd:inc di inc di ;now points to 1st char on screen or line ret;-------LookPgDown:mov cx,[lines] add [linenr],cx dec word [linenr]LookPD2:call LookForward jz LookPDEnd ;(jmp if EOF)%ifndef ELKS inc di%endif inc di ;1st char next line loop LookPD2%ifndef ELKS dec di%endif dec di ;last char last lineLookPDEnd:sub di,ax ;1st char last line ret;----------------------------------------------------------------------;; some more CHECK functions;CheckBlock:cmp byte [showblock],1 ;returns CY if error else ok: NC jc CheckBlockEnd mov si,[blockende] cmp si, sot jb CheckBlockEnd mov si,[blockbegin] ;side effect si points to block begin cmp si, sot jb CheckBlockEnd cmp [blockende],si ;^KK > ^KB ..OK if above!CheckBlockEnd:ret;-------CheckImBlock:cmp [blockbegin],di ;^KB mark > di ? ja CImBlockEnd ;OK cmp di,[blockende] ;di > ^KKCImBlockEnd:ret ;output:cy fehler / nc ok inside block;-------CheckMode:%ifdef ELKS cmp byte [di],NEWLINE ;checks for INSERT status%else cmp byte [di],0dh%endif jz ChModeEnd cmp byte [insstat],1ChModeEnd:ret ;Z flag for ins-mode;-------; a special case called by DeleteByteCheckMarker;CheckMarker: ;dx is blockbegin (^KB) ;bx is deleate area end --- di delete area start cmp di,dx ;delete area start < ^KB marker ? ja CMEnd ;no cmp bx,dx ;yes, but delete area end > ^KB ? jl CMEnd ;no mov dx,di ;yes so block start (^KB) to delete area startCMEnd: ret;----------------------------------------------------------------------;; C O U N T functions; to return number of chars up to some place; (all of them are wrappers of Look....functions anyway);CountToLineEnd:push di call LookForward pop di ret ;ax=chars up to line end;-------CountColToLineBeginVis: ;counts columns represented by chars in ax call CountToLineBegin ;i.e. EXPAND any TAB chars found push si xor dx,dx mov si,di ;startpoint sub si,ax ;to bol dec siCCV1: inc si cmp si,di jae CCVend cmp byte [si],TABCHAR jz CCVTab inc dx ;count visible chars jmp short CCV1CCVTab: call SpacesForTab ;return space_up_to_next_tab in ah add dl,ah ;FIXME: now using 8 bits only jmp short CCV1CCVend: mov [ch2linebeg],dx ;ch2linebeg: interface to Key... functions mov ax,dx ;ax: interface to DispNewScreen pop si ret;-------CountToLineBegin:push di ;output ax=chars up there call LookBackward mov si,di ;side effect: set di to 1st char in line pop di ret;-------CountToWordBegin: ;output ax=chars up there mov si,diCountNLoop:inc si%ifdef ELKS cmp byte [si],NEWLINE%else cmp byte [si],0dh%endif jz fertig2 cmp byte [si],SPACECHAR ;below SPACE includes tab chars jbe CountNLoop cmp byte [si-1],2fh ja CountNLoop fertig2:mov ax,si sub ax,di ;maybe =0 ret;---------------------------------------------------------------------;; some CURSOR control functions;GoUp: mov al,0 mov ah,-1 jmp short UpDownGoDown: mov al,byte [lines] dec al mov ah,1UpDown: mov dx,[kurspos2] ;former was call getkurspos cmp dh,al jz Goret add dh,ah ;ONLY here we change curent line of cursor jmp short SetKursPos Goret: ret ;-------; set cursor to some desired places;KursorStatusLine:mov dh,[lines] mov dl,stdtxtlen jmp short SetKursPosRestKursPos:mov dx,[kurspos]SetKursPos:mov [kurspos2],dx ;saves reading cursor pos (0,0)%ifndef ELKSsys_writeKP: push ax mov ah,2 mov bh,0 int 10h pop ax ret%else ;---------------------------------------------------------------sys_writeKP: push ax push bx push cx push dx push si push di push bp call make_KPstr mov bx,stdout ;file handle (stdout) mov cx,setkp ;second argument: pointer to message to write mov dx,setkplen ;third argument: message length call WriteFile pop bp pop di pop si pop dx pop cx pop bx pop ax ret;-------; make ESC sequence appropriate to most important terminals;make_KPstr: inc dl ;expecting cursor pos in dh/dl (0,0) inc dh ;both line (dh) col (dl) are counted now from 1 cld mov di,setkp ;build cursor control esc string db 27,'[000;000H' mov ax,0x5B1B ;line starts at setkp+2, col starts at setkp+6 stosw mov ax,'00' stosw mov ax,'0;' ;init memory stosw mov ax,'00' stosw mov ax,'0H' ;init memory stosw mov di,setkp+1+3 ;line end xor ax,ax mov al,dh ;DH=line push dx call IntegerToAscii ;make number string pop dx cld mov di,setkp+1+3+4 ;column end xor ax,ax mov al,dl ;DL=col jmp IntegerToAscii %endif;-----------------------------------------------------------------------;; functions for INSERTING, COPYING and DELETING chars in text;InsertByte:or ax,ax ;input: ax = #bytes , di = ptr jz Ins3 mov byte [changed],CHANGED mov cx,MAXLEN ;max_len+offset-eofptr=freespace(cx) add cx,sot sub cx,bp cmp cx,ax ;cmp freespace - newbytes ;>= 0 ok/ NC <0 bad / CY jnc SpaceAva mov word[errno],ERRNOMEM call DosError call RestKursPos stc retSpaceAva:push di mov si,bp ;end of text mov cx,bp add cx,ax sub cx,di ;space count mov di,bp add di,ax std rep movsB pop di;------- add bp,ax cmp di,[blockende] ja Ins1 add [blockende],axIns1: cmp di,[blockbegin] ja Ins2 add [blockbegin],axIns2: clcIns3: ret ;output:nc=ok / cy=bad;-------CopyBlock:call CheckBlock ;copy block, called by ^KC, ^KV jc MoveBlEnd call CheckImBlock jc MoveBlEnd mov ax,[blockende] sub ax,si ;block len call InsertByte jc MoveBlEnd mov si,[blockbegin]MoveBlock:push di ;input : si=^KB di=current mov cx,ax cld rep movsb pop di clc ;nocarry->okMoveBlEnd:ret;-------DeleteByteCheckMarker: ;di points to begin mov bx,di add bx,ax mov dx,[blockbegin] call CheckMarker mov [blockbegin],dx mov dx,[blockende] call CheckMarker mov [blockende],dxDeleteByte:or ax,ax ;input in ax jz DeleteByteEnd mov byte [changed],CHANGED push di push si mov cx,bp ;end sub cx,di mov si,di add si,ax sub cx,ax add cx,3 shr cx,1 cld rep movsW pop si pop di sub bp,ax cmp di,[blockende] jae Del1 sub [blockende],axDel1: cmp di,[blockbegin] jae DeleteByteEnd sub [blockbegin],axDeleteByteEnd:ret;---------------------------------------------------------------------; read a file name for block operations; expecting message text ptr in dx;getBlockName: push ax push bx push cx push dx push si push di push bp call WriteMess9MachRand mov cx,blockpath mov dx,maxfilenamelen call InputString ;cy if empty string pushf call RestKursPos popf pop bp pop di pop si pop dx pop cx pop bx pop ax ret;----------------------------------------------------------------------;; functions reading/writing text or blocks from/into files;NewFile:call InitVars call DelEditScreen or si,si jz noarg cld mov di,filepathccc: lodsb stosb or al,al jnz ccc jmp short GetFile;-------noarg: mov dx, filename call WriteMess9MachRand mov cx,filepath mov dx,maxfilenamelen call InputString jc NFEnd2 ;empty string not allowed here;-------GetFile:mov bx,filepath xor cx,cx ;i.e O_RDONLY call OpenFile mov di,sot mov bp,di mov bx,ax ;file descriptor js NewFileEnd OldFile:%ifdef SYS_FSTAT call Fstat ;kernel returns error 38 js DosEjmp0 mov ax,[fstatbuf+8] ;better define some structure and ax,777q mov [perms],ax%endif;------- mov dx,MAXLEN mov cx,di ;sot call ReadFile mov dx,ax ;bytes read js DosEjmp0 ;DosError call CloseFile js DosEjmp0 ;DosError;------- mov word [errno],ERRNOMEM cmp dx,MAXLEN ;MAXLEN read amount is too much jnz XX2 jmp DosErrorXX2:;------- mov bp,sot ;eof_ptr=filesize+start_of_text add bp,dxNewFileEnd:%ifdef ELKS mov byte [ds:bp],NEWLINE ;eof-marker%else mov word [ds:bp],0a0dh%endif clcNFEnd2: ret;-------; save file (called by ^KS,^KX);SaveFile:cmp byte [changed],UNCHANGED jz SaveFile3 ;no changes: nothing to save mov dx,filesave call WriteMess9 mov cx,O_WRONLY_CREAT_TRUNC mov bx,filepath%ifdef ELKS mov dx,[perms] call OpenFile%else call CreateFile%endifDosEjmp0:js DosEjmp ;DosError mov cx,sot ;cx=bof mov dx,bp ;eofSaveFile2:sub dx,cx ;dx=filesize= eof-bof mov bx,ax ;file descriptor call WriteFile js DosEjmp ;DosError mov word[errno],ERRNOIO ;just in case of.... cmp ax,dx ;all written? jz XX4 jmp DosErrorXX4: call CloseFile js DosEjmp ;DosErrorSaveFile3:ret;------------------------------; save block (called by ^KW);SaveBlock:mov dx,blocksave call getBlockName jnc XX3 jmp DE2XX3: mov cx,O_WRONLY_CREAT_TRUNC mov bx,blockpath%ifdef ELKS mov dx,[perms] call OpenFile%else call CreateFile%endif js DosEjmp ;DosError mov cx,si ;= block begin mov dx,[blockende] jmp short SaveFile2;-------; read a block into buffer (by ^KR);ReadBlock:mov dx,blockread call getBlockName jnc XX5 jmp DE2XX5: xor cx,cx ;i.e O_RDONLY mov bx,blockpath call OpenFileDosEjmp:js DosError mov bx,ax ;file desc mov dx,2 call SeekFile ;end js DosError push dx push ax xor dx,dx call SeekFile ;home pop ax pop dx js DosError or dx,dx mov word [errno],ERRNOMEM jnz DosError push ax call InsertByte pop dx ;file size jc DosError mov cx,di ;^offset akt ptr call ReadFile js preDosError ;to delete inserted bytes (# in dx) mov cx,ax ;bytes read call CloseFile js DosError mov word[errno],ERRNOIO ;just in case of.... cmp dx,cx ;all read? jnz DosErrorReadBlock2:jmp NewFileEnd;------------------------------------------------------------;; Error handler;preDosError:mov ax,dx ;count bytes call DeleteByte ;delete space reserved for insertationDosError:push di mov di,error+8 ;where to store ASCII value of errno mov ax,[errno] push ax call IntegerToAscii ;TODO: print a string instead of errno value pop cx cmp cx,MAXERRNO ja DE0 mov di,errmsgs call LookPD2 ;look message x in line number x mov si,di mov di,error+9 mov ax,' :' stosw mov cx,80 ;max strlen / compare errlen equ 100 rep movsbDE0: mov dx,error pop diDE1: call WriteMess9 call GetCharDE2: call RestoreStatusLine stc ;error status ret;----------------------------------------------------------------------;; some GENERAL helper functions;IntegerToAscii: mov cx,10 std mov bx,ax ;bx=quotientConnum1:mov ax,bx sub dx,dx div cx mov bx,ax ;save quotient (new low word) mov al,dl call Hexnibble or bx,bx jne Connum1 cld retHexnibble:and al,0fh add al,'0' cmp al,':' jb noHex add al,7 ;(should never be due cx==10)noHex: stosb ret;-------;; GetAsciiToInteger reads integer value from keyboard (only > 0);GetAsciiToInteger:call WriteMess9MachRand mov cx,blockpath mov dx,maxfilenamelen call InputString call AskFor_Ex ;repair status line & set cursor pos / preserve flags mov ax,0 ;preserve flags mov cx,ax mov bl,9 ;bl == base-1 jc AIexit2 mov si,blockpath cldAIload: lodsb sub al,'0' js AIexit cmp al,bl ja AIexit mov dx,cx shl cx,3 ;* 8 add cx,dx ;+ 1 add cx,dx ;+ 1 add cx,ax ;+digit jmp short AIloadAIexit: or cx,cx ;ret ecxAIexit2:ret ;CY or ZR if error;-------;; expects curent column in dx; returns # spaces up to next tabulated location in AH;SpacesForTab:push cx mov ax,dx mov cl,TAB div cl neg ah ;ah = modulo division add ah,TAB ;TAB - pos % TAB pop cx ret;-------; a little helper for SetColor* functions;IsShowBlock:cmp byte [showblock],0 je SBlock
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -