Author Topic: Nasm input/output  (Read 14386 times)

Offline Frasier

  • Jr. Member
  • *
  • Posts: 2
Nasm input/output
« on: March 10, 2011, 06:39:00 PM »

I'm trying to write a program that continuously reads a character from a keyboard and uses a printer to print that character.
For the keyboard, setting the K bit to 1 will initiate a keyboard read request. Once a character has been read K will be set to 0 (keyboard is ready for new char). Same thing for the printer.

I am not sure how to pass the char from the keyboard to the printer.
This is what I have done so far:
Code: [Select]
Kcontrolport equ 200200H        ; address of keyboard control port
Kdataport equ 200201H           ; address of keyboard data port
Pcontrolport equ 300300H        ; address of printer control port
Pdataport equ 300301H           ; address of printer data port

string resb 8192                ; 8Kb string buffer
strptr resd                     ; ptr to chars in string buffer

readch:    test byte[Kcontrolport], 40H ; test if R bit is 1
           jz readch                    ; If R=0 then repeat
           mov al, [Kdataport]          ; Copy ASCII char to output register

khandler:  sti                          ; Re-enable interrupts
           push ax                      ; Save register ax
           mov al, [Kdataport]          ; Read ASCII char
           push ax                      ; Parameter in AL part
           call putchar
           add esp, 2
           pop ax                       ; Restore register ax

nextch:    call getchar
           cmp eax, 0
           jl nextch                    ; Repeat if negative

putchar:   mov string, al               ; initialize string

printch:   mov eax, string              ; get address of string
           mov [strptr], eax            ; save pointer to 1st char
           mov al, [eax]                ; get 1st char
           test al, al
           jz skip                      ; skip if char is zero-byte
           mov [Pdataport], al          ; else copy char to data port
           or [Pcontrolport], 20H       ; and issue write request
           call OS.SUSPEND              ; ask OS to suspend bottom half
skip:      ret                          ; return from bottom-half

Phandler:  sti                          ; re-enable interrupts
           push eax                     ; save registers used in handler
           inc [strptr]                 ; advance to next char
           mov eax, [strptr]            ; copy pointer to register
           mov al, [eax]                ; and get char
           jz endofstr                  ; skip if end of string
           mov [Pdataport], al          ; copy char to data port
           or [Pcontrolport], 20h       ; issue write request jmp exit
endofstr:  call OS.RESUME               ; ask OS to resume bottom half
exit:      pop eax

Am I on the right track with this?

Thank you in advance.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Nasm input/output
« Reply #1 on: March 11, 2011, 04:48:00 AM »
What's this "for"? I don't think it'll work on "normal PC hardware", but given hardware that behaves as you apparently expect, I guess you're on the right track. Previously, you posted some 64-bit code. I guess this is supposed to be 32-bit, but some of it appears to be 16-bit(?).

As you know (I assume), this generates a flock of errors, as posted. The most serious error, I think, is:

Code: [Select]
putchar:   mov string, al               ; initialize string

You almost certainly want "[string]" there.

Lessee... "resd" requires a parameter, and "res?" need to be in "section .bss" - don't forget to switch back to "section .text" before the code! (this may not be a problem in "-f obj" output mode.) Several errors about size not specified - I assumed that ports are "byte" and strptr is "dword". I had to make "getchar", "OS.SUSPEND" and "OS.RESUME" extern (since you've provided "putchar", I suspect you intend to provide "getchar"(?) - no idea about "OS.?"...) I got it to assemble without complaint, but that doesn't mean it's right.

I'm concerned about this section:

Code: [Select]
khandler:  sti                          ; Re-enable interrupts
           push ax                      ; Save register ax
           mov al, [Kdataport]          ; Read ASCII char
           push ax                      ; Parameter in AL part
           call putchar
           add esp, 2
           pop ax                       ; Restore register ax

If this is 32-bit code, you want to push/pop eax, and add esp, 4. Currently, "putchar" doesn't get its parameter from the stack - just uses al - so I'm not sure what's intended. You seem to be putting characters into the first byte of [string], but reading them out from strptr, which you increment. That may need some adjusting(?)...

The way the bios handles the keyboard, there's a buffer... and two pointers into it, one for "last character written" (or "next character position" if it's incremented first), and another to "last character read". You may want to do something like that... so if your user can type faster than your printer can print, the characters are buffered, not "lost" (until the buffer fills up).

So I think you're on the right track, but I think you've got a way to go. ("I don't know where we're going, but we're making really good time!: :) )