Branching - 6502 Assembly Crash Course 03

Поделиться
HTML-код
  • Опубликовано: 29 сен 2024

Комментарии • 62

  • @bensmith218
    @bensmith218 3 года назад +117

    The carry flag is set for A >= Memory, because subtraction is actually treated as adding a negative value.
    Negative numbers are encoded using two's complement, which means that to negate a number you invert the bits and add 1. So, for example, if we want to compare $03 and $05 we negate $05 and add it to $03:
    $03 - $05
    $03 + $fb
    This gives the answer $fe which is the two's complement encoding of -2. The carry flag is not set because this addition didn't overflow.
    If we instead compare $05 to $03 we get:
    $05 - $03
    $05 + $fd
    This gives the answer $02, but also sets the carry flag since the actual result was $102.
    Similarly, if you compare two values that are equal, you will set the carry flag since the resulting addition will always be $100.

    • @NesHacker
      @NesHacker  3 года назад +27

      Wow, that is a slick mathematic explanation, nicely stated!

    • @amaiorano
      @amaiorano 2 года назад +7

      Hey Ben, I love how I keep bumping into you, even on random RUclips comments :)

    • @bensmith218
      @bensmith218 2 года назад +7

      @@amaiorano Heh, true! Good to see you Antonio! Working on a NES emulator or just watching some good vids?

    • @amaiorano
      @amaiorano 2 года назад +8

      @@bensmith218 Always wanted to write an NES game myself, and now my son wants to as well! These videos are great.

  • @georgiysrbsk
    @georgiysrbsk 3 года назад +63

    Easily the most approachable 6502 assembly course on RUclips. Love the series, Ryan. You earned a sub and like on every video. Greetings from Serbia!

    • @NesHacker
      @NesHacker  3 года назад +7

      That means a lot! Thank you very much for the support! Also, Serbia? Nice! I’m half Hungarian, though I’ve only been to Eastern Europe once as a kid… :D

    • @georgiysrbsk
      @georgiysrbsk 3 года назад +2

      @@NesHacker Wow, that is awesome. After the pandemics end, you should definitely visit more. Budapest is my favorite destination. :D

    • @Desmaad
      @Desmaad Год назад

      I'd say he gives some insight into assembly in general. Sure, every CPU does things differently, but I think I can assume there's enough similarities to get the gist of them all (except the PDP-8; that architecture is whack.)

  • @NesHacker
    @NesHacker  3 года назад +42

    So what do you all think about branching on the 6502? Stick around to the end of the episode where I present a coding challenge!
    *UPDATES*
    - There is a typo on line 20 of the example: it should read: “sta $02” (not $01). Thanks @Captain N!
    - Turns out there _is_ a slick math reason why the CMP instruction sets Carry Flag is set when A >= Memory. See the awesome comment by @Ben Smith below!

  • @michmart9261
    @michmart9261 2 года назад +13

    To make the routine branch-less I would
    lda #0
    rol
    Which pushes the carry flag into the lowest bit of A which can be used as the output

  • @lolbruah
    @lolbruah Год назад +9

    As an IT guy, who learned all the digital-tech stuff in school 25 years ago, and also had an NES as Kid (magical greybox) I gotta admit: I‘m eating up your 6502 content for hours straight since yesterday.
    Maybe it‘s time to get into programming again :)

    • @NesHacker
      @NesHacker  Год назад +4

      Sweet :), glad you’re enjoying the channel!

  • @DPBOX
    @DPBOX 3 года назад +13

    Is this the way to do it without branching?
    ; Initialize Health, Damage, and the Return Value
    lda #25
    sta $00
    lda #30
    sta $01
    lda #0
    sta $02
    ; Check if Damage >= Health
    lda $01
    cmp $00
    rol A
    and #1
    ; Set carry flag into $01 to to indicate the player has died
    sta $01
    rts
    I do assembly on the Super Nintendo because I hack Super Mario World, but I think the Super Nintendo's processor is backwards compatible with the NES one.

    • @NesHacker
      @NesHacker  3 года назад +5

      Beautiful! Yep, that was pretty much exactly what I was thinking :D

    • @knghtbrd
      @knghtbrd 2 года назад +1

      @@NesHacker The question there is did you wanna teach cmp/bcc or and/rol and instruction cycle length. While and and rol might be good fodder for a crash course, the reason why you'd do it over just branching surely isn't. 😁
      Gotta say, I'm enjoying your approach to the basics, Ryan. Watching because I need to deoxit my brain's contacts a little. It's all coming back to me, like falling off a bicycle. (Ouch.) Now what's the equivalent of applying rust converter paint to the chassis again?

    • @yt_n-c0de-r
      @yt_n-c0de-r 2 года назад

      Would have loved a bit of comment how/why rol & and are used here, for all us noobs not proficient in (S)nes dev (yet)... In the meantime I found a solution of "pushing the carry bit out" (ROL) - still wrapping my old head around it XD
      Love the videos, even if after 20years of trying to learn this it still all is just magic to me :)

  • @mikolanimator
    @mikolanimator 3 года назад +17

    Thank you for your videos. You have an awesome channel. Great explanation and production quality. Please keep them coming. Thank you

    • @NesHacker
      @NesHacker  3 года назад +6

      Thanks for watching them! It’s always a thrill when folks watch the new videos right after I put them out :)

  • @jeffjohnson7984
    @jeffjohnson7984 Год назад +3

    Random question... what software do you use to create the stylized graphics that represent the various concepts in your videos? I think it is very well done and very clear! Thank you.

    • @NesHacker
      @NesHacker  Год назад +2

      I do custom graphics using Adobe Illustrator and animate them using After Effects.

  • @ezekieloruven
    @ezekieloruven 3 года назад +7

    I feel like address $02 was forgotten in this subroutine. It looks like the result of the routine is supposed to be stored in $02, but it gets stored in $01 instead, overwriting the damage taken. This probably doesn't matter but I'd prefer using $02 to store results.
    lda #25
    sta $00
    lda #30
    sta $01
    lda #0
    sta $02
    lda $01
    cmp $00
    rol $02
    rts

    • @NesHacker
      @NesHacker  3 года назад +4

      You’re correct. I made a mistake and accidentally used $01 instead of $02 (which is what I intended) in the example. Thanks for letting me know, another viewer had already done so, and I usually put corrections in a pinned comment on the videos. Thanks for watching and paying such close attention! :D

  • @popoffs5273
    @popoffs5273 2 года назад +4

    The 6502 processor sets the carry flag when the A reg is large that memory because when you do subtraction, the carry out will be on if the answer is positive, and off if it is negative. When it does subtraction it does a process called twos compliment in which, you flip the bits and then add on, when added to a number it subtracts if you ignore the carry out.

  • @hicknopunk
    @hicknopunk 3 года назад +4

    Oh I just hate you 😄 was about to go to bed and saw this upload. You b@stard! 😅
    Thanks for making these. Could you make a review of several 6502 hobby boards? Would I be better off just using a NES without a NES10 chip than buying something modern? It would be lovely to see the NES go up against 2 to 3 modern 6502 boards.

    • @NesHacker
      @NesHacker  3 года назад +3

      I haven't messed with them too much but that's a great idea for a video! I'm finally getting all my electronics lab stuff setup so once I get the lab put back together I'd be more than happy to do an episode on the subject. Do you have any in particular you'd like my thoughts on?
      Unfortunately I can't answer your question about which to use right now, since I haven't done much with them, but you can't go wrong getting some vintage NES gear in my opinion haha.

  • @32BitChronicles
    @32BitChronicles 2 года назад +14

    I would avoid branching by storing the carry in the address $01:
    ; Initialize Health, Damage, and the Return Value
    lda #25
    sta $00
    lda #30
    sta $01
    lda #0
    sta $02
    ; Check if Damage >= Health
    lda $01
    cmp $00
    ; Set address $01 with the value of the carry to indicate the player has died or not
    lda #0
    adc #0
    sta $01
    Amazing videos by the way! I hope you release more soon!

    • @ordozgoite
      @ordozgoite Год назад +4

      Amazing! I just didn´t understand why the result of the adc is stored on $01. I thought the return value should be stored in $02, since #0 was stored there on the beggining of the code.

    • @razorblade413
      @razorblade413 10 месяцев назад

      @@ordozgoite honestly I don't know why the result of adc is stored on $01. Is not supposed that $01 stores the damage? should not be the result of adc stored on $02 or any new memory address since health and damage have already assigned their spaces?
      What about if an enemy does an incoming damage of 1 then?

    • @razorblade413
      @razorblade413 10 месяцев назад

      @@ordozgoite In fact I still don't get it why Ryan set address $01 instead of $02 to indicate if the player has died or not.

  • @kirby0louise
    @kirby0louise 3 года назад +6

    Just copy the carry flag into the $01
    No branch instruction needed

  • @amnotonline3011
    @amnotonline3011 3 года назад +3

    Is this the solution to the "check hp without branching" puzzle?
    LDA $HP_LOCATION
    SEC
    SBC $DAMAGE_LOCATION ; If the HP is greater or equal to the Damage, the C flag will be set
    STA $HP_LOCATION
    LDA #$00
    ADC #$00 ; If the carry is clear (Player is alive / HP is exactly 0 (Call the one extra point of HP benevolent Game Design ;)), 0 will be in A, else, the carry will factor in and A will contain 1
    STA $DEAD_STATE
    (Hopefully this works the same as in 65816 asm. Love your videos!)

    • @NesHacker
      @NesHacker  3 года назад +1

      It’s close but it doesn’t give the *exact* same output. But bonus points for “benevolent game design,” haha. Thanks for watching!

  • @16bitdude36
    @16bitdude36 2 года назад +1

    ;lets assume HP=$00 , DMG=$01
    lda $01
    cmp $00
    bcc gameoverYEAHHHHHHHHHHHHHHHH
    rts;
    gameoverYEAHHHHHHHHHHHHHHHH:
    ;insert code
    Is the above code equivalent to this?
    void isAlive(uint_8 hp,uint_8 dmg)//
    {
    if(dmg>=hp)
    gameover(); //insert code
    return;
    }

  • @mohdyasir1645
    @mohdyasir1645 2 года назад +2

    Most of the things are similar to Assembly Language and Architecture of 8085 Microprocessor

  • @captainnintendo
    @captainnintendo 3 года назад +6

    I really appreciate you doing these videos and putting so much time into making the visual representations easy to understand.
    I have s question or two.
    First, I get the N flag and the Z flag. That makes sense, but I don't really get why the C-flag would also set in if the A value is equal to the compared value... Isn't that whole point of the Z flag. And what if I only want something to happen if the compared value is higher than equal?
    Also for the very last part of the code that is executed if the carry flag is 0 (Lethal hit)
    Should it be $02 that gets a value of #1, not $01?

    • @NesHacker
      @NesHacker  3 года назад +5

      So you’re right! I have a typo and it should have been $02 instead of $01 there!
      As far as I understand it, the Carry Flag is set this way so we can check all of the inequalities () via a single flag. If the 6502 only set the Carry when A > M then I’m pretty sure we’d have to use two checks in order to handle the “>=“ and “=“ and “

    • @captainnintendo
      @captainnintendo 3 года назад +3

      @@NesHacker I guess that makes sense. This is still really new to me so I'm just trying to wrap my head around the logic of all of it.

  • @yuripetrovic7606
    @yuripetrovic7606 23 дня назад

    The only thing constantly messing me up is not always having a solid example to base the code on.
    Grasping everything so far, but not the purpose behind it.
    For example, I learned swapping bytes back and forth but am not entirely sure why I would ever be dong that.
    I also don't understand the order of operations. What exactly should the very top of my code be? Initializing values, or drawing windows and borders and loading graphics?
    Fantastic tutorial, but I would have really liked if you took an existing ROM and walked us through how it's built, why everything is coded where it is and what each line of code is doing in the game

  • @PixelguardianGame
    @PixelguardianGame 3 года назад +4

    Liked and subbed! I love this channel and this series

    • @NesHacker
      @NesHacker  3 года назад +1

      Appreciate it! There’s so much more cover, so I’ll be making a LOT more videos, haha XD

  • @deabits
    @deabits 3 года назад +4

    Great video Ryan! I hope to see next video soon! Keep it up.

  • @randysmith7094
    @randysmith7094 2 года назад +1

    @ 3:58 - are absolute addresses always reversed in their 2 bytes? If I'm looking in the ROM code for a reference to RAM address $0321 then I should do a HEX string search for "2103"? Or if I know the instruction is STA, it should be found as "8D2103" somewhere in the ROM code? Right? Or does this code look different in the ROM file? Because I'm having trouble finding code for a certain "lives count" address.

    • @dimi144
      @dimi144 7 месяцев назад

      Yes. The 6502 is a little-endian machine, meaning that when it stores multi-byte values it always stores the less significant byte first, so when you write $2103 the assembler will assemble it to 0321 because the processor expects you to give it the low byte first and then the high byte after

  • @Ensign_Cthulhu
    @Ensign_Cthulhu 10 месяцев назад

    Amateur C64 programmer here. I note the absence of the Break flag on the NES. I'm assuming this is because there's simply no need for it at the user level on a system whose only function is to play cartridge games.

  • @peterponomarev1622
    @peterponomarev1622 2 года назад +1

    If Damage < Health, couldn't BMI be used as well instead of BCC? Or am I not understanding? Thanks.

    • @peterponomarev1622
      @peterponomarev1622 2 года назад +1

      I think I just answered my own question ... The carry flag would be set on greater than OR equal, both of which result in Game Over

    • @vuurniacsquarewave5091
      @vuurniacsquarewave5091 2 года назад +1

      @@peterponomarev1622 BMI and BPL are really good for terminating loops though when iterating through a set of data, because you will also need to complete your loop when the counter is 0. So right after a decrement instruction you can BPL back to the start of the loop.

  • @wildside4822
    @wildside4822 Год назад +1

    This was very helpful thanks

  • @8_BitKing
    @8_BitKing 2 года назад +2

    I loved this

  • @bandlsd
    @bandlsd 2 года назад +1

    Excellent tutorial, thanks!

  • @PabloSanchez-th5em
    @PabloSanchez-th5em 2 года назад +1

    Amazing course this it is!

  • @dr.ignacioglez.9677
    @dr.ignacioglez.9677 2 года назад +1

    I LOVE C64 👍🥂🎩

  • @andreazaffino
    @andreazaffino 2 года назад +1

    Simply sublime 😃

  • @MrMassaraksh
    @MrMassaraksh Год назад

    Thanks!

  • @pancelor
    @pancelor 3 года назад +3

    thanks for the little coding challenge; it got me to set up a dev enviroment and write some NES code for the first time! my solution:
    ; Initialize Health, Damage, and the Return Value
    lda #17
    sta $00
    lda #33
    sta $01
    lda #0
    sta $02
    ; Set Carry iff Damage >= Health
    lda $01
    cmp $00
    lda #0
    adc #0
    ; Set address $02 to death state (1=dead,0=alive)
    sta $02
    rts

    • @NesHacker
      @NesHacker  3 года назад +2

      Nice!

    • @NesHacker
      @NesHacker  2 года назад +1

      @@jakeelliott1512 So when you use ADC to add 0 to 0 it will result in a 1 if the carry flag is set (this is why it’s called Add with Carry). At this point the A register has a value of 1 if and only if the damage >= health (because the CMP instruction above only sets the carry flag in this case). So they write out the value to $02 where we want to store the result. Hope that helps :)

  • @kythrathesuntamer9715
    @kythrathesuntamer9715 Год назад

    keep making videos.

  • @saganandroid4175
    @saganandroid4175 8 месяцев назад

    OMFG can you STOP that up and down voice thing. It's like a girl that keeps up pitch talking then rapidly cycling. I'm sure you are knowledgeable and have useful information to convey but oh my God it is painful to hear people talk like this. ValleyGirl would be less painful.