6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 7:54 am

All times are UTC




Post new topic Reply to topic  [ 321 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7, 8 ... 22  Next
Author Message
PostPosted: Mon Apr 03, 2017 3:16 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
With the assemblers and programmers I've used, the offset has always been taken care of by the programmer software, not the assembler. The assembler would put out the same thing whether you had for example a single 32KB EPROM or four 8KB EPROMs that fill the same 32KB space in memory, and then the programmer would put the right portion in each EPROM, at the right address from the viewpoint of the EPROMs themselves. I had a project around 1990 at work where there were five 8KB EPROMs on the SBC, for 40KB. There aren't any 40KB EPROMs, but the EPROM programmer sorted out the 8KB sections to put in each 8KB EPROM.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 03, 2017 5:11 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8505
Location: Midwestern USA
Dan Moos wrote:
I'm loving this editor, and the sim is just icing on the cake! I'm too new to critique the assembler.

Be sure to get familiar with the macro language. There is information about it posted around here. Just do a search on "Kowalski."

Quote:
Using @ instead of % for binary messed me up at first...

That is one of the two non-standard syntax things in the assembler, the other being that accumulator addressing, e.g., ROR A in MOS Technology syntax, is written as ROR without the A operand. Mike Kowalski's interpretation of such an instruction is it is implied, which it is not. MOS Technology's standard required that all instructions using accumulator addressing must have an operand for syntactical consistency, that operand being the letter A. This is because the same instructions can act as read-modify-write operations on memory, such as ROR SOME_ADDRESS.

Dan Moos wrote:
BDD, mine says 1.2.11.

Is 1.2.12 worth upgrading to, and where is it?

Yes. It fixes a bug in the listing output that was double-spacing everything, as well as a bug in the macro interpreter related to string processing. I provided you with a link to 1.2.12 in an earlier post in this topic.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 03, 2017 5:25 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8505
Location: Midwestern USA
GARTHWILSON wrote:
With the assemblers and programmers I've used, the offset has always been taken care of by the programmer software, not the assembler.

That's been the case for me as well. In the Kowalski simulator the assembler assembles instructions at whatever address is currently in the program counter. It does not do offsets.

In the case of POC V1.1, whose ROM is mapped in at $00E000-$00FFF, firmware assembly starts at $E000 and the resulting object file (raw binary) is loaded into the EPROM burner's software buffer at $0000. Although I am using a 32KB EPROM, the burn starts at $0000 in the ROM and ends at $1FFF, since that's all the ROM that is being exposed in the system.

POC V2 is a little more involved, as ROM is decoded into an 8KB section at $00E000, ending at $00FFFF, and a 4KB section at $00C000, ending at $00CFFF. So the firmware is assembled starting at $C000. Once all code in the $C000 section has been assembled, a simple conditional statement in the source code tells the assembler to pad the unused space from the end of the $C000 code to address $DFFF with $FF. Assembly then resumes at $E000 and ultimately ends at $FFFF. Again, unused parts of the $E000 section are padded with $FF.

When it comes time to burn the ROM, the RAM image in the Kowalski simulator is saved as raw binary, starting at $C000 and extending to $FFFF. The binary is loaded into the EPROM burner's software buffer at $0000 and burned into the ROM starting at $0000. When placed in-circuit, everything aligns to the right addresses.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 03, 2017 6:05 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
BigDumbDinosaur wrote:
... Mike Kowalski's interpretation of such an instruction is it is implied, which it is not. MOS Technology's standard required that all instructions using accumulator addressing must have an operand for syntactical consistency, that operand being the letter A. This is because the same instructions can act as read-modify-write operations on memory, such as ROR SOME_ADDRESS ...

We've butted heads on this before, but I can't resist the temptation to do it again, all in good fun of course. :)

The decision to combine accumulator addressing with implied addressing is just that ... a decision. I haven't completed an assembler for the 65xx, but it seems self-evident (at least to me) that recognizing the operand 'A' is no more or less difficult than recognizing the absence of an operand. Maybe special-casing 'A' and making its use as a standard operand illegal could be considered by some to be an undesirable irregularity. In fact, if you study the opcode matrix of the 65xx, you will notice that all of the accumulator addressing instructions are in the "xA" column, with the remainder of that column filled with "pure" implied instructions, so even the internal instruction decoder can take electronic advantage of this so-called "equivalence".

Shoot, how about expanding the concept to some of the other mnemonics:
LDX ; TAX
LDY ; TAY
STX ; TXA
STY ; TYA
[meh ... about four decades too late for that nutty idea to have much chance ...]

Mike B.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 03, 2017 3:56 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 679
If you have labels named A, B, and C, then out of ROR A, ROR B, ROR C, the first will behave differently than the rest if you follow the MOS convention. Operand-less ROR is not ambiguous.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 04, 2017 3:58 am 
Offline

Joined: Sat Mar 11, 2017 1:56 am
Posts: 276
Location: Lynden, WA
Ok, I've opted to, for now, roll my own simple monitor. I realize its a lot to take on at this stage in my learning, but the whole point of the exercise is that I'd be forced to learn some stuff I might otherwise over look. I don't tend to get discouraged with failure, but actually learn more when I do fail, so nothing to worry about there.

Goal one is to be able to write and read memory locations from the command line.

I'm not totally sure what the best way to parse command line input is.

My first "in my head" algorithm was along the lines of having all my commands stored in ROM, all NULL terminated, in alphabetical order.

Then, I'd load some buffer in RAM with the user input, while waiting for a CR.

When the CR is read, I'd read the first character in the buffer (maybe I'd toss any spaces preceding the first real character), and compare it to the first byte in the command lookup table in ROM. If no match, I'd increment the index in the lookup until a NULL is found, telling me where the next command is. If a match, I'd compare to the next byte in the lookup. This would continue until either the command is identified, or no match is found (causing some sort of "invalid entry" message)

Once I identified the command that had been typed, I'd enter the proper subroutine, where any argument parsing could be addressed.

Is this a valid way to go about this? Is it at all similar to how its often done? Not looking for code, just direction as far as a rough technique.

Having done a fair amount of C and C++, one really starts to appreciate what a high level language hides when one contemplates such a simple task as I just described. I'll never take a simple IF or WHILE statement for granted again!


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 04, 2017 4:57 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8505
Location: Midwestern USA
Dan Moos wrote:
I'm not totally sure what the best way to parse command line input is.

My first "in my head" algorithm was along the lines of having all my commands stored in ROM, all NULL terminated, in alphabetical order.

Machine language monitors for the 6502 family have generally used single letter commands, followed by a space, followed by one or more operands, if the command takes operands. For example, in most 6502 monitors, the command m $1000 $10ff means dump memory from $1000 to $10FF, with m being the actual command. Use of a single letter for each command greatly simplifies lookups and generally gives you plenty of flexibility.

All of the 6502 monitors I have used, going back to the 1970s, have had these commands:

    a -- assemble code
    c -- compare memory ranges
    d -- disassemble code
    f -- fill memory range with byte value
    g -- execute code
    h -- search (hunt) memory for data
    m -- dump memory
    r -- display MPU registers
    t -- copy (transfer) memory
    x -- exit the monitor, depending upon the environment
    ; modify MPU registers
    > modify memory

The Commodore 128's monitor added:

    j -- execute code as a subroutine
    l -- load code from mass storage
    s -- save code to mass storage
    @ -- execute disk command (e.g., list directory)

Many of these functions use a common set of subfunctions that parse command line arguments, convert numbers from one format to another, etc. A good monitor definitely benefits from a top-down design, as it can be surprisingly complex in some areas, especially assembly and disassembly of instructions.

Incidentally, you could download my Supermon 816 source code to see how some of this works. Although written for the 65C816 running in native mode, quite a bit of the code can be modified to work with the 65C02.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 04, 2017 5:15 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Dan, your idea sounds rather similar to how Forth handles text input. See under the heading, "The Dictionary" in chapter 1 of the book "Starting Forth." Words are found by seeing what's separated by spaces, then they're looked up in the dictionary. If a word is not found, it is passed off to NUMBER which sees if it can make sense of it in the current base (hex, decimal, binary, or any other base you could possibly want). If it's a no-go, an error message is given. If it does make sense as a number, the number is put on the data stack (not the page-1 return stack).

A nice thing about it is that in Forth there's basically no syntax, so the "subroutines" (words) don't have to do any parsing, except that you can have delimiters like " for the end of a string or ) for the end of a commented-out section within an input line. The combination of simplicity and flexibility are amazing. Since there's no real parsing, you can use almost any character in a word name, like to have a variable called °C(initial) for example, or ±½°F without causing problems.

Instead of using the null terminator for the end of the name, it normally uses a counted string, meaning the first byte tells the length of the string. If the name field doesn't match what you're searching for, the word's link field (which immediately follows the name field) is used to find the address of the next word back in the chain, until a match is found or the end is reached. If there is a match, the code-field address is taken, which points to the code to execute. (The code field is pointed to by the next pair of bytes immediately following the link field.) In the case of primitive, ie, words defined in assembly language, the code field just points to the parameter field, or body, which immediately follows. So each word with a header has:
  • name field, starting with the count byte whose lower 5 bits are the length and upper 3 bits have some cool functions. Name can be up to 31 characters.
  • link field which is two bytes and links to the next word back in the vocabulary
  • code field address which is two bytes pointing to the code to execute for that word
  • parameter field which can be any length and can be data, code, addresses, whatever

(For larger processors, the fields are made to be 32 bits or whatever is appropriate for the particular processor.) You could implement this kind of thing with a "skeleton crew" of words, and expand it later—which is what you do in Forth, and everything you write becomes part of the language.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 04, 2017 7:27 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
Taking Garth's Forth paradigm a bit further, you could employ a noun [space] optional-noun [space] verb [cr] setup, like so (user entry after . prompt):
Code:
.300 .
0300 4C

.300 303 .
0300 4C 0A F1 18

.300 20 !
0300 20

.301 5C 04 !
0301 5C 04

.38 ,
0303 38

.300 303 .
0300 20 5C 04 38

.304 / JSR 600
0304 20 00 06

.307 " HI!
0307 48 49 21

.300 !
?.

The parser would push nouns on the stack until it encountered a verb. The handler for the verb would be able to determine the depth of the stack and consume the nouns as appropriate, or error out with a ?. Some verbs like / and " could parse the command line further as necessary.

Mike B.


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 04, 2017 4:28 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8505
Location: Midwestern USA
Quote:
Taking Garth's Forth paradigm a bit further...

Gentlemen, you're injecting too much complexity. :D Even the debuggers I used with MC68000 systems way back when I did 68K assembly language used single-letter commands, and that was with a more sophisticated MPU than a 65C02. A machine language monitor is a low-level debugging program, not a full-featured language and operating environment like Forth.

All that is needed with a single-letter command system is a list of the letters to be used, and a corresponding list of addresses of routines associated with those letters. Here's how I did it in Supermon 816:

Code:
;   monitor commands...
;
mpctab   .byte "A"             ;assemble code
         .byte "C"             ;compare memory ranges
         .byte "D"             ;disassemble code
         .byte "F"             ;fill memory
         .byte "G"             ;execute code
         .byte "H"             ;search memory
         .byte "J"             ;execute code as subroutine
         .byte "L"             ;load data
         .byte "M"             ;dump memory range
         .byte "R"             ;dump registers
         .byte "T"             ;copy memory range
         .byte "V"             ;display software version
         .byte "Z"             ;clear screen
         .byte ">"             ;change memory
         .byte ";"             ;change registers
n_mpctab =*-mpctab             ;entries in above table
;
;
;   monitor command jump table...
;
mpcextab .word monasc-s_byte   ; A  assemble code
         .word moncmp-s_byte   ; C  compare memory ranges
         .word mondsc-s_byte   ; D  disassemble code
         .word monfil-s_byte   ; F  fill memory
         .word monjmp-s_byte   ; G  execute code
         .word monhnt-s_byte   ; H  search memory
         .word monjsr-s_byte   ; J  execute code as subroutine
         .word monlsr-s_byte   ; L  load data
         .word mondmp-s_byte   ; M  dump memory range
         .word monreg-s_byte   ; R  dump registers
         .word moncpy-s_byte   ; T  copy memory range
         .word monver-s_byte   ; V  display software version
         .word moncls-s_byte   ; Z  clear screen
         .word monchm-s_byte   ; >  change memory
         .word monchr-s_byte   ; ;  change registers

It's not complicated. :)

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 08, 2017 6:20 pm 
Offline

Joined: Sat Mar 11, 2017 1:56 am
Posts: 276
Location: Lynden, WA
Ok, I'd like my monitor to have a sort of "system self test" function, and I was contemplating what would make fore a good memory self test.

My notion is to write a byte to memory, read it back, and compare it to some value in the X or Y register. Maybe just use X as a counter, load the current count into the memory address under test, read it back into the accumulator, and compare it to the X register, and so on through memory.

Sound good?


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 08, 2017 6:44 pm 
Offline

Joined: Sat Mar 11, 2017 1:56 am
Posts: 276
Location: Lynden, WA
Also, I just ordered the uVGA adapter for my display. Looks like a really useful product that will get my going pretty easily for video. Still want to roll my own eventually though. Probably will do composite when the time comes. Just doesn't seem to be much info out there on from scratch VGA.


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 08, 2017 7:32 pm 
Offline
User avatar

Joined: Wed Mar 01, 2017 8:54 pm
Posts: 660
Location: North-Germany
Dan Moos wrote:
Ok, I'd like my monitor to have a sort of "system self test" function, and I was contemplating what would make fore a good memory self test.

My notion is to write a byte to memory, read it back, and compare it to some value in the X or Y register. Maybe just use X as a counter, load the current count into the memory address under test, read it back into the accumulator, and compare it to the X register, and so on through memory.

Sound good?

RAM tests are one way to spent really huge amount of processing time :) - whether you ever will catch one error I don't know. I remember test running in several stages: first clearing all (and verify of course), then fill all cell with $FF (and verify), then $55 and $AA, sometimes even $33, $CC, $77, $EE. The "ultimate" was the "walking bit" where one single 1 (and afterwards a single 0) was shifted through all memory, verification of all memory (of course :D ) after every single shift!


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 08, 2017 7:33 pm 
Offline
User avatar

Joined: Wed Mar 01, 2017 8:54 pm
Posts: 660
Location: North-Germany
Dan Moos wrote:
Also, I just ordered the uVGA adapter for my display. Looks like a really useful product that will get my going pretty easily for video. Still want to roll my own eventually though. Probably will do composite when the time comes. Just doesn't seem to be much info out there on from scratch VGA.

Perhaps this http://www.waveguide.se/?article=bitmapped-video-interface might be interesting for you.


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 08, 2017 7:56 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
On the first commercial computer product I designed (for private aircraft), in the late 1980's, I had it test both RAM and ROM upon power-up, just because I saw that another avionics manufacturer did that and reported to the user that it passed. All it did is delay the user's ability to use it upon power-up. Predictably, the test was never failed, unless the entire product was non-op.

There's really no point in testing the RAM. If it doesn't work, you won't even be able to run the self test unless you can go with no variables and no stack use (JSR/RTS) etc.. It's not like a disc which may have bad sectors. The manufacturer tests every byte before selling the RAM. If there's any damage after that, it will be to the input or output circuitry that affects everything, not just a random byte here and there. You could test to see how much memory is installed, but there's no need to test every byte for that, just the ones on likely boundaries. You could also just tell it with jumper options, or just put the quantity in the ROM, and re-program the ROM in the unlikely event that you ever change the amount of memory.

EPROM is usually only guaranteed to hold its programmed data for ten years, so it might make more sense to test that. But if it's starting to go, the computer may not be able to run the test anyway. If it's on the raggedy edge, it may pass the test, and still fail to work after the temperature rises from warm-up. I just refresh EPROMs every 10 or so years, including on products I bought rather than made. I put a label on them telling when I refreshed them last. What makes refreshes easy is that you don't have to have the original files. Just read the contents into the programmer and program them back in.

Testing all of I/O would be quite complex, especially since the I/O ICs have so many modes of operation, timers, etc.. Testing one IC's I/O would require another I/O IC, and loopback circuitry. Then if there is a failure, you have to troubleshoot anyway to see which IC it was.

I have never gotten a bad IC brand new in hobby or in my prototyping work for my job. I have also been responsible for hundreds of thousands, possibly millions, of ICs in our products for our tiny company over the years, and to my knowledge, none of them were bad when brand new either. I usually go many months between customer repairs, and the few failures we do get have been infant mortality of relays (ie, if they make it through the first few months, they will probably last indefinitely), electrolytic capacitors of one particular brand, size, and value from one batch that started to go down after at least a dozen years in the field, on very rare occasion a monolithic ceramic capacitor or switching power supply controller IC that goes down for unknown reasons. We had one 65c22 almost 20 years ago that had an I/O pin get disconnected on the inside, undoubtedly a wire bond failure. Other failures, which generally show up and are caught before the unit is sold, are from human error in the assembly. Fortunately the SMT portion gets no errors anymore like the thru-hole stuffing did years ago.

There was a time that I accidentally let a screwdriver roll under my wire-wrapped workbench computer on the workbench, and it shorted pins together and blew things, such that nothing would work so there was no way to run a diagnostic. I did not take the time to troubleshoot to find out which ICs were bad. I just replaced all of them and got back to work.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 321 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7, 8 ... 22  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: