A Working Console

A Working Console

Robbert Haarman

2005-04-26


Introduction

In the previous chapter, we developed a kernel with a keyboard driver that printed the characters that the user typed on the screen. In this chapter, we will save the characters to a buffer and implement a function that reads a character from this buffer if any are available. This will allow us to write simple interactive programs.


The Input Buffer

We will use a circular buffer to store the characters typed at the keyboard. A circular buffer consists of a block of memory and two indices, one of which indicates the beginning of the data, the other one the end. When an item is placed in the buffer, the end indexis incremented. When an item is taken from the buffer, the begin index is incremented. When an index runs past the end of the block, it wraps around to the beginning. This is what makes the buffer circular.

Of course, the circular nature of the buffer means that we run the risk of the writing task overwriting values that the reading task has not yet read, or the reading task reading values that have not yet been written. We say that the buffer is empty if the begin and end indices are equal, and full if incrementing the end index (wrapping it around as necessary) would make it equal to the begin index. Then, we prevent the writing task from writing to a full buffer, and the reading process from reading from an empty one.


The Code

We change the keyboard interrupt service routine from the previous chapter, by replacing the part that prints the received character by the following code:


mov bl, [cs:lastInput]
inc bl
and bl, 15
cmp bl, [cs:firstInput]
je .end	; buffer full, discard character
xor bh, bh
mov [cs:inputBuffer + bx - 1], al
mov [cs:lastInput], bl

Then, we define the following function to read characters from the buffer:


readChar:
; Read character
; In: none
; Out: ASCII code in AL
; Global:
;	firstInput (modified)
mov bl, [cs:firstInput]
.loop0:
cmp bl, [cs:lastInput]
jne .end
hlt
jmp .loop0
.end:
xor bh, bh
mov al, [cs:inputBuffer + bx]
inc bl
and bl, 15
mov [cs:firstInput], bl
ret

The hlt halts the CPU until an IRQ occurs. Since we know the condition we are testing for can only change after the occurrence of an IRQ, we can safely do this. On some systems, it saves power.

Finally, we define the following function to read a line from the console:


readLine:
; Read line
; In:
;	buffer address (word)
;	buffer size (word)
; Out:
;	string length (ax)
push bp
mov bp, sp
mov di, [bp + 6]
push es
push ds
pop es
mov cx, [bp + 4]
.loop0:
call readChar
cmp al, 13
je .end
stosb
loop .loop0
.end:
pop es
sub di, [bp + 6]
mov ax, di
pop bp
ret

Files

The file console_kernel.asm contains the source for the kernel developed in this chapter.

Next part: System Calls

Comments

Posted by inglorion
at 2007-05-09 07:45:25

The arguments to printString and readLine were being given and used in the opposite order from what the documentation specified. This has been fixed. Those responsible have been sacked. ;-)

Posted by andrewsw
at 2012-02-17 05:12:21

I'm having trouble with the keyboard interrupt handler and the circular buffer when it wraps around. Maybe I'm doing it wrong (since I'm translating to AT&T syntax and getting confused in the process). As I see it, and watch it behave, it seems that when the lastInput is incremented and then ANDed, the subsequent store of the character will end up underflowing the circular buffer by one byte.

For example, when lastInput is 0x0f and loaded into BX, it is incremented to, 0x10, then ANDed with 0x0f to get 0x00 in BX. Now MOVing to [cs:inputBuffer + BX - 1] gets you at [cs:inputBuffer - 1], one byte below the buffer. As I said, I'm using AT&T syntax in gnu assembler so my MOV looks like this:

mov %al, %cs:inputBuffer-1(%bx)

and it gives the behavior of skipping one char when the buffer wraps around. Did I translate it incorrectly?

I've worked around it by INCing and then storing it aside in CL, then doing the same test for full buffer, and restoring from CL to store the character. Seems to work for me.

A

Post a comment