Image Map Image Map
Page 4 of 4 FirstFirst 1234
Results 31 to 40 of 40

Thread: FLEX for the 6502 or building a compatible operating system...

  1. #31

    Default

    I am now able to cross assemble most inherent 6800 instructions.

    While 6800 binary files currently have no value on a 6502, this means that a large part of the fundamental infrastructure of the assembler is working.

    Next up, evaluating expressions...asmb.png

  2. #32

    Default

    This project is now two months old.

    The FLEX file system (File Management System or FMS) is still lacking the code for writing random access files until I can come up with a good way to test it. I may go ahead and write the code but leave it disconnected to get an idea how big it is likely to be.

    The FLEX user interface portion is feature complete except for background printing. Again, I may write the code to find out how large it will be. The error message reporting mechanism is complete.

    There was little progress on the Utility Command Set this month. The SAVE utility has been written, but not thoroughly tested.

    The 6800 assembler now runs on the 6502 as a cross assembler. To help test it, I have started implementing the text editor. It can currently create a text file and make some simple edits to it. The editor is definitely more difficult code than the assembler has been.

    The current system memory map is:

    $0000..$00FF - Zero page, locations at $12 and above are free for application programs to use
    $0100..$017F - FLEX line buffer
    $0180..$01FF - Stack
    $0200..$033F - FLEX entry points, variables and printer driver
    $0340..$047F - System File Control Block
    $0480..$0AFF - FLEX Utility Command Space
    $0B00..MEMEND - User memory

    Somewhere above that is about 6K of FLEX itself.

    It is time to start trying to freeze the memory organization. I am considering making a somewhat radical change to move the public portions (entry points, variables, Utility Command Space) from $200 up to $2000. Why? Doing this will make it possible for a KIM-1 or clone with a expanded RAM and a serial port to run FLEX. The operating system itself can reside from $200 to $2000 on systems which allow that and at the top of user memory otherwise. Because the binary file format consists of a collection of separate chunks, pieces of the system can potentially be built to load into several disjoint places where memory is available.

    Another decision is whether the system should reserve a part of the lower or upper end of the zero page.

    The important part now is to determine where the public portions are located. This is where I need your input as to what your particular system requires and allows. It may not be possible to please everyone, but the main goal is to have one version of the utilities and application programs which work on all supported platforms.

  3. #33
    Join Date
    Dec 2011
    Location
    Dallas, TX
    Posts
    347

    Default

    I'm curious about the rationale for putting the line buffer at $0100. Is it that the system + user programs are just unlikely to get deeper than $0180? I honestly haven't ever looked that deeply into how deep stack usage gets in various software but it would be good to know.

  4. #34

    Default

    Quote Originally Posted by dfnr2 View Post
    I'm curious about the rationale for putting the line buffer at $0100. Is it that the system + user programs are just unlikely to get deeper than $0180? I honestly haven't ever looked that deeply into how deep stack usage gets in various software but it would be good to know.
    FLEX for the 6800 and the 6809 both allocate only 128 bytes for their stacks.

    As far as I know, 6502 programs do not have an inherent tendency to use more stack. One would think that 6809 code would use more since the addressing modes encourage it.

    If you think it is a concern, I can easily move the buffer somewhere else. I do not have enough experience to say.

    The only other thing I can think of is that 680x code has the option of reloading the stack pointer to put it somewhere else; 6502 code cannot do that.

  5. #35
    Join Date
    Dec 2011
    Location
    Dallas, TX
    Posts
    347

    Default

    I don't have hard data, but given that it might be hard to control behavior of user programs, it might be nice to free up the full stack size. Could this be configured at compile time (i.e., just set the input buffer and start of user space to $0100 / $0B00, or $0B00 / $0B80?

  6. #36

    Default

    Quote Originally Posted by dfnr2 View Post
    I don't have hard data, but given that it might be hard to control behavior of user programs, it might be nice to free up the full stack size. Could this be configured at compile time (i.e., just set the input buffer and start of user space to $0100 / $0B00, or $0B00 / $0B80?
    It is set when the system files are assembled.

    It should be the same for all systems or we run a risk of software incompatibility. Historically, the location had been documented and I am not inclined to stop doing that.

  7. #37

    Default

    The text editor code has been difficult; I can only stand to work on it a bit at a time.

    The 6800 version keeps values in the X register for long stretches of code, sometimes across several subroutines. I am about to give up trying to keep it in 6502 registers even part of the time, but to declare RegX, a 2-byte variable in the zero page, and copy values into and out of it as the 6800 loads and stores X. Addresses already have to be stored in the zero page to access memory. It will not be as efficient, but the code will be somewhat clearer; this program really needs that.

    So far, the following functionality is complete:

    loading a file
    saving a file
    text buffer management
    Print command
    Insert command
    Delete command
    Renumber command
    Overlay command
    Find command

    The Copy command has been coded, but it does not work. When that is done, the Move command should be easy as it does a copy followed by a delete. I would guess we are somewhat past the halfway mark.

    During breaks, I have been working on assemblers.

    First, I added the SET directive to the 6800 ASMB. It is like EQU, but a label may be assigned a value more than once.

    I have always liked the local labels in RELASMB, the 6809 relocatable assembler, and wished that ASMB implemented them.

    Local labels work like this: a one or two digit number in the label field is considered to be a local label. It is referenced by stating the number followed by a "b" or "f" to designate whether to search for the nearest occurrence of the number before or following the current line. Note that it is not possible to find a local label on the current line. For example:

    Code:
    2                       ; This is the target for "2b"
    
    2       beq     target  ; The label for this line cannot be specified
    
    2                       ; This is the target for "2f"
    Advantages of a local label include doing away with the need to come up with meaningful and unique names for short, trivial branches and a local label uses less memory than a regular symbol.

    A web search for local label uncovered no prevalent standard, but a number with a "b" or "f" suffix is a very common form.

    I will put a seemingly arbitrary limit on local labels: the number may not consist of only "0" and "1" digits. Why? ASMB 6800 accepts binary numbers in both the %xx and xxb forms. Something like "1b" is ambiguous.

    I had been initially tempted to limit the reference of local labels to relative branch instructions to prevent people writing FORTRANish code, but RELASMB does not have that restriction. And it is convenient to be able to do something like the following:

    Code:
            ldx     #2f     ; Print error message
            jsr     PSTRNG
            rts
    
    2       fcc     "Operand expected."
            fcb     4
    I am currently implementing local labels in my 6502 cross assembler. Should that go well, the capability will be migrated to the 6800 and 6809 assemblers. Then I will implement it in ASMB 6800; ASMB 6502 will inherit that functionality.

  8. Default

    Because of the nature of the 6502, I'd give serious consideration of using a single entry point ala CP/M, and stick it in zero page.
    Code:
    LDX #cmd
    JSR $0000
    and at $0000 is simply
    Code:
    JMP SYSENTRY
    With SYSENTRY being set on startup appropriately.

    Then the Jump table can be anywhere. As long as things are guaranteed stable during program execution, it's not untoward to let the program request locations from the OS, then cache and work with them. By that notion, we would learn quickly some aspects are so prevalent, they may as well use dedicated ZP locations anyway (since odds are any program of complexity is going to do those anyway, may as well standardize them).

    Zero page is magic to the 6502, Page $01 is magic, as it's the stack, high memory is dedicated to vectors (which initially have to be ROM), folks plonk hardware every odd place in the 6502 (mostly upper RAM), so even contiguous memory can be a precious resource. Folks also get lazy decoding hardware, so large chunks are just carved out for 2 ports.

    So, when the the OS "footprint" is simply a few ZP locations and some blocks of RAM "somewhere", that gives it a lot of flexibility.

    Having the natural EXE being relocatable adds to the flexibility. And requiring loads to start on a page boundary, and having to simply keep track of the high bytes, I think simplifies it readily, and relocation is cheap, 8 bit math. You can always add the ability to flag an executable as an "absolute" image, but just appreciate that as a binary, it would not be portable. A small price to pay, and cheap to do.

    It also gives you the ability to just load hard coded image straight away early on and migrate from ".COM" to ".EXE" later on.

  9. #39

    Default

    Quote Originally Posted by whartung View Post
    Because of the nature of the 6502, I'd give serious consideration of using a single entry point ala CP/M, and stick it in zero page.
    That horse left the barn early in this thread.

    FLEX was far from being an object-oriented operating system.

    Though the FMS (file system) uses a single entry point dispatcher mechanism, the DOS portion was organized as a collection of subroutines. To make thing worse, many system variables were documented and thus made public. Implementing methods to access the data is very against the FLEX tradition and more work than I want to do, both in building the operating system and developing software to run with it.

  10. #40

    Default

    The Poor Man's Linker experiment has gone well. The conversion of the run-time library to the new approach is done. In the foreseeable future, my Python library (currently 6502 only) will be converted in the same way; it really needs it.

    The following program, the skeleton of a monitor or a debugger, compiles into a 6800 binary image a little under 2K bytes in size; it uses quite a bit but not all of the library code.

    Code:
    10 PRINT '? ';
    20 INPUT LINE A$
    30 GOSUB 1000:REM Strip leading spaces from A$
    40 B$=LEFT$(A$,1):A$=MID$(A$,2):GOSUB 1000:GOSUB 1100
    50 IF B$ = 'D' THEN 10000
    60 IF B$ = 'U' THEN 12000
    90 IF B$ = 'Q' THEN END
    95 PRINT 'Unrecognized command.':GOTO 10
    1000 REM Strip leading spaces from A$
    1010 IF ASC(' ') = ASC(A$) THEN A$=MID$(A$,2) ELSE RETURN
    1020 GOTO 1010
    1100 REM Convert B$ to upper case
    1110 IF ASC('a') <= ASC(B$) AND ASC('z') >= ASC(B$) THEN B$=CHR$(ASC(B$)-32)
    1120 RETURN
    10000 REM DUMP
    10001 print "DUMP ";a$:goto 10
    12000 REM UNASSEMBLE
    12001 print "UNASSEMBLE ";a$:goto 10
    You may have noticed the ordering of "IF ASC(' ') = ASC(A$)" as a bit unusual. A single-pass compiler which generates code as it parses the source can do a better job if simple expressions which can be completely evaluated at compile time are on the left while things which must wait until run time are postponed as long as possible. The opposite "IF ASC(A$) = ASC(' ')" gets the first character from the string, puts it into a temporary variable, then does the comparison because without lookahead, the compiler does not know that a constant follows.

    Since what I thought was source code for the FLEX BASIC interpreter turned out to be something else, SWTPC BASIC instead of TSC BASIC, I will be building a version of this compiler to generate 6502 code for TSC BASIC programs. I am just starting to reverse engineer the FLEX BASIC and Extended BASIC interpreters and thus cannot commit to doing anything with them at this time.

    For comparison, here is some code from the two compilers...

    The 6502 code generated by the compiler:

    Code:
                              00108 ; 120 C = A * (B + 1)
     0B26                     00109	L00120:
                              00110          ifdef  __TRACE
                              00111          ldx    #<120
                              00112          lda    #>120
                              00113          jsr    Trace
                              00114          endif
                              00115          ifdef  __ATLIN
                              00116          ldx    #<L00120
                              00117          stx    ResLn_
                              00118          ldx    #>L00120
                              00119          stx    ResLn_+1
                              00120          endif
                              00121
     0B26 18              [2] 00122          clc
     0B27 AD 0F39         [4] 00123          lda    B_
     0B2A 69 01           [2] 00124          adc    #<1
     0B2C AA              [2] 00125          tax
     0B2D AD 0F3A         [4] 00126          lda    B_+1
     0B30 69 00           [2] 00127          adc    #>1
     0B32 AC 0F37         [4] 00128          ldy    A_
     0B35 84 14           [3] 00129          sty    Int0
     0B37 AC 0F38         [4] 00130          ldy    A_+1
     0B3A 84 15           [3] 00131          sty    Int0+1
     0B3C 20 0D30         [6] 00132          jsr    IMul
     0B3F 8E 0F3B         [4] 00133          stx    C_
     0B42 8D 0F3C         [4] 00134          sta    C_+1
    The 6800 code generated by the compiler:

    Code:
                              00083 * 120 C = A * (B + 1)
     0119                     00084 L00120
                              00085          ifdef  __TRACE
                              00086          ldx    #120
                              00087          jsr    Trace
                              00088          endif
                              00089          ifdef  __ATLIN
                              00090          ldx    #L00120
                              00091          stx    ResLn_
                              00092          endif
                              00093
     0119 C6 01           [2] 00094          ldab   #1
     011B 4F              [2] 00095          clra
     011C FB 0435         [4] 00096          addb   B_+1
     011F B9 0434         [4] 00097          adca   B_
     0122 FE 0432         [5] 00098          ldx    A_
     0125 BD 0297         [9] 00099          jsr    IMul
     0128 F7 0437         [5] 00100          stab   C_+1
     012B B7 0436         [5] 00101          staa   C_
    The 6502 multiply subroutine:

    Code:
    .                         00730 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    .                         00731 ;
    .                         00732 ; IMul - Multiply integers
    .                         00733 ;
    .                         00734 ; Input:
    .                         00735 ;       A:X = one number
    .                         00736 ;       Int0 = the other number
    .                         00737 ;
    .                         00738 ; Output:
    .                         00739 ;       A:X = the product
    .                         00740 ;
    .                         00741
    .0D2C                     00742 IMulB    rmb    2         ; Operand
    .0D2E                     00743 IMulC    rmb    1         ; Bits left
    .0D2F                     00744 IMulS    rmb    1         ; Sign of the product
    .                         00745
    .0D30                     00746 IMul:
    .0D30 A0 00           [2] 00747          ldy    #0        ; Clear sign of product
    .0D32 8C 0D2F         [4] 00748          sty    IMulS
    .                         00749
    .0D35 C9 00           [2] 00750          cmp    #0        ; Is first number negative?
    .0D37 10 10 (0D49)  [2/3] 00751          bpl    IMul1     ; No
    .                         00752
    .0D39 EE 0D2F         [6] 00753          inc    IMulS     ; Update sign of product
    .                         00754
    .0D3C 49 FF           [2] 00755          eor    #$FF      ; Negate the number
    .0D3E A8              [2] 00756          tay
    .0D3F 8A              [2] 00757          txa
    .0D40 49 FF           [2] 00758          eor    #$FF
    .0D42 18              [2] 00759          clc
    .0D43 69 01           [2] 00760          adc    #1
    .0D45 AA              [2] 00761          tax
    .0D46 98              [2] 00762          tya
    .0D47 69 00           [2] 00763          adc    #0
    .                         00764
    .0D49                     00765 IMul1:
    .0D49 8E 0D2C         [4] 00766          stx    IMulB     ; Save the number
    .0D4C 8D 0D2D         [4] 00767          sta    IMulB+1
    .                         00768
    .0D4F A5 15           [3] 00769          lda    Int0+1    ; Is the other number negative?
    .0D51 10 10 (0D63)  [2/3] 00770          bpl    IMul2     ; No
    .                         00771
    .0D53 EE 0D2F         [6] 00772          inc    IMulS     ; Update sign of product
    .                         00773
    .0D56 A9 00           [2] 00774          lda    #0        ; Negate the other number
    .0D58 38              [2] 00775          sec
    .0D59 E5 14           [3] 00776          sbc    Int0
    .0D5B 85 14           [3] 00777          sta    Int0
    .0D5D A9 00           [2] 00778          lda    #0
    .0D5F E5 15           [3] 00779          sbc    Int0+1
    .0D61 85 15           [3] 00780          sta    Int0+1
    .                         00781
    .0D63                     00782 IMul2:
    .0D63 A9 10           [2] 00783          lda    #16       ; 16 bits to multiply
    .0D65 8D 0D2E         [4] 00784          sta    IMulC
    .                         00785
    .0D68 A9 00           [2] 00786          lda    #0        ; Clear product
    .0D6A A8              [2] 00787          tay
    .                         00788
    .0D6B                     00789 IMul3:
    .0D6B 4E 0D2D         [6] 00790          lsr    IMulB+1   ; Shift number right
    .0D6E 6E 0D2C         [6] 00791          ror    IMulB
    .0D71 90 09 (0D7C)  [2/3] 00792          bcc    IMul4     ; Skip add if low bit was clear
    .                         00793
    .0D73 18              [2] 00794          clc              ; Add number to product
    .0D74 65 14           [3] 00795          adc    Int0
    .0D76 AA              [2] 00796          tax
    .0D77 98              [2] 00797          tya
    .0D78 65 15           [3] 00798          adc    Int0+1
    .0D7A A8              [2] 00799          tay
    .0D7B 8A              [2] 00800          txa
    .                         00801
    .0D7C                     00802 IMul4:
    .0D7C 06 14           [5] 00803          asl    Int0      ; Shift the other number left
    .0D7E 26 15           [5] 00804          rol    Int0+1
    .                         00805
    .0D80 CE 0D2E         [6] 00806          dec    IMulC     ; One fewer bit to do
    .0D83 D0 E6 (0D6B)  [2/3] 00807          bne    IMul3     ; More?
    .                         00808
    .0D85 4E 0D2F         [6] 00809          lsr    IMulS     ; Is product negative?
    .0D88 90 0E (0D98)  [2/3] 00810          bcc    IMul5     ; No
    .                         00811
    .0D8A 49 FF           [2] 00812          eor    #$FF      ; Negate the product
    .0D8C 18              [2] 00813          clc
    .0D8D 69 01           [2] 00814          adc    #1
    .0D8F AA              [2] 00815          tax
    .0D90 98              [2] 00816          tya
    .0D91 49 FF           [2] 00817          eor    #$FF
    .0D93 69 00           [2] 00818          adc    #0
    .                         00819
    .0D95 4C 0D9A         [3] 00820          jmp    IMul6
    .                         00821
    .0D98                     00822 IMul5:
    .0D98 AA              [2] 00823          tax              ; Product goes in A:X
    .0D99 98              [2] 00824          tya
    .                         00825
    .0D9A                     00826 IMul6:
    .0D9A 60              [6] 00827          rts
    The 6800 multiply subroutine:

    Code:
    .                         00560 ******************************************************************************
    .                         00561 *
    .                         00562	* IMul - Multiply integers
    .                         00563 *
    .                         00564 * Input:
    .                         00565 *       A:B = one number
    .                         00566 *       X = the other number
    .                         00567 *
    .                         00568 * Output:
    .                         00569 *       A:B = the product
    .                         00570 *
    .0293                     00571 IMulB    rmb    2         ; Operand
    .0295                     00572 IMulC    rmb    1         ; Bits left
    .0296                     00573 IMulS    rmb    1         ; Sign of the product
    .                         00574
    .0297                     00575 IMul
    .0297 7F 0296         [6] 00576          clr    IMulS     ; Clear sign of product
    .                         00577
    .029A DF 02           [5] 00578          stx    Int0      ; Save second number
    .                         00579
    .029C 4D              [2] 00580          tsta             ; Is first number negative
    .029D 2A 07 (02A6)    [4] 00581          bpl    IMul1     ; No
    .                         00582
    .029F 7C 0296         [6] 00583          inc    IMulS     ; Update sign of product
    .                         00584
    .02A2 40              [2] 00585	         nega             ; Negate the number
    .02A3 50              [2] 00586          negb
    .02A4 82 00           [2] 00587          sbca   #0
    .                         00588
    .02A6                     00589 IMul1
    .02A6 B7 0293         [5] 00590          staa   IMulB     ; Save the number
    .02A9 F7 0294         [5] 00591          stab   IMulB+1
    .                         00592
    .02AC 96 02           [3] 00593          ldaa   Int0      ; Is the other number negative?
    .02AE 2A 0E (02BE)    [4] 00594          bpl    IMul2     ; No
    .                         00595
    .02B0 7C 0296         [6] 00596          inc    IMulS     ; Update sign of product
    .                         00597
    .02B3 73 0002         [6] 00598          com    Int0      ; Negate the other number
    .02B6 70 0003         [6] 00599          neg    Int0+1
    .02B9 25 03 (02BE)    [4] 00600          bcs    IMul2
    .02BB 7A 0002         [6] 00601          dec    Int0
    .                         00602
    .02BE                     00603 IMul2
    .02BE 86 10           [2] 00604          ldaa   #16       ; 16 bits to multiply
    .02C0 B7 0295         [5] 00605          staa   IMulC
    .                         00606
    .02C3 4F              [2] 00607          clra             ; Clear product
    .02C4 5F              [2] 00608          clrb
    .                         00609
    .02C5                     00610 IMul3
    .02C5 74 0293         [6] 00611          lsr    IMulB     ; Shift number right
    .02C8 76 0294         [6] 00612          ror    IMulB+1
    .02CB 24 04 (02D1)    [4] 00613          bcc    IMul4     ; Skip add if low bit was clear
    .                         00614
    .02CD DB 03           [3] 00615          addb   Int0+1    ; Add number to product
    .02CF 99 02           [3] 00616          adca   Int0
    .                         00617
    .02D1                     00618 IMul4
    .02D1 78 0003         [6] 00619          asl    Int0+1    ; Shift the other number left
    .02D4 79 0002         [6] 00620          rol    Int0
    .                         00621
    .02D7 7A 0295         [6] 00622          dec    IMulC     ; One fewer bit to do
    .02DA 26 E9 (02C5)    [4] 00623          bne    IMul3     ; More?
    .                         00624
    .02DC 74 0296         [6] 00625          lsr    IMulS     ; Is the product negative?
    .02DF 24 04 (02E5)    [4] 00626          bcc    IMul5     ; No
    .                         00627
    .02E1 40              [2] 00628          nega             ; Negate the product
    .02E2 50              [2] 00629          negb
    .02E3 82 00           [2] 00630          sbca   #0
    .                         00631
    .02E5                     00632 IMul5
    .02E5 39              [5] 00633          rts

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •