I have seen some questions about using a port expanders, here is a version that works for the MCP23017, I am using MicroChip's USB boot loader. This program simply sets the 23017's PortA as inputs and PortB as outputs (driving LEDs). It also send the PortA value to the PC via USB.

Code:
define LOADER_USED 1        ' USB Boot loader
define RESET_ORG 800h
define INTERRUPT_ORG 808h
DEFINE OSC 48
DEFINE I2C_SCL PORTA,1
DEFINE I2C_SDA PORTA,0
Define I2C_SLOW 1     'At this clock speed this needed to be added to make it work.


'define SHIFT_PAUSEUS 200
ADCON1 = $F       'port A digital
CMCON = 7         'PortA Digital

USBBufferSizeMax   con 16  ' maximum buffer size
USBBufferSizeTX    con 16  ' input 
USBBufferSizeRX    con 16  ' output

' the USB buffer...
USBBuffer        Var Byte[USBBufferSizeMax] 
USBBufferOut     Var Byte[USBBufferSizeMax]
USBBufferCount   Var Byte 
Addr             var byte
j                var byte
i                var byte

'======================================================================================
' Port A Registers (8 Bit Mode)
IODIRA             con   $00          ' Direction Bit Control Reg
IOBITSA            con	%11111111	' Direction Bit Settings Reg (0 = output, 1 = input)
IPOLA              con	$01			' Interrupt Polarity Control Reg
GPINTENA           con	$02			'Interrupt Enable Reg
DEFVALA            con	$03
INTCONA	           con	$04
IOCONA	           con	$05			' I/O Configuration Reg
IOCONSETA          con	%10111000	' IOCON register setting
GPPUA	           con	$06			' Pull-Up Control Reg
INTFA	           con	$07			' Interrupt Flag Register
INTCAPA	           con	$08
GPIOA	           con	$09			' General Purpose I/O
IOLATA	           con	$0A			' Output Latch Reg

'Port B Registers (8 Bit Mode)
IODIRB	          con	$10			' Port B Direction Bit Control Address
IOBITSB	          con	%00000000		' Port B Direction Bit Settings (0 = output, 1 = input)
IPOLB	          con	$11			' Interrupt Polarity Control
GPINTENB          con	$12			' Interrupt Enable Reg
DEFVALB	          con	$13
INTCONB	          con	$14
IOCONB	          con	$15			' I/O Configuration Reg
IOCONSETB         con	%10111000		' IOCON register setting
GPPUB	          con	$16			' Pull-Up Control Reg
INTFB	          con	$17			' Interrupt Flag Register
INTPOLB	          con	$18
GPIOB	          con	$19			' General Purpose I/O Reg
IOLATB	          con	$1A			' Output Latch Reg

'========================================================================================
' Port A Reguisters (16 Bit Mode)
IODIRA16            con	    $00
IODIRB16            con	    $01
IOCONA16            con	    $0A
IOCONB16            con	    $0B
GPIOA16             con		$12
GPIOB16             con		$13
OLATA16             con		$14
OLATB16             con		$15

IO_EXP0WR           con	    $4E		' MCP23017  Write
IO_EXP0RD           con	    $4F		' MCP23017  Read
IO_DAT              var     byte    ' MCP23017  Data read
IO_DAT_OLD          var     byte
Out_Dat             var     byte
    '   Interrupt definition   
    '   ====================
        '   USB interrupt used to keep USB connection alive
INCLUDE "DT_INTS-18.bas"    ' Base Interrupt System
INCLUDE "ReEnterPBP-18.bas"     ' Include if using PBP interrupts
ASM
INT_LIST  macro    ; IntSource,         Label,  Type, ResetFlag?
        INT_Handler    USB_INT,  _DoUSBService,   ASM,  yes
    endm
    INT_CREATE               ; Creates the interrupt processor
ENDASM
usbinit ' initialise USB...
USBService                                    ' keep connection alive
UIE = $7F
UEIE = $9F
@   INT_ENABLE  USB_INT
gosub InitMPC23017
gosub ReInitPortA
goto Programstart
' ************************************************************
' * Sub-routines                                             *
' ************************************************************
DoUSBService:    'Keeps USB alive
    usbservice
@   INT_RETURN


' ************************************************************
' * receive data from the USB bus                            *
' ************************************************************
DoUSBIn:
   USBBufferCount = USBBufferSizeRX              ' RX buffer size
   'USBService                                    ' keep connection alive
   USBIn 1, USBBuffer, USBBufferCount, DoUSBIn   ' read data, if available
   return
    
' ************************************************************
' * wait for USB interface to attach                         *
' ************************************************************
DoUSBOut:
   USBBufferCount = USBBufferSizeTX              ' TX buffer size
   'USBService                                    ' keep connection alive
   USBOut 1, USBBufferout, USBBufferCount, DoUSBOut ' if bus available, transmit data
   return
   
InitMPC23017:
Pause 100
'#############  PORTA
i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOCONA,IOCONSETA]
i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IODIRA,$0]          'PortA inputs
i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOLATA,$FF]            'PortA = 0
'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IPOLA,0]
'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[DEFVALA,0]
'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPPUA,$FF]           'pull-ups enabled
'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[INTCONA,0]
'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPINTENA,$FF]        'interupt on change
'##############  PORTB
i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOCONB,IOCONSETB]
i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IODIRB,0]
i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOLATB,$FF]
'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IPOLB,0]
'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[DEFVALB,0]
'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[INTCONB,0]
'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPINTENB,0]
return
ReInitPortA:
i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOCONA,IOCONSETA]
i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IODIRA,$FF] 
i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPPUA,$FF]           'pull-ups enabled

return


' ************************************************************
' * main program loop - remember, you must keep the USB      *
' * connection alive with a call to USBService every couple  *
' * of milliseconds or so...                                 *

ProgramStart: 
   'gosub DoUSBIn
   'gosub DoUSBOut
i2cwrite PortA.0,PortA.1,IO_EXP0wr,[gpioa]
i2cread PortA.0,PortA.1,IO_EXP0rd,[IO_dat] 
if IO_DAT_OLD != io_dat then
''''   usbbufferout(0) = io_dat
   for j = 0 to 15
  usbbufferout(j) = io_dat
   next j
   gosub  dousbout
 out_dat = io_dat
   io_dat_old = io_dat

endif
i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[gpioB,out_dat]
PAUSE 250
''i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[gpioB,0]
''PAUSE 250   
   
goto ProgramStart  

   end
Thanks

Dave