Summary of I/O Ports for p86



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 BP ; these two lines are optional

MOV BP,SP ; as MoveChar has no parameters

; PUSH …. To add later

; 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 …. To add later

POP BP ; required if the first two lines present

IRET

; 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 BP

MOV BP,SP

PUSH CX

PUSH DX

; code for 1. to 6. above goes here

Done:

POP DX

POP CX

POP BP

IRET

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 BP ; required as there are parameters

MOV BP,SP

; PUSH …. To add later

; get parameters

MOV BH,[BP+4] ; row

MOV BL,[BP+6] ; 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 …. To add later

POP BP

RET ; 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 CX ; column

PUSH AX ; row

CALL ReturnPort

ADD SP,4

MOV DX,AX ; port returned in AX

CMP DX,-1 ; see if there was a problem

JE Problem2

; used DX

; 3. subtract 1 (if possible)

CMP DX,0100H ; are we at 0, 0?

JE Problem2

SUB DX,1 ; decrement port

JMP HavePosn2

Problem2:

MOV AX,0 ; return value

JMP Done2

; 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 BP

MOV BP,SP

PUSH BX

PUSH CX

PUSH DX

; code for 1. to 6. above goes here

Done2:

POP DX

POP CX

POP BX

POP BP

RET ; 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 BP

MOV BP,SP

PUSH DX ; only register used

MOV DX,04EBH ; row

IN AL,[DX]

MOV AH,AL ; row now in AH

MOV DX,04EAH ; column

IN AL,[DX] ; column in AL

POP DX

POP BP

RET

; 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 BP

MOV BP,SP

PUSH BX

PUSH CX

MOV BL,[BP+4] ; row

MOV 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: ; parms are ok

; calculate port

MOV AL,40

MUL BL ; AX = 40*BL (BL = row)

MOV CH,0

ADD AX,CX ; add on col (CL)

ADD AX,0100H ; add on offset to first port

RetPortDone:

POP CX

POP BX

POP BP

RET

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 DX, 10H ;TIMER: control port

MOV AL, 1010B ;stop timing, clear count done,

;disable interrupt

OUT [DX], AL

MOV AX, [WAITTIME] ;number of ticks

MOV DX, 12H ;TIMER: reload value lsB

OUT [DX], AL

MOV DX, 13H

MOV AL, AH ;TIMER: reload value msB

OUT [DX], AL

Fragment 1: Start timer.

RETIME:

MOV DX, 10H ;TIMER: control port

MOV AL, 0100B ;copy reload value and start timer

OUT [DX], AL

Fragment 2: Ask the A/D converter to take a reading.

MOV DX, 1001H ;Converter status port

IN AL,[DX] ;Get status

AND AL,1B ;enabled bit

JZ DisabledError ;Not functional

; should we also check if data is already ‘ready’?

MOV DX, 1000H ;Converter control port

MOV AL, 80H ;Ask to take a reading

OUT [DX], AL

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 DX,1002H ;Converter data port

IN AL, [DX] ;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 SI ;bump array index

CMP SI, Word Ptr[ArraySize]

JE TooManyError ;error: array is full

MOV [BX+SI],AL ;store temp in next byte

Fragment 5: Delay for rest of delta t

MOV DX, 11H ;Timer status port

DELAYMORE:

IN AL, [DX]

AND AL,10B ;count done?

JZ DELAYMORE

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download