6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 12:41 pm

All times are UTC




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Mon May 02, 2022 7:29 pm 
Offline
User avatar

Joined: Tue Apr 03, 2018 2:10 pm
Posts: 125
I thought I understood this, but I suspect something basic is tripping me up. I was under the impression that BCC could be used as a 'less than' operator and BCS as a 'more than'. But it's not working for me.

I'm trying to run a test to ensure that an input character is uppercase alpha (ASCII 65 to 90 inclusive). The code currently looks like this:

Code:
.read_filename_next_char
  lda STDIN_BUF,X           ; Get next byte from buffer
  inx
  beq read_filename_check   ; If a null (0), at end of input
  cmp #CHR_SPACE            ; If it's a space, ignore it & get next byte
  beq read_filename_next_char
  cmp #CHR_LINEEND          ; Same for linefeed
  beq read_filename_next_char
  cmp #65
  bcc read_filename_fail
  cmp #90
  bcs read_filename_fail


But when I use this, the code always routes to the read_filename_fail label - ie, the character always fails the tests. I know I'm probably doing something dumb, but I just can't see it.

_________________
I like it when things smoke.
BlogZolatron 64 project


Top
 Profile  
Reply with quote  
PostPosted: Mon May 02, 2022 7:39 pm 
Offline

Joined: Fri Apr 15, 2016 1:03 am
Posts: 140
Code:
beq read_filename_check

is testing the Z frag from "inx", not "lda" ; this will miss the trailing null on a C string.

Code:
  cmp #65
  bcc read_filename_fail

will branch on unsigned < 'A' ; seems OK.

Code:
  cmp #90
  bcs read_filename_fail

will branch on unsigned >= 'Z'; did you mean cmp #'Z'+1 ?


Top
 Profile  
Reply with quote  
PostPosted: Mon May 02, 2022 7:45 pm 
Offline
User avatar

Joined: Tue Apr 03, 2018 2:10 pm
Posts: 125
leepivonka wrote:
Code:
beq read_filename_check

is testing the Z frag from "inx", not "lda" ; this will miss the trailing null on a C string.


I picked up on that immediately after posting!

leepivonka wrote:
Code:
  cmp #90
  bcs read_filename_fail

will branch on unsigned >= 'Z'; did you mean cmp #'Z'+1 ?


Yes, you're right. Here's an amended version:

Code:
  ldy #0                    ; Offset for where we're storing each byte
.read_filename_next_char
  lda STDIN_BUF,X           ; Get next byte from buffer
  beq read_filename_check   ; If a null (0), at end of input
  cmp #CHR_SPACE            ; If it's a space, ignore it & get next byte
  beq read_filename_loop
  cmp #CHR_LINEEND
  beq read_filename_loop
  cmp #65                  ; Acceptable values are 65-90 (A-Z)
  bcc read_filename_fail
  cmp #91
  bcs read_filename_fail
  sta STR_BUF,Y             ; Store in STR_BUF buffer
  iny                       ; Increment STR_BUF index
.read_filename_loop
  inx                       ; Increment input buffer index
  jmp read_filename_next_char
.read_filename_fail

_________________
I like it when things smoke.
BlogZolatron 64 project


Top
 Profile  
Reply with quote  
PostPosted: Mon May 02, 2022 7:51 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
Some assemblers give you

Code:
  BLT: <
  BGT: >
  BLE - <=
  BGE: >=


These are sometimes macros, sometimes pseudo ops..

With ca65 which I use if I

Code:
.macpack generic


then it gives me:

Code:

            .macro  add     Arg     ; add without carry
                    clc
                    adc     Arg
            .endmacro

            .macro  sub     Arg     ; subtract without borrow
                    sec
                    sbc     Arg
            .endmacro

            .macro  bge     Arg     ; branch on greater-than or equal
                    bcs     Arg
            .endmacro

            .macro  blt     Arg     ; branch on less-than
                    bcc     Arg
            .endmacro

            .macro  bgt     Arg     ; branch on greater-than
                    .local  L
                    beq     L
                    bcs     Arg
            L:
            .endmacro

            .macro  ble     Arg     ; branch on less-than or equal
                    beq     Arg
                    bcc     Arg
            .endmacro

            .macro  bnz     Arg     ; branch on not zero
                    bne     Arg
            .endmacro

            .macro  bze     Arg     ; branch on zero
                    beq     Arg
            .endmacro



Hope this is of some use...


-Gordon

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


Top
 Profile  
Reply with quote  
PostPosted: Tue May 03, 2022 2:36 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8509
Location: Midwestern USA
Code:
lda #A
cmp #B
bcc A_less_than_B
beq A_same_as_B
bne A_greater_than_B

That’s all there is to it.

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


Top
 Profile  
Reply with quote  
PostPosted: Tue May 03, 2022 6:55 am 
Offline
User avatar

Joined: Tue Apr 03, 2018 2:10 pm
Posts: 125
BigDumbDinosaur wrote:
Code:
lda #A
cmp #B
bcc A_less_than_B
beq A_same_as_B
bne A_greater_than_B

That’s all there is to it.


That’s what I always understood, which is why I’m confused about why it’s not working. But I think that misplaced INX is the problem. Without the error checking, this routine actually works. Or maybe that should be ‘works’.

Haven’t had the opportunity to check it yet, but what I think is happening is that the original routine is ignoring the null terminator and instead triggering when X rolls over. By this time, all kinds of random garbage has been copied into the STR_BUF buffer, with the final char unlikely to be in the range A-Z. Which is why the sanity check barfs.

This would also explain why a later check, on the size of Y (the length of the provided filename) is also failing to work as expected. And maybe another new problem with an entirely unrelated buffer getting corrupted. All from that one mistake (and a lack of bounds checking). I’ll give the fix a whirl later today.

[UPDATE] Yep, moving that INX solved all three problems!

_________________
I like it when things smoke.
BlogZolatron 64 project


Last edited by speculatrix on Tue May 03, 2022 6:42 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Tue May 03, 2022 1:35 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8509
Location: Midwestern USA
speculatrix wrote:
[UPDATE] Yep, moving that INX solved all three problems!

As a fairly general rule, you should branch immediately after the comparison—no intermediate instructions between the comparison and the branch. The exceptions would be if you know for certain an intermediate operation will not affect the relevant flag(s) or if the comparison is being used because it affects the flags in a certain way in linear code. If the latter, you need to thoroughly comment the usage, since it may not be immediately obvious.

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


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC


Who is online

Users browsing this forum: dmsc and 11 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: