post

More IC photos added

I discovered more unique 65xx IC’s in my stash of boards.

So more 6502, 6521, 6545,6522 and 6522 shown here!

post

LJ EMMA, John Bell Engineering SBC’s

I have added two pages with photos and manuals of two 6502 SBC manufacturers:

EMMA and EMMA II by LJ Technical Systems. Educational SBC’s KIM-1 like, part of a whole eco system

John Bell Engineering, 82-300  SBC 6502, 6532 2716, 80-153 SBC 6522, 6502

post

L.J. Technical Systems: EMMA DIGIAC

The EMMA and EMMA II SBC’s were produced by LJ Electronics Ltd, Norwich, a company established in 1979 to market training technology to colleges, schools and universities. The company behind LG Electronics still exists but is now known as LJ Create, also carrying the USA based brand Digiac.

Here you find information on:

post

John Bell Engineering SBC’s

John Bell Engineering was a small firm producing microprocessor many boards between 1980 and 1990.
The early boards were 6502 and Z80 SBC’s, later boards were for the Apple II, and the last ones for the IBM PC bus.

I present here, what I have found, of John Bell 6502, Z80 and Apple ][ boards.

John Bell catalog 1984
John Bell catalog 1988

KIM Clone Corsham Technologies

A new KIM CLone kit is coming!

Bob Applegate is filling in the gap left by Vince Briel, with his own design.

  • 6502 for now, but will probably ship with a 65C02 (extra instructions).
  • Fully KIM-1 software compatible.
  • 5K memory from 0000 to 13FF, then another 56K from 2000 to FFF7.
  • The top 8K of RAM can be turned off and 8K of EEPROM can be enabled (socket on board for the EEPROM).
  • Has an 8V power plug and on/off switch.
  • No cassette interface.
  • USB serial board.  Ie, plug a USB cable between your computer and the KIM clone to use the TTY port.
  • Has connector to plug in our SD System.  Store/retrieve programs from a micro SD card.

http://www.corshamtech.com/

 

post

EhBASIC bug Ibuffs location

Bug in EhBASIC 2.22 Daryl Rictor et al (from a discusson on 6502.org)

The following works:

; Ibuffs can now be anywhere in RAM, ensure that the max length is $80
IRQ_vec   = VEC_SV+2      ; IRQ code vector
Ibuffs      = IRQ_vec+$14

Whereas the following doesn’t:

; Ibuffs can now be anywhere in RAM, ensure that the max length is $80
Ibuffs      = $0400
Ibuffe      = Ibuffs + $47    ; end of input buffer

Of course be careful to make sure that Ram_base is quite faraway from Ibuffs.

So, Ibuffs can be anywhere in RAM that’s not $0400??
Any reason $0400 is magical?
Nope. $0400 is an example. $0500 gives you the same result: negative.
As long as Ibuffs is in the same page as ccflag and friends, it works. And ccflag can be at $0400.

Now, if you reference Ibuffs in relation to IRQ_vec (copy it over from min_mon.asm), then things work.
Perhaps someone somewhere made some assumptions of the page where Ibuffs need to be e.g. be in the same page as ccflag and friends etc.

The other problem is what I’ve already observed: the EhBASIC binary has to be located in memory higher than Ram_base and Ram_top. Otherwise strange things happen.

With Ibuffs set to $0400 AND Ram_base set to $0500, I did a Cold start and entered this line – 10 PRINT “HELLO WORLD”

I examined the memory at Ram_base and found that the stored line was formatted correctly. However, when I typed LIST, all I got back was HELLO WORLD, as if I had typed RUN. Typing RUN also returned HELLO WORLD. When I ran the SYS command (my added command to return me to my Monitor), it just ignored it and returned to the BASIC input prompt.

Next, I changed Ibuffs to $0401 and reassembled. This time, everything performed as it should.

Next, I set Ram_base to $0600 with Ibuffs set to $0400 and entered the same line. This time, LIST returned nothing. Examining memory at $0600, the stored line is there and is correct. RUN and SYS also return nothing.

Finally, I set Ram_base to $0600 and Ibuffs to $0401 and all worked as it should.
I think I found the problem… and it would explain the issue with Ibuffs and Ram_base being 1 page apart too.

This piece of code is the problem:

LAB_142A
   INY            ; increment pointer
   INY            ; increment pointer (makes it next line pointer high byte)
   STA Ibuffs,Y   ; save [EOL] (marks [EOT] in immediate mode)
   INY            ; adjust for line copy
   INY            ; adjust for line copy
   INY            ; adjust for line copy
   DEC Bpntrl     ; allow for increment (change if buffer starts at $xxFF)
   RTS

Previously in the code, Bpntrl gets set to Ibuffs. When the DEC instruction gets executed, Bpntrl get set to $FF. Later in the code, we have this:

LAB_15F6
   JSR   LAB_IGBY     ; increment and scan memory

LAB_15F9
   JSR   LAB_15FF   

The routine LAB_IGBY is located in zero page (to increase speed). it looks like this:

LAB_2CEE
   INC   Bpntrl        ; increment BASIC execute pointer low byte
   BNE   LAB_2CF4      ; branch if no carry
               ; else
   INC   Bpntrh       ; increment BASIC execute pointer high byte

; page 0 initialisation table from $C2
; scan memory

LAB_2CF4
   LDA   $FFFF         ; get byte to scan (addr set by call routine)
   CMP   #TK_ELSE      ; compare with the token for ELSE
   BEQ   LAB_2D05      ; exit if ELSE, not numeric, carry set

   CMP   #':'          ; compare with ":"
   BCS   LAB_2D05      ; exit if >= ":", not numeric, carry set

   CMP   #' '          ; compare with " "
   BEQ   LAB_2CEE      ; if " " go do next

   SEC                 ; set carry for SBC
   SBC   #'0'          ; subtract "0"
   SEC                 ; set carry for SBC
   SBC   #$D0          ; subtract -"0"
                       ; clear carry if byte = "0"-"9"
LAB_2D05
   RTS

The code at LAB_2CEE will INC Bpntrl, which becomes $00 and then INC’s Bpntrh to $05. Now this pointer is pointing to the wrong page. And depending upon what is stored there, different things will happen.

This note is incorrect:

   DEC   Bpntrl      ; allow for increment (change if buffer starts at $xxFF)

It should read (change if buffer starts at $xx00).

My fix would be to add this:

LAB_142A
   INY            ; increment pointer
   INY            ; increment pointer (makes it next line pointer high byte)
   STA Ibuffs,Y   ; save [EOL] (marks [EOT] in immediate mode)
   INY            ; adjust for line copy
   INY            ; adjust for line copy
   INY            ; adjust for line copy

; add patch for when Ibuffs is $xx00 - Daryl Rictor
   LDA  Bpntrl    ; test for $00
   BNE  LAB_142P  ; not $00
   DEC   Bpntrh   ; allow for increment when $xx00
LAB_142P
; end of patch
   DEC   Bpntrl    ; allow for increment
   RTS

I have tested this fix and it worked for me.

Daryl

post

Lee Davison 6502 website page

Lee Davison

http://retro.hansotten.nl/lee-davison-web-site/

post

Enhanced 740 BASIC Language reference

Enhanced BASIC 740, language reference.

Most of EhBASIC74 is identical in operation to 6502 EhBASIC so this page will just describe the keywords that differ from that version.
Code that doesn’t use the features of one version should run identically on the other.

BASIC Keywords

Here is a list of BASIC keywords that differ from the 6502 version of EhBASIC. They
are only valid when entered in upper case as shown and spaces may not be included
in them. So, for example, TIMER1 is valid but TIMER 1 is not.

A2D CLEAR CNTR0 CNTR1 COUNT D2A1
D2A2 EVENT FLUSH INT0 INT1 INT2
INT3 INT4 IRQ NMI ON OFF
PRES12 PRESX PRESY PULSE PWM RETIRQ
RETNMI RETURN START STOP TIMER TIMER1
TIMER2 TIMERX TIMERY +

Anything in upper case is part of the command/function structure and must be present
Anything in lower case enclosed in < > is to be supplied by the user
Anything enclosed in [ ] is optional
Anything enclosed in { } and separated by | characters are multi choice options
Any items followed by an ellipsis, … , may be repeated any number of times
Any punctuation and symbols, except those above, are part of the structure and must be included

var is a valid variable name
var$ is a valid string variable name
var() is a valid array name
var$() is a valid string array name
expression is any expression returning a result
expression$ is any expression returning a string
result
addr is an unsigned integer in the range +/- 16777215 that will be
wrapped to the range 0 to 65535
b is a byte value 0 to 255
n is an integer in the range 0 to 63999
w is an integer in the range -32768 to 32767
i is a +ve integer value
r is real number
+r is a +ve value real number (0 is considered +ve)
$ is a string literal

BASIC74 Commands

FLUSH

This command, specific to version 1.10 on, clears the input buffer of any pending keystrokes. The buffer is also cleared by CLEAR and RUN.

INTx {ON|OFF|CLEAR}

Changes INTx event handling (where x is one of 0, 1, 2, 3 or 4).
ON
Enables the INTx handling subroutine after it has been turned off.
Note If a INTx event occured while the INTx event handling was disabled then it will be actioned immediately after this command.
OFF
Disables the INTx handling subroutine but does not remove the assignment. INTx events that occur while the handler is disabled will still be flagged for action.

CLEAR
Cleares the INTx handling assignment. After an INTx CLEAR the handling subroutine can only be restarted with an ON INTx command.


INTx {+|-}

Sets the detection edge for INTx (where x is one of 0, 1, 2, 3 or 4). + sets a low to high transition (positive edge) as the trigger, – sets a high to low (negative edge) as the trigger. The default is -. Note that changing the trigger edge when the interrupt is enabled may cause the interrupt to trigger.


CNTRx {ON|OFF|CLEAR}

Changes CNTRx event handling (where x is either 0 or 1).
ON

Enables the CNTRx handling subroutine after it has been turned off.
Note If a CNTRx event occured while the CNTRx event handling was disabled then it will be actioned immediately after this command.

OFF

Disables the CNTRx handling subroutine but does not remove the assignment. INTx events that occur while the handler is disabled will still be flagged for action.

CLEAR

Cleares the CNTRx handling assignment. After a CNTRx CLEAR the handling subroutine can only be restarted with an ON CNTRx command.


CNTRx {+|-}

Sets the detection edge for CNTRx (where x is one of 0 or 1). + sets a low to high transition (positive edge) as the trigger, – sets a high to low (negative edge) as the trigger. The default is -. Note that changing the trigger edge when the interrupt is enabled may cause the interrupt to trigger.


PRESq <b>

Sets the value for prescaller q (where q is one of 12, X or Y).


TIMERp {TIMER|PWM|COUNT|PULSE}

Sets TIMERp timing mode (where p is either X or Y).
TIMER

The timer (X or Y) counts down (f/16)/(1+PRESq)/(1+TIMERp).

PWM

If the corresponding active edge selection bit (CNTR0 for timer X, CNTR1 for timer Y) is “0” (CNTRx -) then the counter counts as in timer mode while the pin is at “1”.
If the corresponding active edge selection bit (CNTR0 for timer X, CNTR1 for timer Y) is “1” (CNTRx +) then the counter counts as in timer mode while the pin is at “0”.
The Prescaller and timer latches are preset to $FF by setting this mode and when the selected event (-ve or +ve edge) happens the prescaller and timer values are copied and available to BASIC using the TIMERp (where p is either X or Y) function.

COUNT

The same as timer mode except pulses on the corresponding counter pin (CNTR0 for timer X, CNTR1 for timer Y) are counted. Selecting this mode also sets the corresponding pin to input mode.

PULSE

As timer mode except when the timer reaches $0000 the counter pin (CNTR0 for timer X, CNTR1 for timer Y) is inverted. Selecting this mode also sets the corresponding pin to output mode.


TIMERp {START|STOP}

Enables or disables counting for TIMERp (where p is either X or Y).


TIMERq {ON|OFF|CLEAR}

Changes TIMERq event handling (where q is one of 1, 2, X or Y).
ON

Enables the TIMERq handling subroutine after it has been turned off.
Note If a TIMERq event occured while the TIMERq event handling was disabled then it will be actioned immediately after this command.

OFF

Disables the TIMERq handling subroutine but does not remove the assignment. TIMERq events that occur while the handler is disabled will still be flagged for action.

CLEAR

Cleares the TIMERq handling assignment. After a TIMERq CLEAR the handling subroutine can only be restarted with an ON TIMERq command.

TIMERq <b>

Sets the value of TIMERq (where q is one of 1, 2, X or Y).


RETIRQ

This command has been removed from EhBASIC74. It’s function is now handled by an enhanced RETURN command.


RETNMI

This command has been removed from EhBASIC74. It’s function is now handled by an enhanced RETURN command.


RETURN

As well as returning program execution to the next statement after the last GOSUB in EhBASIC74 RETURN also restores execution to the next statement after event
subroutine has been executed. RETURN checks the type of event and automatically restores the enabled flag for the interrupt that caused the event.


ON

See INTx {ON|OFF|CLEAR}, CNTRx
{ON|OFF|CLEAR} or TIMERq {ON|OFF|CLEAR}.


OFF

See INTx {ON|OFF|CLEAR}, CNTRx
{ON|OFF|CLEAR} or TIMERq {ON|OFF|CLEAR}.


CLEAR

See INTx {ON|OFF|CLEAR}, CNTRx
{ON|OFF|CLEAR} or TIMERq {ON|OFF|CLEAR}.


ON {IRQ|NMI} <n>

These commands have been removed from EhBASIC74 as there is no IRQ or NMI interrupt on the 740 series microprocessor.


ON INTx <n>

Set up the INTx routine pointers (where x is one of 0, 1, 2, 3 or 4). This sets up the effective GOSUB line that is taken when an interrupt happens. When the effective GOSUB is taken the interrupt, INTx, is turned off. The interrupt is turned back on when normal program flow is resumed by a matched RETURN command.


ON CNTRx <n>

Set up the CNTRx routine pointers (where x is one of 0 or 1). This sets up the effective GOSUB line that is taken when a counter interrupt happens. When the
effective GOSUB is taken the interrupt, CNTRx, is turned off. The interrupt is turned back on when normal program flow is resumed by a matched
RETURN command.


ON TIMERq <n>

Set up the TIMERq routine pointers (where q is one of 1, 2, X or Y). This sets up the effective GOSUB line that is taken when a timer interrupt happens. When the
effective GOSUB is taken the interrupt, TIMERq, is turned off. The interrupt is turned back on when normal program flow is resumed by a RETURN
command.


IRQ {ON|OFF|CLEAR}

This command has been removed from EhBASIC74 as there is no IRQ interrupt on the 740 series microprocessor.


NMI {ON|OFF|CLEAR}

This command has been removed from EhBASIC74 as there is no NMI interrupt on the 740 series microprocessor.


D2Ax <b>

Output byte b as an analog voltage on D-A port x (where x is 1 or 2). Setting either convertor also sets the corresponding pin to analog output mode.

D2Ax {ON|OFF}

Enables or disables the D2Ax output (where x is one of 0 or 1).


+

See INTx {+|-} or CNTRx
{+|-}.


See INTx {+|-} or CNTRx
{+|-}.

BASIC74 Functions

Functions always return a value, be it numeric or string, so are used on the right hand side of the = sign or in commands requiring an
expression e.g. after PRINT, within expressions, or in other functions.


A2D(<b>)

Returns the value of the A-D convertor input b, where b is 0 to 7. Any value for b outside this range will cause a function call error.


EVENT

Returns a boolean value. If any enabled interrupt has occured since EVENT was last examined then EVENT will return -1 else EVENT will return 0


TIMERp

Returns the count value from TIMERp (where p is either X or Y). As this is a count down timer the value returned is first subtracted from zero then returned as if it had been DEEKed from the timer registers. This function is only of any use when TIMERp is being used in PWM mode.

post

Enhanced 740 BASIC

Enhanced BASIC74 is a BASIC interpreter for the 740 microprocessor family. It is constructed to be quick and powerful and includes instructions to facilitate easy low level handling of 740 family hardware devices. It also retains most of the powerful high level instructions from similar BASICs.

EhBASIC74 is derived from EhBASIC for the 6502 and shares much of the code used in that BASIC. However EhBASIC74 also includes enhancements to make it specifically more usefull on the Mitsubishi 740 series of single chip micros. While it was developed on the M38067 it should be possible to run it on most of the 740 family with only minor modifications.

EhBASIC74 is free but not copyright free. For non commercial use there is only one restriction, any derivative work should include, in any binary image distributed, the string “Derived from EhBASIC” and in any distribution that includes human readable files file that includes the above string in a human readable form e.g. not as a comment in an HTML file.

  • Language reference
  • Code examples

19th June 2003.
Confusingly the main version number is now the 3806 specific version number so, while the generic BASIC version is still 1.09, this incarnation is 1.10.This adds an interrupt driven receive buffer and an extra command to help use it. Go see the language reference for details.

18th June 2003.
This is the last version for the SuprDupr and SuprChip boards that will use polled input. The next version will have an interrupt driven Rx buffer for better response. As such version 1.09 will remain available for download here.

AT keyboard interface driver

The SuprDupr has a PS2 style socket for an AT keyboard. However, as it arrived, the data and clock go to the GAL and so were jumped directly to port 7, bits 7 and 6, on the micro. There are also positions for pullup resistors on both the keyboard data and clock lines, these are not needed and were omitted. These details may have changed as this was an early production board.
The software is unfinished and provided as a starting point for anyone who wishes to make their own. As provided the driver provides very reliable basic keyboard handling. During developement it was noticed that the keyboard driver would sometimes hang so some test code was added to monitor the reliability (included in the source but commented out) and it was found that the routine wouldn’t return about once in every 750,000 calls.

This was eventually traced to a faulty keyboard but highlighted the vunerability of the code to spurious responses from the keyboard. As a result the robustness of the code was improved by adding timeouts and the resulting code proved reliable over hundreds of millions of calls.

Download the source here

LCD port driver

The SuprDupr has a port wired to enable use of many inteligent LC displays. The display, pictured right, is an LC7980 type though most of the other graphics and
text types are similarly driven.
One change needed to be made to the SuprDupr to use this display and that was to disconnect the earthy end of the contrast pot from 0v and connect it to the -ve
charge pump output on the MAX232 chip. This is because the greater multiplex on these graphics displays requires a more -ve bias to maintain the viewing angle.

A down side to this is that display contrast is effected by the loading on the RS232 port and use of such things as a RS232 line monitor can have an adverse
effect on the display. Also if the load from the display is to great then the MAX232 charge pump will not start. However this should not be a problem in normal use.
Another change made to the SuprDupr was to wire +12v to the spare pin on the LCD port to provide power for the backlight. This could be connected through a PNP
transistor and controlled by software via one of the port pins.

The software is unfinished and provided as a starting point for anyone who wishes to make their own. It is usable and was used to produce the displays pictured above and below.

Download the source here


8 Bit ISA slot

I wanted a quick way to connect an 8 bit ISA slot, only to access the IO adresse range, to the SuprChip V microcontroller. The circuit I came up with appears on the right.

The address lines A5 to A15 can either be set using jumpers or switches (I used switches) or, if you only need one address range, can be hard wired to the corresponding address.

Any of the five interrupt lines, from IRQ3 to IRQ7, can be selected by the use of a jumper. Again if you will only need one (or none) of these then the desired interrupt can be hard wired.

This circuit could be fairly easily adapted as a memory mapped device by connecting the corresponding address and data lines (possibly through buffers), by driving the IOR and IOW pins with decoded read and write signals, and by connecting the interrupt, via an invertor, to the NMI input on the processor. The RESET line can be driven, again via an invertor, by the processor RESET line or by an output port line. This line is active high.

While experimenting with different network cards I discovered some of them need the +12v supply in addition to the +5v supply. This additional connection is shown in red on the diagram.

As I had a stack of 3Com 3C509B NICs of various types I decided to try to use them. Well it turns out that even with PnP disabled you still need to access the card’s id port on $01xx. To allow this Port 6 bit 6 was connected to the A9 line, so both $03xx and $01xx can be accessed by the software. This additional connection is shown in green on the diagram.

Though the slot can be accessed entirely from EhBASIC it was decided to create two short routines to make accessing the slot faster and easier. To that end one function, to read a byte, and one subroutine, to write a byte, were written.

After initialising the function and subroutine addresses thus ..

..
30 DOKE $44,$EF20 : REM USR(n) = read from IO address $xxnn	
31 rr = $EF00 : REM call address for write to IO address
..

It is a simple matter to write a byte by doing ..

20500 CALL rr,cr,dd : REM set control register			
20505 REM cr is the IO address - $00 to $1F
20510 REM dd is the byte value for that IO address

.. and read a byte by doing ..

10050 by = USR(cr)						
10055 REM cr is the IO address - $00 to $1F
10060 REM the byte value is returned to by

You can download the assembly source for the read and write routines.

post

EhBASIC LOAD and SAVE notes

The quickest and easiest way to save the program is to do this …

Type LIST but not the return ..
Set your terminal program to ASCII capture..
Hit return to start the LIST command..
Once the list is complete stop the ASCII capture.

To load the program back there are two possible, similar, ways.

If your hardware supports hardware handshake properly just select the listing and use ASCII send to transfer it (You’ll need to edit the ‘Ready’ prompt from the end of the listing).

If your hardware doesn’t support hardware handshaking then you’ll need to paste a number of SPACE characters at the start of each line to give the interpreter enough time to tokenise the previous line. The number of spaces depends on two things, how fast your processor is and how fast the serial link is. The faster the processor the fewer spaces, the faster the serial link the more spaces. Otherwise just do as above.

(Alternately edit the NULL command to insert $20’s instead of $00’s into the start of each line and do ..
NULL n
LIST
NULL 0
when you save the list)

If you want to save the program as binary you should save (Smeml) to (Svarl)-1.

If you want to save the program as ASCII you should redirect the character output vector to write to your filesystem and then call LIST. Doing this can also allow you to specify line numbers or ranges as with LIST. The output vector should be restored and the file closed when LIST returns or an error is encountered.

To load a binary program start loading it at (Smeml) and set (Svarl) to the last address + 1 then call LAB_1477 to clear the variables and reset the execution pointer. An easy way to do the first part is by copying (Smeml) to (Svarl) and using (Svarl) as a post incremented save pointer. If there is a chance that the program has been relocated it’s probably a good idea to rebuild the line pointer chain.

To load an ASCII program redirect the character input vector to read from your filesystem and return to the main interpreter loop. The input vector should be restored and the file closed when the file end is reached or an error is encountered.

I prefer ASCII format as it’s far more portable, easier to manipulate and can include direct commands and comment lines that aren’t saved to memory.

Is there an easy way to support a filename in the LOAD and save COMMANDs, and get access to that from my code? Right now I am prompting the user for it.

Call the evaluate following expression routine, LAB_EVEZ, and look for a string by testing if the data type flag, Dtypef, is negative. If it is the string descriptor is on the descriptor stack so don’t forget to pop it off there by calling LAB_22B6 once you’re done with it.

Look at Jeff Trantor’s implemention of LOAD and SAVE for the Apple 1 with a CFFA1 and for the OSI C1P via the serial line.

Daryl Rictor wrote a simple SAVE and LOAD program:

;******** LOAD &amp; SAVE PATCH FOR ENHANCED BASIC ON 65C02 Simulator

psave    
    jsr  pscan
    ldy  #$00
    lda  itempl
    sta  (itempl),y
    iny
    lda  itemph
    sta  (itempl),y
    ldx  smeml
    lda  smemh
    jsr  print2byte
    jsr  print_cr
    sec
    lda  itempl
    sbc  smeml
    tax
    lda  itemph
    sbc  smemh
    jsr  print2byte
    jsr  print_cr
    rts

pload    
    jsr  pscan
    lda  itempl
    sta  svarl
    sta  sarryl
    sta  earryl
    lda  itemph
    sta  svarh
    sta  sarryh
    sta  earryh
    JMP   LAB_1319    
pscan
    lda  smeml
        sta  itempl
        lda  smemh
        sta  itemph
pscan1  ldy   #$00
    lda   (itempl),y
    bne   pscan2
    iny   
    lda   (itempl),y
    bne   pscan2
    clc
    lda   #$02
    adc   itempl
    sta  itempl
    lda  #$00
    adc  itemph
    sta  itemph
    rts
pscan2  ldy   #$00
    lda  (itempl),y
    tax
    iny
    lda  (itempl),y
    sta  itemph
    stx  itempl
    bra  pscan1

Another version of this:
;******** LOAD &amp; SAVE PATCH FOR ENHANCED BASIC ON SBC-3
; Daryl Rictor, Feb 2009
;

.include dos.lbl      ; get DiskOS pointers
;input    ; sbc scanned input
;output    ; text output
;DiskOS    ; diskos entry
;SaveF    ; save program file from BASIC
;LoadF    ; load program file from BASIC

;ibuffs+1 ($420) contains the name, start addr, end address

psave    ldx  #$00
    lda  ibuffs+1
    stz  ibuffs+1  ; this fixes syntax error in ehbasic
    bne  psave15
    rts
psave1    lda  ibuffs+1,x
    stz  ibuffs+1,x  ; this fixes syntax error in ehbasic
    beq  psave3
psave15    cmp  #$b9
    bne  psave2
    lda  #"/"
psave2    sta  buffer+2,x
    inx
    cpx  #$46
    bne  psave1
    rts      ; entry too long, abort
psave3    lda  #","
    sta  buffer+2,x
    inx
    phx
    jsr  pscan    ; Find end of program
    plx
    lda  smemh
    jsr  ToHex
    lda  smeml
    jsr  ToHex
    lda  #","
    sta  buffer+2,x
    inx
    lda  itemph
    jsr  ToHex
    lda  itempl
    jsr  ToHex
    lda  #$00
    sta  buffer+2,x
    jsr  SaveF    ; save file to IDE (in DiskOS)
    rts

pload    ldx  #$00
    lda  ibuffs+1
    stz  ibuffs+1  ; this fixes syntax error in ehbasic
    bne  pload15
    rts
pload1    lda  ibuffs+1,x
    beq  pload3
pload15    cmp  #$b9
    bne  pload2
    lda  #"/"
pload2    sta  buffer+2,x
    inx
    cpx  #$47
    bne  pload1
    rts      ; entry too long, abort
pload3    lda  #$00
    sta  buffer+2,x
    jsr  Loadf    ; load file from IDE (in DiskOS)
    jsr  pscan
    lda  itempl
    sta  svarl
    sta  sarryl
    sta  earryl
    lda  itemph
    sta  svarh
    sta  sarryh
    sta  earryh
    JMP   LAB_1319    

pscan
    lda  smeml
          sta  itempl
          lda  smemh
          sta  itemph
pscan1    ldy   #$00
    lda   (itempl),y
    bne   pscan2
    iny   
    lda   (itempl),y
    bne   pscan2
    clc
    lda   #$02
    adc   itempl
    sta  itempl
    lda  #$00
    adc  itemph
    sta  itemph
    rts
pscan2    ldy   #$00
    lda  (itempl),y
    tax
    iny
    lda  (itempl),y
    sta  itemph
    stx  itempl
    bra  pscan1

SysJMP    JSR  Main_Loop  ; in DiskOS
    rts

ToHex    PHA                     ;  prints AA hex digits
    LSR                     ;  MOVE UPPER NIBBLE TO LOWER
    LSR                     ;
    LSR                     ;
    LSR                     ;
    JSR   SaveDig           ;
    PLA                     ;
SaveDig    AND   #$0F              ;
    CMP   #$0A              ;
    BCC   SaveDig1          ;
    ADC   #$66              ;
SaveDig1  EOR   #$30              ;
    sta   buffer+2,x        ;
    inx
    rts

And another approach:

There seems to be quite a lot of mixed information about how to deal with string arguments in LOAD and SAVE. I’d like to present the way I came up with:
At the beginning of either LOAD and SAVE, i call a subroutine that gets the string argument using LAB_EVEX and opens the file:

openfile:
                jsr LAB_EVEX
                lda Dtypef
                bne @go
                ; not a string, trigger syntax error
                ldx #$02
                jsr LAB_XERR
@go:
                ldy #$00
@l:
                lda (ssptr_l),y
                beq @open
                cmp #'"'
                beq @term
                iny
                bne @l
@term:
                lda #$00
                sta (ssptr_l),y
@open:
                lda ssptr_l
                ldx ssptr_h
                jsr krn_open
                bne     io_error
                rts
io_error:
                pha
                jsr     krn_primm
                .asciiz "io error: "
                pla
                jmp krn_hexout

As it seems, after calling LAB_EVEX, ssptr points to the string given as parameter including the closing “, which I overwrite with $00 to be compatible with my open routine, which expects the address of a null terminated string.
In another thread, it was suggested to pop the string from the descriptor stack using LAB_22B6, which in my case resulted in ut1_ph/l not pointing to the string, but anywhere in the area of $exxx, where my os resides. So I went for the above approach. It works, but it feels rather dirty due to the overwriting of the closing “. At this point, I am open for suggestions.