Home arrow Forums
OSDEV Forums  


anonymous
Visitor

Fresh Osdever
Posts: 0
graphgraph
Karma: 0  
string input - 2005/05/28 08:48 Does anybody know how to write a scanf-like keyboard string input function in assembly (real mode)? Are there any good examples of this?
  | | The administrator has disabled public write access.
OSDEV
Community
Advertisement
   
gaf
User

Platinum Osdever
Posts: 153
graph
Karma: 10  
Re: string input - 2005/05/29 09:17 Hello,
first you'll have to write a keyboard driver. Information on how to interface a ps/2 keyboard can be found on Adam Chapweske's homepage. If you have a usb keyboard writing a driver will be somewhat more difficult, maybe it'd be a better idea to either simply buy a ps/2 kbd (~ 15€ or use a programm such as bochs which can emulate it. Sooner or later you'll of course have to write a driver for usb kbds aswell, but it's probably not a good idea to start with it..

Here's how a simple ps/2 keyboard driver might look like:
- install a handler for IRQ #01 which will be triggered by the keyboard each time a key is presses or released
- in the handler first get the key's scancode from the keyboard controller (possibly translating it to ASCII) and then store it in an internal table so that it can be passed to the application later

The first step is just initialization and requires to reprogramm the PIC and insert an entry in the IVT (Interrupt Vector Table) which will be indexed by the processor each time an interrupt occures to find the handler in charge.

The second step requires you to write an ISR (Interrupt Service Routine - the last chapter is pmode specific), get the scancode using the information on Adam's site and then process it.

After you've written the keyboard driver all you have to do is to design a small library that acts as glue between your driver and the apps providing high-level abstractions such as scanf. How the driver interface this library will be build on actually looks depends on your personal idea about system design.
Here are two ways that I could imagine:
- Applictions can ask the driver to be notified every time a key is pressed or released. The driver doesn't need to translate the scancode to an ASCII character but simply hands it to the application which can then process it itself. The idea is that the scan-code already provides all information needed and that any abstraction should be left to the application because it knows best what to do (end-to-end argument, exokernel). Such a driver design is very usefull if the application needs full control over the keyboard input ("raw tty"). Functions like 'scanf' are still possible but have to be written as an library that is linked to the application itself.
- A more high-level approach would be to let the driver buffer keyboard access and only notify the application when 'enter' is pressed. The application then gets the whole line as an ASCII string which might be convenient but also limits the programmers possibilities ("cooked tty"). With such a design it'd, for example, be impossible to write any kind of game because a more direct access methode is needed here. Operating systems that provide cooked tty therefore also have to additionaly provide some kind of raw tty..

regards,
gaf
  | | The administrator has disabled public write access.
anonymous
Visitor

Fresh Osdever
Posts: 0
graphgraph
Karma: 0  
Re: string input - 2005/05/29 09:18 Well that should be easy
If you're looking for some simple string input I think this will do the job:

*******************************
read:
xor ax, ax
int 16 ; AL = ASCII read, AH = ScanCODE
cmp ah, 0x1C0D ; see if ENTER is pressed
je end_read
; store AL (ASCII code)
jmp read ; read until ENTER is pressed
end_read:
*******************************

int 16, 0 is BIOS interupt for character reading
after the intrupt AL = ASCII read and AH = scan code read
it loops while ENTER = 0x1C0D (scane code) is read
if ENTER is not pressed you can store the character whereever you like.

OK maybe you will like to add some more controls (for example if function key is pressed).

thats it ... you've got your string reading code ))

(I wrote the code above directly in this REPLY so there may be some sintax err)

PC-SandMan^^
"... and justice for all ..."
  | | The administrator has disabled public write access.
DRF
User

Platinum Osdever
Posts: 123
graphgraph
Karma: 1  
Re: string input - 2005/05/29 10:46 Don't worry about the driver, in real mode which you say you are using you can use the BIOS interrupt (as the previous poster said). The interrupt to call is 16h. The function is 0.
It should return the scan code in AH and the ASCII code in AL.

So you need to make a simple loop which:
Run 'int 16h' al=0
Compare al with the return key value (0x0D)
If the compared values are the same jmp to end.
Store AL in memory some where.
Loop back round to the start.

In the spirt of sharing I'll cut and paste my code below (which I wrote for an early OS of mine so the values/useage might be a bit different as it does a few extra things but you might get some ideas from it).

Code:

; Scanf - Get a string from the keyboard, until the key is pressed
; DI must be set before running command to the command variable. (CmdStr)
; Output the keyboard value to the variable in DI.
; Limited to dx chars, and will start at the start of the string.
; If CX contains a 1 then the string is not to be displayed

Scanf:
xor bx,bx ; Zero BX (string location counter/pointer)
.start
; Make the BIOS call
xor ax,ax ; Function 0, read keyboard char
int 16h ; Keyboard interrupt (outputs char to al)

; Check to see if the return key was pressed
cmp al, 0x0D ; Compare to ASCII char code
je .return ; If equal make the jump

; Save the character to a location
mov [es:di+bx],al ; String Location + Num chars from start
inc bx ; Increase BX for next char

; Max string size
cmp bx, dx ; Compare the length with the max size entered
je .return ; No error message, just act as though return pressed

; Display or not?
push bx ; Save bx
xor bx,bx
cmp bx,cx ; Compare cx to see what value was passed
je .putchar
.putcharReturn
;pop bx ; Restore bx (Done before reaching this point!)

jmp .start ; Loop for next char input
.putchar
pop bx ; Restore bx
push ax ; Save the registers
push bx
xor ah,ah
mov si,ax ; Move the ASCII char to the register
call putchar ; Call the procedure
pop bx ; Restore the registers
pop ax
jmp .putcharReturn ; Return
.return
xor al,al ; 0 to indicate the end of the string
mov [es:di+bx],al
ret ; Return


Which I called using:
Code:

mov di, CmdStr ; Location to store keyboard input
mov dx, 40 ; Max size
xor cx, cx ; 0 = Display char
call Scanf ; Make the call

CmdStr was just a variable of in this case 40bytes I zeroed and reserved for use to store the inputted 'string' containing a command at the prompt.

Hope that helps a little (sorry about the size of my code/bodge job style of my code).

If you want any help later on the backspace/cursor buttons just ask (thought I should paste a simpler earlier version of my scanf code).

Daniel
  | | The administrator has disabled public write access.
anonymous
Visitor

Fresh Osdever
Posts: 0
graphgraph
Karma: 0  
Re: string input - 2005/05/29 12:06 Thanks. But once I have the string, how do I compare it to a command? String handling is the one thing i couldnt find any tutorials on.
  | | The administrator has disabled public write access.
gaf
User

Platinum Osdever
Posts: 153
graph
Karma: 10  
Re: string input - 2005/05/29 15:21 I always programm in pmode, so that I often forget that you can also use the BIOS. What I've said is however still true, the only difference is that don't have to consider these things yourself but can rely on the 'driver' the BIOS writer provided you with..

If you want to compare two strings the 'cmps' instruction should be used:

Code:
scanf_buffer db "delete c:/windows"

command db "delete"
command_lenght equ 6

; you should make sure that es is set up corretly..

mov di, scanf_buffer
mov si, command
mov cx, command_lenght
repe cmpsw

cmp cx, 0
je delete


regards,
gaf
  | | The administrator has disabled public write access.

A WebArticles site. Sponsored by Evoleto. Motorola V525 / Business Directory / Delaware Incorporation / Home Made Bazaar