Yeah! That seems to work quite well. I made a couple of minor changes - mostly a matter of "style"... I returned "readcnt" as an exit code, so we can read it with "echo $?" instead of using a debugger to see it. Strictly speaking, only bl is relevant as an exit code, the upper bits of ebx are ignored. So long as the number of reads doesn't exceed 255, this works.
If we're actually reading from the keyboard, sys_read returns every time we hit "enter". I wasn't sure what happens when it's redirected... which is why I did the above. Turns out, as I expected, but wasn't sure, it keeps reading past the linefeed for the full size of the buffer (I temporarily reduced the size of the buffer to check out what happened with multiple reads).
I tried making your variables "local" by simply prepending ".". I wasn't sure this would work with the variables in .data... but it does. If, in the course of modifying the code, you introduced a "non-local" label between 'em, this would break. A more "robust" way would be to put "readfile" and its variables in a separate file ("modular programming" rather than "monofile programming" - I advocate "modular", but often do "monofile"). We'd want to pass the buffer and its size as parameters, I imagine. We could leave these "hard coded", too, but would have to declare 'em "global" in the calling file and "extern" in the called file. Better to pass 'em as parameters, I think. Dunno what to do with "readcnt" in this case, but it's only a "temporary diagnostic" anyway. I may try an example of this, just to do it...
This is not much different from what you posted...
; nasm -f elf32 myfile.asm
; ld -o myfile myfile.o
; invoke as ./test < inputfilename
; or just ./test
; if you use it with console stdin then type control d to end input
;
section .data
writmsg db "Char was: "
; we can give the "target" a name, instead of counting bytes...
the_char db 0,10
; this won't screw up our "length"
writmlen equ $-writmsg
readcnt dd 0 ; diagnostic, will remove
section .bss
buffalen equ 8192 ; 8k
readbuff resb buffalen ; input buffer area
section .text
global _start
;------------------------------------------------------------------------;
; test readchar routine. ;
;------------------------------------------------------------------------;
_start: nop
call readchar ; al will contain char if one is available
jc exit0000 ; carry flag will be set in readchar
; if error condition or EOF
mov ecx,writmsg ; addr of text to write
; instead of "+ 10", we can use a "named variable"
; mov byte [writmsg+10],al ; move char to output message
mov byte [the_char],al ; move char to output message
mov edx,writmlen ; number of bytes to write
mov eax,4 ; syscall = write
mov ebx,1 ; fd 1 = stdout
int 80h ; issue write syscall
nop
jmp _start ; repeat until no more data
;--------------------------------------------------------------------------------------;
; return one character at a time to the caller from stdin. char is ;
; returned in al. carry flag is set for error condition, cleared for ;
; normal completion a la FreeBSD. ;
;--------------------------------------------------------------------------------------;
readchar push ebx ; save caller registers
push ecx
push edx
;; i want to compare the contents of readcurr and readlast
;; is this the right way?
mov eax,[.readcurr] ; get contents of readcurr
cmp eax,[.readlast] ; any data remaining in buffer?
ja .readfil ; no, issue read syscall
mov eax,[.readcurr] ; load eax with addr of current byte in buffer
mov al,[eax] ; save byte at readcurr for caller
inc dword [.readcurr] ; inc input buffer pointer
clc ; indicate normal completion
jmp .readexi ; restore and return
.readfil mov eax,3 ; syscall = read
mov ebx,0 ; fd 0 = stdin
mov ecx,readbuff ; address of buffer
mov edx,buffalen ; number of bytes to read (max)
int 80h ; issue syscall
cmp eax,0 ; did read return an error or eof?
jna .readerr ; yes, set cf and bail out
inc dword [readcnt] ; diagnostic counter of successful reads
;; save the address of readbuff in readcurr
;; is this the right way to do this?
; yeah. could also have used "mov edx, readbuff"
lea edx,[readbuff]
mov dword [.readcurr],edx
;; save the address of the last input byte in readlast
;; is this the right way to do this?
; yeah... we already had "readbuff" in edx
; so could have skipped doing it again... no harm
lea edx,[readbuff]
add edx,eax
dec edx
mov dword [.readlast],edx
mov eax,[.readcurr] ; load eax with addr of current byte in buffer
mov al,[eax] ; save byte at readcurr for caller
;; is this the right way to advance readcurr to next char in buffer?
; yeah.
inc dword [.readcurr] ; increment input buffer pointer
clc ; clear carry flag to indicate normal completion
jmp .readexi ; go to exit
.readerr stc ; set carry flag to indicate error
.readexi pop edx ; restore input registers
pop ecx
pop ebx
ret ; return to caller
;-----------------------------------------------------------------------------------------------;
; data for readchar procedure. Can I make these names local to readchar ;
; even though they are in .data? OO assembly? Would be way cool! ;
; yeah, kinda...
;-----------------------------------------------------------------------------------------------;
section .data
.readcurr dd 01h ; address of next available byte in
; input buffer (readbuff)
.readlast dd 00h ; address of last available byte in
; input buffer (readbuff)
section .text
align 4
;------------------------------------------------------------------------;
; exit to system ;
;------------------------------------------------------------------------;
exit0000 mov eax,1 ; exit syscall
; mov ebx,0 ; return code zero
; further diagnostics...
mov ebx, [readcnt] ; return count...
; we can display exit-code with "echo $?"
int 80h ; exit
Best,
Frank