6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Apr 27, 2024 12:44 pm

All times are UTC




Post new topic Reply to topic  [ 20 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Thu Jun 01, 2023 7:52 pm 
Offline

Joined: Mon May 25, 2015 1:12 pm
Posts: 92
I think I found and fixed a bug, but before declaring it done, I'd just like for all you beautiful people to just look it over and see if I've missed any subtleties.

Code:
; perform SWAP

LAB_SWAP
      JSR   LAB_GVAR          ; get var1 address
      STA   Lvarpl            ; save var1 address low byte
      STY   Lvarph            ; save var1 address high byte
      LDA   Dtypef            ; get data type flag, $FF=string, $00=numeric
      PHA                     ; save data type flag

      JSR   LAB_1C01          ; scan for "," , else do syntax error then warm start
      JSR   LAB_GVAR          ; get var2 address (pointer in Cvaral/h)
      PLA                     ; pull var1 data type flag
      EOR   Dtypef            ; compare with var2 data type
     
; BUGFIX:  SWAP would only swap a string with a number otherwise it would generate an error!
;
      ; BPL   SwapErr           ; exit if not both the same type
      BNE   SwapErr           ; exit if not both the same type
;
; End of bugfix.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 01, 2023 8:31 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1398
Location: Scotland
JenniferDigital wrote:
I think I found and fixed a bug, but before declaring it done, I'd just like for all you beautiful people to just look it over and see if I've missed any subtleties.

Code:
; perform SWAP

LAB_SWAP
      JSR   LAB_GVAR          ; get var1 address
      STA   Lvarpl            ; save var1 address low byte
      STY   Lvarph            ; save var1 address high byte
      LDA   Dtypef            ; get data type flag, $FF=string, $00=numeric
      PHA                     ; save data type flag

      JSR   LAB_1C01          ; scan for "," , else do syntax error then warm start
      JSR   LAB_GVAR          ; get var2 address (pointer in Cvaral/h)
      PLA                     ; pull var1 data type flag
      EOR   Dtypef            ; compare with var2 data type
     
; BUGFIX:  SWAP would only swap a string with a number otherwise it would generate an error!
;
      ; BPL   SwapErr           ; exit if not both the same type
      BNE   SwapErr           ; exit if not both the same type
;
; End of bugfix.


Hm... Not a great fan of diving into ehBasic, but I've had a quick look..

The test is for a string type vs. numeric type. String type is $FF, numeric is $00.

So number EOR number: $00 eor $00 -> 0 (positive)
String EOR string: $FF eor $FF -> 0 (positive)
Number EOR String: $00 EOR $FF -> $FF (negative)

I actually think the branch ought to be (or was intended to be) BMI rather than BPL, but BNE here works too. (So a logic swap waaaaaaay back)

It also makes me think that no-one has ever used the SWAP command...

Attachment:
Screenshot_2023-06-01_21-23-52.png
Screenshot_2023-06-01_21-23-52.png [ 17.57 KiB | Viewed 13137 times ]


Swapping a number & string is ... interesting:

Attachment:
Screenshot_2023-06-01_21-25-35.png
Screenshot_2023-06-01_21-25-35.png [ 17.93 KiB | Viewed 13137 times ]


I patched my version (the Floobydust 2.22p5C version) with BMI and it works as it ought to.

Cheers,

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 01, 2023 9:19 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1373
Interesting.... when I worked on making a CMOS version of EhBasic, I implemented the patches that Klaus did, P5 being the latest. I guess I'm a bit surprised that Klaus hadn't found this particular bug.

It's been a few years since I worked on the CMOS version of EhBasic, as most of my recent activity (outside of my own projects. hardware, BIOS/Monitor code) has been creating a CMOS version of DOS/65.

So, moving forward... I will at least put the fix into the P5C code... now the decision, should this qualify as a P6 fix or something else? I'm open to suggestions.

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 02, 2023 4:29 am 
Offline

Joined: Mon May 25, 2015 1:12 pm
Posts: 92
So far I'm pleased that this little bugfix seems to be agreed with.

Now, as to why someone wouldn't spot this bug, I think its down to SWAP being a very uncommonly used command that isn't implemented on that many versions of BASIC and so wouldn't affect all that many people.

To err is human, to really 'make a hash of it' requires a computer. <- Polite versions of everything these days.


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 04, 2023 6:14 pm 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 387
Location: Minnesota
I'm a bit surprised that EOR was used instead of CMP, since the only point is to see if the two values are different or not. EOR takes a bit of thinking about to see if it comes out right, whereas CMP followed by BNE makes it pretty much obvious to any reader what's going on.

As for why it wasn't caught earlier, another possibility is that no one ever thought about swapping a number and string before. It's true the original author should have checked to make sure as part of the test routine, but possibly in practice no one tried to make a mistake like that.


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 04, 2023 6:45 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1398
Location: Scotland
teamtempest wrote:
I'm a bit surprised that EOR was used instead of CMP, since the only point is to see if the two values are different or not. EOR takes a bit of thinking about to see if it comes out right, whereas CMP followed by BNE makes it pretty much obvious to any reader what's going on.


Who knows. Lee isn't with us anymore - so it's something he (or someone else) added into the original Microsoft disassembly he worked with.

Quote:
As for why it wasn't caught earlier, another possibility is that no one ever thought about swapping a number and string before. It's true the original author should have checked to make sure as part of the test routine, but possibly in practice no one tried to make a mistake like that.


It didn't work when used correctly, but worked (or at least didn't produce an error - it didn't really work!) when you mixed string and number.

So it's been broken from day zero. It's not been found because no-one, not even the author tested it... I suspect it was added then forgotten about. It's not a common command in BASICs...

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 05, 2023 4:21 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 727
Location: Tokyo, Japan
teamtempest wrote:
I'm a bit surprised that EOR was used instead of CMP, since the only point is to see if the two values are different or not. EOR takes a bit of thinking about to see if it comes out right, whereas CMP followed by BNE makes it pretty much obvious to any reader what's going on.

To a 6502 programmer, sure. But to an 8080 or Z80 programmer, who's used to exclusive-oring a value with itself to generate zero, it's probably instinctive. XRA A, or XOR A,A in Z80 syntax, is the standard idiom for loading zero into the accumulator because it's a byte shorter and more than three times faster than LDA 0.

This, and its use as a comparison tool, is even mentioned in the original 1975 Intel 8080 Assembly language Programming Manual, where the instruction is titled "XRA Logical Exclusive-Or Register or Memory With Accumulator (Zero Accumulator)," and the largest example given in that section is using XRA to determine if a new set of bits read from a device register has any bits changed from the previous value read, which naturally leads to using JNZ ("Jump if Not Zero") or CNZ to do something if the bits have changed. (Or RZ ("Return if Zero") to short-cut the remainder of the subroutine if the bits have not changed.)

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 05, 2023 7:23 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1398
Location: Scotland
cjs wrote:
teamtempest wrote:
I'm a bit surprised that EOR was used instead of CMP, since the only point is to see if the two values are different or not. EOR takes a bit of thinking about to see if it comes out right, whereas CMP followed by BNE makes it pretty much obvious to any reader what's going on.

To a 6502 programmer, sure. But to an 8080 or Z80 programmer, who's used to exclusive-oring a value with itself to generate zero, it's probably instinctive. XRA A, or XOR A,A in Z80 syntax, is the standard idiom for loading zero into the accumulator because it's a byte shorter and more than three times faster than LDA 0.

This, and its use as a comparison tool, is even mentioned in the original 1975 Intel 8080 Assembly language Programming Manual, where the instruction is titled "XRA Logical Exclusive-Or Register or Memory With Accumulator (Zero Accumulator)," and the largest example given in that section is using XRA to determine if a new set of bits read from a device register has any bits changed from the previous value read, which naturally leads to using JNZ ("Jump if Not Zero") or CNZ to do something if the bits have changed. (Or RZ ("Return if Zero") to short-cut the remainder of the subroutine if the bits have not changed.)


That makes sense - especially as the 6502 version came after Micro Soft wrote the 8080 version of their BASIC.... It might be interesting to see if there are other examples in the MS Basic sources like that - and I'm supposing Lee copied code from another routine that takes 2 parameters to implement his new SWAP command.

I've written (been paid to write) 8080 code just once but it was after my brain had been shaped by the 6502 so it's not something I recognise, but it might be amusing for me to go through all my old sources... One day, maybe....

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 05, 2023 9:15 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 727
Location: Tokyo, Japan
drogon wrote:
That makes sense - especially as the 6502 version came after Micro Soft wrote the 8080 version of their BASIC.... It might be interesting to see if there are other examples in the MS Basic sources like that - and I'm supposing Lee copied code from another routine that takes 2 parameters to implement his new SWAP command.

I can't speak to the SWAP command, but yes, most 8-bit versions of Microsoft BASIC seem to share substantial bits of low-level design and idioms. The next one written after the original 8080 version was (the 6800 version) I belive and, though I've not looked at that for years, I seem to recall it had a bunch of things in it that really only made sense if someone had been working from the 8080 version, and the same with the 6502 version. This isn't surprising; there wasn't a lot of automated testing or unit tests or things like that in the day, so if you've got a working algorithm, you probably want to muck with it as little as you can avoid to avoid introducing an off-by-one error or something dumb like that. Even doing that, I'm sure that testing was still the greatest expense when coding this stuff.

Quote:
I've written (been paid to write) 8080 code just once but it was after my brain had been shaped by the 6502 so it's not something I recognise, but it might be amusing for me to go through all my old sources... One day, maybe....

I've found that disassembling and reverse-engineering code for other systems really helps to give one a sense of how they work. I've written less 6800 code than 6502 code, and almost no Z80 code, but I've disassembled a fair amount of all three and it's given me quite a bit of insight into the design decisions made for each CPU. (6800 vs. 6502 has been particularly enlightening.)

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 05, 2023 6:53 pm 
Offline

Joined: Mon May 25, 2015 1:12 pm
Posts: 92
if there's one thing I've learned about software over the years its that no matter how hard you try, there's always one little bug left. I'd imagine porting code from one architecture to another has traps for the lazy too. In a way, when writing Z80 code I was spoiled for registers. I wonder if Klaus would consider adding my little amendment to the repo he has.

EDIT: I in no way think that Klaus is doing a bad job. Far from it, he is doing a great job. I just thought I'd get that out there in case anyone reads my comments otherwise.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 05, 2023 7:25 pm 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 727
Location: Tokyo, Japan
JenniferDigital wrote:
I'd imagine porting code from one architecture to another has traps for the lazy too.

I really wish we could get off this whole, "Errors happen because programmers are 'lazy' thing." All humans make errors, and it's not because they're lazy, it's because they're efficient.

If you don't believe me, start by looking at every error you've ever made. I'm going to posit they are all because you are immensely lazy. Would you agree?

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 05, 2023 8:39 pm 
Offline

Joined: Mon May 25, 2015 1:12 pm
Posts: 92
cjs wrote:
JenniferDigital wrote:
I'd imagine porting code from one architecture to another has traps for the lazy too.

I really wish we could get off this whole, "Errors happen because programmers are 'lazy' thing." All humans make errors, and it's not because they're lazy, it's because they're efficient.

If you don't believe me, start by looking at every error you've ever made. I'm going to posit they are all because you are immensely lazy. Would you agree?


Point taken.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 05, 2023 8:53 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
I've a feeling I've read that organisations with a very great need for flaw-free software put about ten times the effort into writing that software. For a factor of ten, for ordinary purposes, I'd be happy with a few bugs - let alone a few bits of inefficiency.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 06, 2023 3:35 pm 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 387
Location: Minnesota
https://www.youtube.com/watch?v=GWYhtksrmhE

I suspect NASA would hate my Python code, since I love to use function indirection :-)


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 06, 2023 3:43 pm 
Offline

Joined: Mon May 25, 2015 1:12 pm
Posts: 92
NASA Won't allow you to use recursion, I think they forbid heap usage too. There will definitely be documentation on their requirements.

After all... Who wants to loose a multi-billion pound mission with years of work behind them and jobs on the line over a single bit out of place.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 20 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 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: