Language…
9 users online: 35TCB77, cletus_deletus, Danik2343, Hammerer, howardadam1126, KoJi, Oskise, pnaha, tOaO - Guests: 217 - Bots: 370
Users: 64,795 (2,377 active)
Latest user: mathew

How to save and load 16bit numbers

Hello, how do i save and load 16bit Numbers?

MY Problem:
I want to do this. I save a value and load it in an other asm. For explaination it is in one file. But this dont work. I Also tryed this REP #$20 Mode.

Code
LDA.w #$0078
STA $A000|!addr	
LDA.w $A000|!addr
STA $142C|!addr	


When i use this it works without problems:

Code
LDA.w #$0078
STA $142C|!addr	


This is because of the way addresses are extended from that 16-bit form to the full 24-bit form. To describe it briefly, you are not writing to $7EA000, but rather to the address $xxA000 where xx is (usually) the current bank you are running code in. This happens to be ROM, not RAM.

The reason you can reference 16-bit addresses is because addresses $0000 through $1FFF are mapped to RAM addresses $7E0000 through $7E1FFF. Addresses in the range $8000 through $FFFF, meanwhile, are generally going to be mapped to ROM. So what your code is effectively doing is "storing" to ROM (which does nothing) and then loading the actual value at that ROM address and writing it to $142C.

Instead, you should extend the RAM address to the full 24 bits. Assuming you meant to refer to $7FA000, that means you should write your code like this:

Code
LDA #$0078
STA $7FA000
;...
LDA $7FA000
STA $142C

Sidenote: you should not use the !addr value when dealing with 24-bit addresses, instead just provide an alternative value. It helps to just write the value via define rather than directly in the code, like this:

Code
!freeram	=	$7FA000		; SA-1: change to $41A000

LDA #$0078
STA !freeram
;...
LDA !freeram
STA $142C


Professional frame-by-frame time wizard. YouTube - Twitter - SMW Glitch List - SMW Randomizer
ok thx. It works perfect.

But maybe one more question...when do i use this
Code
SEP #$20
REP #$20


This "mode" has to be active in order to do something like this?

Code
LDA #$0001


and sometimes i also see this:

Code
LDA.w #$0001


This should also activate the 16 bit mode of this "A" thing?

I don't understand how to use both in a proper way.
Hello there, I can answer your first question but not the others.

REP #$20 is used when you want the accumulator to use 16-bit numbers, SEP #$20 is used when you want to use 8-bit.


YY-CHR > Photoshop.
Yes, you must be in 16-bit mode (REP #$20) to use word arguments in accumulator opcodes (LDA #$0001, CMP #$0001, ORA #$0001, etc.). If you're in 8-bit mode (SEP #$20), they will be read as if their argument is only 8 bits wide. So if you write LDA #$0001 (which assembles as A9 01 00) but that code is ran while in 8-bit mode, it'll be interpreted as LDA #$01 (A9 01) and the 00 will be read as an opcode, misaligning the rest of your code and potentially crashing the game. In this particular case the crash is certain, considering 00 is the BRK opcode.
It's easily the best thing I've done
So why the empty numb?


In regards to the ".w", that is a way of telling the assembler the specific length of the argument for the opcode you want. .b specifies an 8-bit opcode (like LDA #$00), while .w specifies a 16-bit opcode (like LDA #$0000). It does not affect whether the game will actually read the opcodes that way, though; as Koopster mentioned, having the wrong length for constants will potentially crash your game, even if Asar doesn't throw an error from doing so.

Similarly though, you can also use it to specify the specific versions of opcodes you want. For example, the opcodes "LDA $00" and "LDA $0000" are actually two separate opcodes (assembling as A5 00 and AD 00 00 respectively). The .w is a way of specifying that, regardless of whether you wrote $00 or $0000 (or $7E0000), you want to use the LDA $0000 version. Similarly:

Code
LDA.b $00		; -> LDA $00
LDA.w $00		; -> LDA $0000
LDA.l $00		; -> LDA $000000

LDA.b $7E0000		; -> LDA $00
LDA.w $7E0000		; -> LDA $0000
LDA.l $7E0000		; -> LDA $7E0000

(as a sidenote, the letters stand for "byte", "word", and "long" respectively)

This sort of thing is most useful when dealing with defines to prevent user error, or math to make sure that Asar outputs the right size of number. For example:
Code
!value	=	$10

LDA.w #!value		; -> LDA #$0010

LDA.b #$100-!value	; -> LDA #$F0

Otherwise, Asar is usually smart enough to figure out the appropriate opcode for you.

Professional frame-by-frame time wizard. YouTube - Twitter - SMW Glitch List - SMW Randomizer
ok thx
The difference between both of them is that the latter will force the number to be 16-bit (compare .b which assembles the opcode as an 8-bit value) but the former doesn't. This usually doesn't matter since Asar assembles automatically two digits as 8-bit and four digit numbers as 16-bit values sets the correct number but using labels, different amount of digits, maths or decimal values, where the bytes to encode is ambiguous, makes it more or less necessary.

Keep in mind that Asar, as an assembler, abstracts as few things as possible. This is how the value is assembled, not how they're accessed. The size of the registers are purely controlled by the processor flags i.e. only opcodes REP, SEP,PHP, PLP and RTI as well as the interrupts can affect them (and realistically, you only need to take care of the former two). Using 16-bit immediate values when you're in 8-bit mode causes the SNES to read one byte to few (or to much if reading an 8-bit value in 16-bit mode) which will run the code differently than intended.
In other words: Avoid this:
Code
	SEP #$20	; 8-bit A
	LDA.w #$0042	; Gets read as BRK $8D
	STA $1337	; Doesn't get read anymore.