don't click here

Debugging misaligned read/write

Discussion in 'Engineering & Reverse Engineering' started by flamewing, Mar 10, 2011.

  1. Chilly Willy

    Chilly Willy

    Tech Member
    751
    11
    18
    Doom 32X
    Exactly - anyplace that data may be accessed as a word (code fetches fall under this category) or a long, the address must be at least word aligned. Putting an even right before code starts, or before dc.w/dc.l/ds.w/ds.l variables assures that they will meet that alignment.

    More difficult are blocks of data where the code that deals with said blocks use a mix of byte, word, and long accesses. In such a case, you would need to make sure the block of data is built to meet the alignment rules as well.
     
  2. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    So why put an even after it if it only evens data after the word? For example, how do you know that an even doesn't need to go before "File1Location:"? I've gone through my whole ASM putting evens after the BINCLUDES and after the dc.b's and etc.


    An example:

    Code (Text):
    1. return_2D42E:
    2.     rts
    3. ; ===========================================================================
    4. ; animation script
    5. off_2D430:
    6.     dc.w byte_2D436-off_2D430
    7.     dc.w byte_2D43A-off_2D430; 1
    8.     dc.w byte_2D43E-off_2D430; 2
    9. byte_2D436: dc.b   7,  0,  1,$FF
    10. byte_2D43A: dc.b   3,  0,  1,$FF
    11. byte_2D43E: dc.b   7,  0,$FF
    12.     even
    13. ; ----------------------------------------------------------------------------
    14. ; sprite mappings
    15. ; ----------------------------------------------------------------------------
    16. Obj5C_MapUnc_2D442: BINCLUDE "mappings/sprite/obj5C.bin"
    17.     even
    18. ; ===========================================================================
    19.  
    20. JmpTo34_MarkObjGone
    21.     jmp MarkObjGone

    Should I put an even before the "off_2D430" and "Obj5C_MapUnc_2D442" and not after it?
     
  3. Chilly Willy

    Chilly Willy

    Tech Member
    751
    11
    18
    Doom 32X
    If you see code or dc.w/dc.l/ds.w/ds.l, those MUST be on an even address. How do you know they are on an even address? Some cases are simple:

    Code (Text):
    1.     rts
    2.  
    3. some_var:
    4.     dc.b 5
    5.  
    6. another_function:
    7.     movem.l d0-d1,-(sp)
    See how you have a single byte stuck between pieces of code? Unless that second bit of code at another_function is aligned, calling it will cause an address errror.

    Code (Text):
    1.     rts
    2.  
    3. some_var:
    4.     dc.b 5
    5.     even
    6.  
    7. another_function:
    8.     movem.l d0-d1,-(sp)
    That now works. However, some cases are harder...

    Code (Text):
    1.     rts
    2.  
    3. some_var:
    4.     incbin "some_data_file.bin"
    5.  
    6. another_function:
    7.     movem.l d0-d1,-(sp)
    Is another_function aligned or not? It depends on how long some_data_file.bin is. If it's an odd length, the code is unaligned again and will fail. But if the block is an even length, you don't need to worry, right? Maybe, but maybe not. Will the block ever change length? Will you remember that this block affects code later on when you change the contents of the block? Will you do something like this?

    Code (Text):
    1.     rts
    2.  
    3. another_var:
    4.     dc.b 11
    5. some_var:
    6.     incbin "some_data_file.bin"
    7.  
    8. another_function:
    9.     movem.l d0-d1,-(sp)
    Even if the file is an even length, you've changed where it starts to an odd address by adding the byte variable before it. That means since it's an even length, it will end on an odd address and the code is again unaligned. In the case of variables stuck between code segments, use alignment directives no matter what to guarantee the following code segment is aligned. Like this

    Code (Text):
    1.     rts
    2.  
    3. another_var:
    4.     dc.b 11
    5. some_var:
    6.     incbin "some_data_file.bin"
    7.  
    8.     even
    9. another_function:
    10.     movem.l d0-d1,-(sp)
    Another case people forget occurs when code is split over several files. Say file 3 ends like this

    Code (Text):
    1.     dc.b 0,0,0
    and say file 4 starts like this

    Code (Text):
    1. enemy_code:
    2.     movem.l d0-d7/a0-a6,-(sp)
    You've created an odd alignment without even realizing it. You need to keep in mind how the overall code and data sections are being populated when assembling/compiling to avoid this. For code that starts a file, ALWAYS align it no matter what.

    Code (Text):
    1.     even
    2. enemy_code:
    3.     movem.l d0-d7/a0-a6,-(sp)
    Now it doesn't matter how file 3 ends, file 4 will start with aligned code. This can also get you when you switch back and forth among sections...

    Code (Text):
    1.     rts
    2.  
    3. local_var_used_by_last_routine_above:
    4.     dc.b 1
    5.  
    6.     .data
    7. level_data:
    8.     incbin "level1.bin"
    9.  
    10.     .text
    11.  
    12. another_function:
    13.     tst.l d0
    14. ...
    15.  
    16.     rts
    17.  
    18.     .data
    19. global_var:
    20.     dc.l 53
    I've created TWO potential address errors in the above code! First the code section ends with a byte variable, but when the section resumes later, starts straight in with code. Second, I have an unknown length block of data in the data section that when the data section resumes has a long variable. Both may cause address errors. When you resume a section, you cannot really be certain how that section ended... so align it!

    Code (Text):
    1.     rts
    2.  
    3. local_var_used_by_last_routine_above:
    4.     dc.b 1
    5.  
    6.     .data
    7. level_data:
    8.     incbin "level1.bin"
    9.  
    10.     .text
    11.     even
    12. another_function:
    13.     tst.l d0
    14. ...
    15.  
    16.     rts
    17.  
    18.     .data
    19.     even
    20. global_var:
    21.     dc.l 53
     
  4. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber

    There's only one thing I do not understand.


    With this code above, you say when I make edits, it can become unaligned at anytime. So, you've put an "even" in front of "another_function". So you're saying that now, no matter what, "another_function" will be aligned, right?


    Well, why not put an "even" in front of "another_var" and "some_var"? So, that way, "another_var" and "some_var" will also always be aligned?
     
  5. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    If they aren't read as words, then alignment doesn't matter for them; if they are used as words, then yeah, they should be aligned too.
     
  6. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    I'm not sure if half of them are words or not, so I will put an "even" in front anyway. There's no harm in doing it and I won't have to worry it ever being unaligned.
     
  7. Chilly Willy

    Chilly Willy

    Tech Member
    751
    11
    18
    Doom 32X
    You have to be very aware of how the code uses bytes... for example, here's a case where two byte variables MUST be aligned...

    Code (Text):
    1.     move.w var1,d0 ; get both var1 and var2 at the same time
    2.  
    3. ...
    4. var1:
    5.     dc.b 10
    6. var2:
    7.     dc.b 10
    If var1 isn't evenly aligned, the above with blow up.

    Code (Text):
    1.     move.w var1,d0 ; get both var1 and var2 at the same time
    2.  
    3. ...
    4.     even
    5. var1:
    6.     dc.b 10
    7. var2:
    8.     dc.b 10
    But now let's say I get crazy with the evens and do this

    Code (Text):
    1.     move.w var1,d0 ; get both var1 and var2 at the same time
    2.  
    3. ...
    4.     even
    5. var1:
    6.     dc.b 10
    7.     even
    8. var2:
    9.     dc.b 10
    Oopsi! I just made the code fail in a hard to trace manner because the code is trying to load both vars at once, but that second even pushes var2 off a byte so that it won't load with that move.w. So you just can't stick evens EVERYWHERE or you may break the code. Such is the joy and fun of assembly! :v:
     
  8. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    So I found out earlier. The HUD screwed up and etc when I put an even before it. So if anything ever goes wrong, I will mess around with evens there.
     
  9. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Okay, HUGE bump here, but it looks like flamewing's question never got answered. Does his error report work on real hardware? Yes.


    A while ago, I asked ChillyWilly to try my Sonic 2 Recreation out on real hardware. Right at the beginning of the ROM, an error occurred, reported by flamewing's report (which the error never happens on emulators). I've fixed it now and my hack works 100% on real hardware. But in conclusion, yes, flamewing's report works on real hardware. Thanks to ChillyWilly for testing.