Some ASM tutorials in regards to making NES Maker stuff

User avatar
Kasumi
Posts: 155
Joined: Fri Mar 09, 2018 11:13 pm

Re: Some ASM tutorials in regards to making NES Maker stuff

Post by Kasumi » Sat Jul 21, 2018 10:48 pm

I know ifdef is not if, but if still only controls what gets assembled, not what gets run. The asssmbler doesn't really have enough information to create a branch because most values it has can be interpreted as multiple things. The simplest example is signed and unsigned numbers.

The 8bit value -1 is equal to 255. Really!
%11111111
or
$FF
=
-1
If interpreting the value as signed.
%11111111
or
$FF
=
255
If interpreting the value as unsigned.

All 8bit values where the leftmost bit is set can be interpreted as a negative OR a positive number, not just %11111111.

Code: Select all

lda #-1;Assembles as $A9 $FF
lda #255;Also assembles as $A9 $FF
Try it!

The programmer knows whether they want to interpret any given value as positive or negative. They choose the branch they need based on this. The assembler doesn't know and that's why it can't choose branches without more context. Check out this example similar to the above:

Code: Select all

lda #-1;Load the accumulator with -1
cmp #255;Compare to 255
bne label;If the two numbers were not equal, skip
lda #2;Will this line of code run?
label:
Yes, that line of code runs. The value 2 will be in the accumulator at the end of that example. The branch won't happen because %11111111 is identical to %11111111. Knowing this, look at this example:

Code: Select all

lda #-1
sta variable

lda #0
sta variable2

if variable > variable2
     lda #2;Should this run or not?
endif
-1 is not greater than 0.
255 IS greater than 0.

So what code should the assembler generate for the if statement? Should a branch be generated that would skip the load accumulator with 2, or should a branch be generated that doesn't skip the load accumulator with 2? There's not enough information given to figure that out. The above example might seem easy because the store of the negative constant is directly above the if. But imagine if the if was in a subroutine, and 255 and -1 were both stored to variable throughout the program. The assembler would have to guess what the programmer wants.

What ends up happening is that the address for variable is compared with the address for variable2. Those are things that can't change at runtime. Those are things the assembler doesn't have to make a guess for. If the address is greater, lda #2 is added to the program. If the address is not greater, those two bytes aren't added. No branch is generated either way.

Signed vs unsigned is only one of many things that means the context must be guessed. A number can also be 8 bit, or 16bit, or 24bit or 64bit, and you can compare a signed number to an unsigned number or an 8bit number to a 16bit number. This is also why you need multiple macros even for one type of comparison like I mentioned. Is -1 equal to 255? As far as the CPU is concerned, yeah. So if you want 255 to equal 255, but you also want -1 to NOT equal 255 you need macros you can provide the context of the values to. This is why C has you add types to things.

Code: Select all

char variable = -1;
unsigned char variable2 = 255;
Languages without types usually solve the problem in a different way (variables are always signed, and can even be non integers to cover a large range of possibilities), but still usually have a way to force context when it's needed.
User avatar
Mihoshi20
Posts: 441
Joined: Tue Mar 06, 2018 11:47 pm

Re: Some ASM tutorials in regards to making NES Maker stuff

Post by Mihoshi20 » Sun Jul 22, 2018 1:21 am

Okay, so then yeah, that function of ASM6 wouldn't be helpful at all since it only matters what gets assembled instead of used for logic in the game itself. Macro or pure asm loops/logic traps it is.
darkhog
Posts: 256
Joined: Sun May 13, 2018 10:02 am

Re: Some ASM tutorials in regards to making NES Maker stuff

Post by darkhog » Sun Aug 12, 2018 9:23 pm

Okay, so how would I do a switch..case in assembly? Just assembly equivalent of if..else if? Anyway, thanks for all the help, guys (and girls, if any posted here).
User avatar
Kasumi
Posts: 155
Joined: Fri Mar 09, 2018 11:13 pm

Re: Some ASM tutorials in regards to making NES Maker stuff

Post by Kasumi » Mon Aug 13, 2018 12:15 am

A switch..case is a jump table in assembly: http://wiki.nesdev.com/w/index.php?titl ... edirect=no

That link contains several ways. Be aware you can't really sanely do non contiguous cases like you can in things you're probably used to, however.

So if you needed like

Code: Select all

switch(  variable  ){
			case 26:
				
				break;
			case 44:
				
				break;
			case 127:
				
				break;
			case 250:
				
				break;
		}
You're better off just doing if/else. But if you need a more usual

Code: Select all

switch(  variable  ){
			case 0:
				
				break;
			case 1:
				
				break;
			case 2:
				
				break;
			case 3:
				
				break;
		}
You're good.
Note that after jumping to a label from the address table, it's up to each of them to jmp back in order to be exactly like a switch. (But sometimes having them jump back is not desired.)

Edit: Since the article is not totally clear (and in ca65 syntax, I think), here's what the tables would look like:

Code: Select all

; Jumps to the subroutine indexed by 'A'.
do_action:
       asl
       tax
       lda table,x
       sta ptr
       lda table+1,x
       sta ptr+1
       jmp (ptr)
postswitch: 
       rts
      
table:
     .dw case1
    .dw case2
     
case1:
;code for case 1 here
       jmp postswitch
case2:
;code for case 2 here
       jmp postswitch
And here's the faster split table method (without the case labels since that part doesn't change):

Code: Select all

table_lo:
    .dl case1
    .dl case2
table_hi:
    .dh case1
    .dh case2

; Jumps to the subroutine indexed by 'A'.
do_action:
       tax
       lda table_lo,x
       sta ptr
       lda table_hi,x
       sta ptr+1
       jmp (ptr)
postswitch:
Note that these don't check for an out of range case. (An out of range case will likely crash the program)
Post Reply