I/O Port Examples

advertisement
I/O Port Examples
This file contains four examples using I/O Ports
Example 1:
Keyboard Input Example
This example shows fragments of a program that gets input
from the keyboard.
Fragment 1:
Indicate that interrupts are not allowed (just done once near the
beginning of the program).
….
; set Keyboard Control Port to indicate interrupts
; not allowed
MOV
DX,0000H
MOV
AL,0b
OUT
[DX],AL
….
Fragment 2:
Wait until input is ready and then read it in (done every time input is
needed), and process it.
….
; wait for input (polling with busy waiting loop) using
; Keyboard Status Port
MOV
DX,0001H
PollLoop:
IN
AL,[DX]
AND
AL,010b
; result of AND will be 1 if data is ready
JZ
PollLoop
; we have input, so get it (Keyboard Data Port)
MOV
DX,0002H
IN
AL,[DX]
; process AL (ASCII character)
…
Example 2:
Display I/O Example
This example shows an ISR, MoveChar, that reads in the character
just before the current cursor position and prints it in the upper left
hand corner of the otherwise blank screen. It returns 0 if it cannot
access the position before the current cursor position (i.e. cursor at
0,0), and otherwise it returns 1.
; boolean MoveChar ( ) [ISR]
; read character just before current cursor position and print
; in upper left corner of otherwise blank screen
; return 0 if cannot access position before cursor
; (i.e. cursor at 0, 0); return 1 otherwise
Outline:
MoveChar:
PUSH
MOV
;
PUSH ….
BP
BP,SP
To add later
; these two lines are optional
; as MoveChar has no parameters
; 1. get current cursor row and column
; 2. move to previous position (if possible)
; 3. get character
; 4. clear screen (which also homes cursor)
; 5. write character at (0, 0)
; 6. set return value
Done:
;
POP ….
POP
IRET
To add later
BP
; required if the first two lines present
; 1. get current cursor row and column
MOV
DX,04EAH
; column
IN
AL,[DX]
MOV
CL,AL
; column in CL
MOV
DX,04EBH ; row
IN
AL,[DX]
; row in AL
; used CX, DX
; 2. move to previous position (if possible)
CMP
CL,0
; are we at the start of a row?
JE
MoveToPrevRow
SUB
CL,1
JMP
HavePosn
MoveToPrevRow:
CMP
AL,0
; are we at (0, 0)?
JE
Problem
SUB
AL,1
; move to end of prev row
MOV
CL,39
; column is now 39
JMP
HavePosn
Problem:
MOV
AL,0
; return value
JMP
Done
; 3. get character
; (calculate port 0100H + 40 * row + col)
MOV
DX,0100H
MOV
CH,40
MUL
CH
; AX = 40*AL (AL = row)
ADD
DX,AX
MOV
CH,0
ADD
DX,CX
; add on col (CL)
IN
AL,[DX]
; get character at that position
MOV
CL,AL
; store character in CL
; (as AL will be overwritten by clear screen)
; 4. clear screen (which homes cursor)
MOV
DX,04E8H
MOV
AL,0001b
; clear screen is bit 0
OUT
[DX],AL
; 5. write character at current cursor position (0,0)
; (and advance cursor)
; Note that if we use port 0100H it will write to position (0,0) but
; the cursor will remain on top, so the value is not visible
MOV
DX,04E9H
MOV
AL,CL
; character to display
OUT
[DX],AL
; 6. set return value
MOV
AL,1
; everything ok
Updated Stack Frame for MoveChar:
Note: registers to PUSH and POP are: CX and DX (only)
MoveChar:
PUSH
MOV
PUSH
PUSH
BP
BP,SP
CX
DX
; code for 1. to 6. above goes here
Done:
POP
POP
POP
IRET
DX
CX
BP
Example 3:
Display I/O Example
This example shows a subroutine (not an ISR), MoveCharTo
(similar to MoveChar) that reads in the character just before the
current cursor position and prints it at the Row, Col indicated. It
returns 0 if it cannot access the position before the current cursor
position (i.e. cursor at 0,0) or if Row and/or Col are not valid, and
otherwise it returns 1.
; boolean MoveCharTo ( byte Row, byte Col )
[regular subroutine]
; read character just before current cursor position and print
; in position indicated of otherwise blank screen
; return 0 if cannot access position previous to cursor
; (i.e. cursor at 0, 0), or if Row not in range 0-24,
; or if Column not in range 0-39; return 1 otherwise
Uses:
; word GetCursorPosn ( ) [regular subroutine]
; returns the row and column of the current cursor position
; (row is in AH, column in AL)
And:
; word ReturnPort (byte Row, byte Col)
[regular subroutine]
; returns the display Port corresponding to the given
; Row and Column; returns –1 if Row >24 or Column >39
Outline:
MoveCharTo:
PUSH
MOV
;
PUSH ….
BP
BP,SP
To add later
; required as there are parameters
; get parameters
MOV
MOV
BH,[BP+4]
BL,[BP+6]
; row
; col (used BX)
; 1. get current cursor row and column
; 2. calculate port
; 3. subtract 1 from port (if possible)
; 4. get character
; 5. clear screen
; 6. get port for desired screen location (if possible)
; 7. write character and move cursor if it’s on top
; 8. set return value
Done2:
;
POP ….
POP
RET
To add later
BP
; regular subroutine
; 1. get current cursor row and column
Call
GetCursorPosn
MOV
CL,AL
; column
MOV
AL,AH
; row
; used CX
; 2. calculate port
PUSH
PUSH
CALL
ADD
MOV
CMP
JE
; used DX
CX
AX
ReturnPort
SP,4
DX,AX
DX,-1
Problem2
; column
; row
; port returned in AX
; see if there was a problem
; 3. subtract 1 (if possible)
CMP
DX,0100H
JE
Problem2
SUB
DX,1
JMP
HavePosn2
Problem2:
MOV
AX,0
JMP
Done2
; are we at 0, 0?
; decrement port
; return value
; 4. get character (already have port)
HavePosn2:
IN
AL,[DX]
; get character at that position
MOV
CL,AL
; store character in CL
; 5. clear screen (which will home the cursor, too)
MOV
DX,04E8H
MOV
AL,0001b
; clear screen is bit 0
OUT
[DX],AL
; 6. get port for desired screen location (if possible)
PUSH
BX
; col (BL)
MOV
AL,BH
PUSH
AX
; row (BH)
CALL
ReturnPort
ADD
SP,4
MOV
DX,AX
; port returned in AX
CMP
DX,-1
; see if there was a problem
JE
Problem2
; 7. write character (move cursor forward if writing to 0,0)
CMP
DX,0100H
JNE
WriteChar
; if we are writing to 0,0
MOV
DX,04E9H
; use non-mapped port
; which will advance cursor
WriteChar:
MOV
AL,CL
; character to display
OUT
[DX],AL
; 8. set return value
MOV
AL,1
; everything ok
Updated Stack Frame for MoveCharTo:
Used registers BX, CX, and DX (only)
MoveCharTo:
PUSH
MOV
PUSH
PUSH
PUSH
BP
BP,SP
BX
CX
DX
; code for 1. to 6. above goes here
Done2:
POP
POP
POP
POP
RET
DX
CX
BX
BP
; regular subroutine
Sub-subroutines:
; word GetCursorPosn ( ) [regular subroutine]
; returns the row and column of the current cursor position
; (row is in AH, column in AL)
GetCursorPosn:
PUSH
MOV
PUSH
BP
BP,SP
DX
MOV
IN
MOV
MOV
IN
DX,04EBH
AL,[DX]
AH,AL
DX,04EAH
AL,[DX]
POP
POP
RET
DX
BP
; only register used
; row
; row now in AH
; column
; column in AL
; word ReturnPort (byte Row, byte Col)
[regular subroutine]
; returns the display Port corresponding to the given
; Row and Column; returns –1 if Row >24 or Column >39
ReturnPort:
PUSH
MOV
PUSH
PUSH
MOV
MOV
BP
BP,SP
BX
CX
BL,[BP+4] ; row
CL,[BP+6] ; column
; check parameters
CMP
BL,24
JBE
RowOK
MOV
AX,-1
JMP
RetPortDone
RowOK:
CMP
CL,39
JBE
ColOK
MOV
AX,-1
JMP
RetPortDone
ColOK:
; calculate port
MOV
MUL
MOV
ADD
ADD
RetPortDone:
POP
POP
POP
RET
; parms are ok
AL,40
BL
CH,0
AX,CX
AX,0100H
CX
BX
BP
; AX = 40*BL (BL = row)
; add on col (CL)
; add on offset to first port
Example 4:
A/D Converter Example
Suppose that we want to collect temperature readings every 5 seconds
and these readings are converted to binary via an A/D converter as
studied in the class slides. Assume that the A/D converter has
1. an 8-bit Control port at 1000H (bit 7 =1 => take a reading, all
other bits unused),
2. an 8 bit Status port at 1001H (bit 7 = 1 => data is ready, bit 0 = 1
=> A/D converter is enabled, all other bits unused), and
3. an 8 bit Data port at 1002H where the digital temperature reading
is presented.
Fragment 0: Initialize timer to expire after “delta t” time ==
[WAITTIME] ticks.
MOV
MOV
OUT
DX, 10H
;TIMER: control port
AL, 1010B ;stop timing, clear count done,
;disable interrupt
[DX], AL
MOV
MOV
OUT
AX, [WAITTIME] ;number of ticks
DX, 12H
;TIMER: reload value lsB
[DX], AL
MOV
MOV
OUT
DX, 13H
AL, AH
[DX], AL
;TIMER: reload value msB
Fragment 1: Start timer.
RETIME:
MOV
MOV
OUT
DX, 10H
;TIMER: control port
AL, 0100B ;copy reload value and start timer
[DX], AL
Fragment 2: Ask the A/D converter to take a reading.
MOV
IN
AND
JZ
DX, 1001H
AL,[DX]
AL,1B
DisabledError
;Converter status port
;Get status
;enabled bit
;Not functional
; should we also check if data is already ‘ready’?
MOV
MOV
OUT
DX, 1000H
AL, 80H
[DX], AL
;Converter control port
;Ask to take a reading
Fragment 3: Get a temperature reading from converter
MOV
DX, 1001H
;Converter status port
WAITFORDATA:
IN
AL,[DX]
;Get status
AND
AL,80H
;data ready bit
JZ
WAITFORDATA ;poll until data ready
MOV
IN
DX,1002H
AL, [DX]
;Converter data port
;get temperature value
Fragment 4: Application specific processing – suppose temperature is
stored in a byte array pointed to by BX, and whose size is in ArraySize.
SI is array index.
INC
CMP
JE
MOV
SI
;bump array index
SI, Word Ptr[ArraySize]
TooManyError
;error: array is full
[BX+SI],AL
;store temp in next byte
Fragment 5: Delay for rest of delta t
MOV
DELAYMORE:
IN
AND
JZ
DX, 11H
;Timer status port
AL, [DX]
AL,10B
DELAYMORE
;count done?
Download