📄 getc.inc
字号:
;; $Id$;; -----------------------------------------------------------------------;; ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved;;;; This program is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,;; Boston MA 02111-1307, USA; either version 2 of the License, or;; (at your option) any later version; incorporated herein by reference.;;;; -----------------------------------------------------------------------;;;; getc.inc;;;; Simple file handling library (open, getc, ungetc);;;; open,getc: Load a file a character at a time for parsing in a manner; similar to the C library getc routine. Only one simultaneous; use is supported. Note: "open" trashes the trackbuf.;; open: Input: mangled filename in DS:DI; Output: ZF set on file not found or zero length;; openfd: Input: file handle in SI; Output: none;; getc: Output: CF set on end of file; Character loaded in AL;open: call searchdir jz openfd.retopenfd: pushf mov [FBytes],ax mov [FBytes+2],dx mov eax,[FBytes] add eax,SECTOR_SIZE-1 shr eax,SECTOR_SHIFT mov [FSectors],eax ; Number of sectors mov [FNextClust],si ; Cluster pointer mov ax,[EndOfGetCBuf] ; Pointer at end of buffer -> mov [FPtr],ax ; nothing loaded yet popf ; Restore no ZF.ret: retgetc: stc ; If we exit here -> EOF mov ecx,[FBytes] jecxz .ret mov si,[FPtr] cmp si,[EndOfGetCBuf] jb .loaded ; Buffer empty -- load another set mov ecx,[FSectors] cmp ecx,trackbufsize >> SECTOR_SHIFT jna .oksize mov ecx,trackbufsize >> SECTOR_SHIFT.oksize: sub [FSectors],ecx ; Reduce remaining clusters mov si,[FNextClust] push es ; ES may be != DS, save old ES push ds pop es mov bx,getcbuf push bx call getfssec ; Load a trackbuf full of data mov [FNextClust],si ; Store new next pointer pop si ; SI -> newly loaded data pop es ; Restore ES.loaded: lodsb ; Load a byte, increment SI mov [FPtr],si ; Update next byte pointer dec dword [FBytes] ; Update bytes left counter clc ; Not EOF.ret: ret;; ungetc: Push a character (in AL) back into the getc buffer; Note: if more than one byte is pushed back, this may cause; bytes to be written below the getc buffer boundary. If there; is a risk for this to occur, the getcbuf base address should; be moved up.;ungetc: mov si,[FPtr] dec si mov [si],al mov [FPtr],si inc dword [FBytes] ret;; skipspace: Skip leading whitespace using "getc". If we hit end-of-line; or end-of-file, return with carry set; ZF = true of EOF; ZF = false for EOLN; otherwise CF = ZF = 0.;; Otherwise AL = first character after whitespace;skipspace:.loop: call getc jc .eof cmp al,1Ah ; DOS EOF je .eof cmp al,0Ah je .eoln cmp al,' ' jbe .loop ret ; CF = ZF = 0.eof: cmp al,al ; Set ZF stc ; Set CF ret.eoln: add al,0FFh ; Set CF, clear ZF ret;; getint: Load an integer from the getc file.; Return CF if error; otherwise return integer in EBX;getint: mov di,NumBuf.getnum: cmp di,NumBufEnd ; Last byte in NumBuf jae .loaded push di call getc pop di jc .loaded stosb cmp al,'-' jnb .getnum call ungetc ; Unget non-numeric.loaded: mov byte [di],0 mov si,NumBuf ; Fall through to parseint;; parseint: Convert an integer to a number in EBX; Get characters from string in DS:SI; Return CF on error; DS:SI points to first character after number;; Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+K, val+M;parseint: push eax push ecx push bp xor eax,eax ; Current digit (keep eax == al) mov ebx,eax ; Accumulator mov ecx,ebx ; Base xor bp,bp ; Used for negative flag.begin: lodsb cmp al,'-' jne .not_minus xor bp,1 ; Set unary minus flag jmp short .begin.not_minus: cmp al,'0' jb .err je .octhex cmp al,'9' ja .err mov cl,10 ; Base = decimal jmp short .foundbase.octhex: lodsb cmp al,'0' jb .km ; Value is zero or al,20h ; Downcase cmp al,'x' je .ishex cmp al,'7' ja .err mov cl,8 ; Base = octal jmp short .foundbase.ishex: mov al,'0' ; No numeric value accrued yet mov cl,16 ; Base = hex.foundbase: call unhexchar jc .km ; Not a (hex) digit cmp al,cl jae .km ; Invalid for base imul ebx,ecx ; Multiply accumulated by base add ebx,eax ; Add current digit lodsb jmp short .foundbase.km: dec si ; Back up to last non-numeric lodsb or al,20h cmp al,'k' je .isk cmp al,'m' je .ism dec si ; Back up.fini: and bp,bp jz .ret ; CF=0! neg ebx ; Value was negative.done: clc.ret: pop bp pop ecx pop eax ret.err: stc jmp short .ret.isk: shl ebx,10 ; x 2^10 jmp short .done.ism: shl ebx,20 ; x 2^20 jmp short .done section .bss alignb 4NumBuf resb 15 ; Buffer to load numberNumBufEnd resb 1 ; Last byte in NumBufFBytes resd 1 ; Number of bytes left in getc fileFSectors resd 1 ; Number of sectors in getc fileFNextClust resw 1 ; Pointer to next cluster in d:oFPtr resw 1 ; Pointer to next char in buffer;; unhexchar: Convert a hexadecimal digit in AL to the equivalent number;; return CF=1 if not a hex digit; section .textunhexchar: cmp al,'0' jb .ret ; If failure, CF == 1 already cmp al,'9' ja .notdigit sub al,'0' ; CF <- 0 ret.notdigit: or al,20h ; upper case -> lower case cmp al,'a' jb .ret ; If failure, CF == 1 already cmp al,'f' ja .err sub al,'a'-10 ; CF <- 0 ret.err: stc.ret: ret;;; getline: Get a command line, converting control characters to spaces; and collapsing streches to one; a space is appended to the; end of the string, unless the line is empty.; The line is terminated by ^J, ^Z or EOF and is written; to ES:DI. On return, DI points to first char after string.; CF is set if we hit EOF.;getline: call skipspace mov dl,1 ; Empty line -> empty string. jz .eof ; eof jc .eoln ; eoln call ungetc.fillloop: push dx push di call getc pop di pop dx jc .ret ; CF set! cmp al,' ' jna .ctrl xor dx,dx.store: stosb jmp short .fillloop.ctrl: cmp al,10 je .ret ; CF clear! cmp al,26 je .eof and dl,dl jnz .fillloop ; Ignore multiple spaces mov al,' ' ; Ctrl -> space inc dx jmp short .store.eoln: clc ; End of line is not end of file jmp short .ret.eof: stc.ret: pushf ; We want the last char to be space! and dl,dl jnz .xret mov al,' ' stosb.xret: popf ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -