This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Basic ASM question

Basic ASM question
by on (#158778)
I am using NESASM3 as compiler, is there any different between labels like:

CMP #$00
BNE LabelNoPeriod
...
...
LabelNoPeriod:

V.S.

CMP #$00
BNE .next
...
...
.next

just curious about it.
Re: Basic ASM question
by on (#158781)
Both of your examples will generate the exact same binary. The period merely makes labels local, meaning they only exist between two global labels, allowing you to reuse their names, like this:

Code:
GlobalLabel1:
   cmp #$00
   bne .LocalLabel
   ;(...)
.LocalLabel:
   ;(...)
GlobalLabel2:
   cmp #$80
   bne .LocalLabel
   ;(...)
.LocalLabel:
   ;(...)

This exists so you don't have to think of unique names for labels all throughout the program.
Re: Basic ASM question
by on (#158783)
Then I've got a question as well:

What's the difference between @label and .label?
Re: Basic ASM question
by on (#158784)
@ is the default symbol for local labels in ca65. (It can be changed, though.)

@ is also the symbol for local labels in ASM6.

. is the symbol for local labels in NESASM3.

Alternatively ca65 and ASM6 also have anonymous labels (:, +, -, :+, --, etc.) with a syntax that is different between the two.
Re: Basic ASM question
by on (#158791)
Why does the same programming language use different syntax with different compilers? To me, that's like if a specific C compiler had := as the assignment operator instead of =.
Re: Basic ASM question
by on (#158792)
It's not the same programming language. These are 3 different assembly languages for the 6502.

C has standards, assembly does not. Every different CPU has different needs for an assembly language, which is part of the reason there's no standard. C is CPU agnostic, which is a big reason why it needs a standard, and can have one.
Re: Basic ASM question
by on (#158793)
Understood!

What is more efficient; to have many RTS on the same subroutine, or just having 1 at the end and many JMP to a label just before that RTS?
Re: Basic ASM question
by on (#158794)
ASM isn't really a single programming language.

Intel uses dramatically different syntax than Motorola uses different syntax than MOS uses dramatically different syntax than ARM.

Even Intel and NEC uses significantly different names for the mnemonics and registers in the same 8086 clones.

And that's entirely ignoring how AT&T/GNU decided that they didn't like that syntax and wanted to inflict upon the world the abomination that is their assembly syntax a more-nearly uniform syntax across different instruction set architectures.
Re: Basic ASM question
by on (#158796)
sempressimo wrote:
What is more efficient; to have many RTS on the same subroutine, or just having 1 at the end and many JMP to a label just before that RTS?

Another RTS saves 3 cycles and 2 bytes over a JMP to RTS. But it's often useful to have several branches that point to the same RTS (e.g. beq @bail). And if all return paths execute some common code, such as updating a pointer or storing the value in A into some variable, you might want to jump to that return path instead of duplicating the code (e.g. beq @have_player_speed).

Other parallels to the Intel/NEC situation exist, possibly to avoid the appeaance of copyright or patent infringement:
  • Use of mov on 8080/8086 vs. ld on Z80/GBZ80.
  • Use of more Intel-like syntax on the Sony SPC700, when the core is actually a 65C02 clone. Blargg implemented both Sony-syntax and 65C02-syntax front-ends for a ca65 macro pack that assembles SPC700 instructions.
Re: Basic ASM question
by on (#158799)
rainwarrior wrote:
It's not the same programming language. These are 3 different assembly languages for the 6502.

Which ones do you mean?

rainwarrior wrote:
Every different CPU has different needs for an assembly language, which is part of the reason there's no standard.

Sure, but we're not talking about different CPUs here, like the difference between 6502 Assembly and x86 assembly or the difference between the NES and the Game Boy.

We're talking about the following:

NESASM, CA65 and Asm6 all have different syntax, even when you use all three for programming the NES. (So, I assume all three of them are supposed to represent the same kind of Assembly language, right?)

And on the other hand, we have the fact that CA65 has the same syntax, even if you program for different platforms: CA65 for the NES works just like CA65 for the C64.

Then why do two compilers that are used for the same platform have different syntax?

You said there are three 6502 Assembly languages. Does that mean that NESASM uses one version, CA65 uses the second and Asm6 uses the third language version? So, another compiler's syntax would definitely be identical to either of those?

Because when they all use the same kind of 6502 Assembly, then my question is still not answered:
Why is the way to declare labels different in all three? This doesn't have anything to do with programming for different platforms, these are different ways to represent the language itself.

So, does this mean that the creator of the next NES assembler would be free to redeclare the "load into accumulator" command from LDA to LoadAcc and his design decision would be just as valid since there's no standard?
Or does this command has to be called LDA when creating a 6502 assembler?
If it has to be called like this, why are there no rules on how to declare local labels?
Re: Basic ASM question
by on (#158802)
Given so many compilers, I wonder what compiler did professional studios used? And is it still available?
Re: Basic ASM question
by on (#158803)
DRW, are you seriously asking why people make arbitrary decisions when there is no standard convention to guide them? Or are you just complaining about it in the form of a question?

If you want to know where the mnemonic names for opcodes come from, MOS published a hardware guide t the CPU that named the official opcodes. Most people would follow these when making a 6502 assembler, since there's little reason not to. The unofficial opcodes, on the other hand, were not named, and you will notice that various assemblers and documents use different names for them.

DRW wrote:
So, does this mean that the creator of the next NES assembler would be free to...

You act like there's some sort of "assembly police" that will put a stop to it. If you're making an assembler you can do whatever you want. Probably you'll mostly copy the style of some other assembler you like, but eventually you'll be adding your own features, and they'll come out in some arbitrary style, just like it did for the local label feature in these three assemblers.

Implementers of C compilers actually do have a standard to use as a guide. It's a completely different situation.
Re: Basic ASM question
by on (#158804)
DRW wrote:
So, does this mean that the creator of the next NES assembler would be free to redeclare the "load into accumulator" command from LDA to LoadAcc and his design decision would be just as valid since there's no standard?
Or does this command has to be called LDA when creating a 6502 assembler?
If it has to be called like this, why are there no rules on how to declare local labels?


What does "has to" mean?

Once the code is assembled the string "LDA" or "LoadAcc" doesn't exist, only the opcode it assembles to, so it certainly doesn't technically have to be called LDA.

And if you do happen to make it LoadAcc instead of LDA, will the 6502 police at WDC come and arrest you? No, of course not. It doesn't legally have to LDA.

So yes, if you want you can make it LoadAcc in your assembler. People probably won't like it because they're used to LDA. They're used to LDA because the original documentation for the chip called it LDA and it's what all the other assemblers use and have used since time immemorial. It's a convention, like everything with assembly language, and some conventions stick better than others. Tepples and lidnariq gave several examples of times when assembler makers bucked trends for their assemblers and made unconventional syntax decisions, for one reason or another.

Without hunting around the official 6502 documentation, WDC probably doesn't specify the format for temporary labels and stuff like that, because they don't really correspond to anything on the chip, so it's not really their business. Developers of new assemblers thus choose the format based on what's easiest to parse, what looks nicest to them, and what they're used to from whatever assemblers they've used/coded before.

There's a bunch of reasons why this stuff happens less often with, say, C compilers. For one thing, C is an ISO standard. Almost everything is specified (or left intentionally unspecified), so you often don't have much of an excuse to make stuff up on your own, and, I dunno, maybe someone might actually yell at you or even sue you if you call your compiler a C compiler if it doesn't actually compile C? For another thing, there's a massive amount of C code out there written for massive numbers of compilers for massive numbers of platforms, and the nature of (and reason for) the C standard is such that you, to some extent or another, expect standards-compliant C code to compile on all of it and will get mad at you the compiler writer if they need to change all their =s to :=s, whereas by convention and due to the lack of standards assembly programmers generally don't expect their code to assemble without modifications with other assemblers. And finally, in fact, many so-called C compilers do have subtle incompatibilities/deviations from the standards, because of bugs or technical limitations (as in cc65) or just because they're not feature complete for time/effort reasons (or in the case of something like CompCert, probably because of unresolved research issues).
Re: Basic ASM question
by on (#158806)
rainwarrior wrote:
DRW, are you seriously asking why people make arbitrary decisions when there is no standard convention to guide them? Or are you just complaining about it in the form of a question?

I want to know whether there are really no conventions. After all, it looks like you always have LDA in a 6502 assembler. I don't think anybody would create a 6502 assembler that uses another code for this command.

You said there is a list of official opcodes. O.k., so we do have some kind of "standard" after all.


adam_smasher wrote:
What does "has to" mean?

Once the code is assembled the string "LDA" or "LoadAcc" doesn't exist, only the opcode it assembles to, so it certainly doesn't technically have to be called LDA.

I know this of course. In this context, "has to" means: "You should better design your 6502 assembler this way if you don't want people thinking that you're an idiot."
Nobody in his right mind would design a 6502 compiler where he replaces LDA with another word. But other syntax details seem to be fair game for change. And I just wanted to know where you draw the line. What is a quasi-standard and what is dependent on each developer? That was my question.

But I guess I understand it now. I was under the assumption that a specific assembly language is (or should be) completely defined within itself (like in "this specific assembly language for this specific CPU looks the same in every compiler"). But it seems that the compiler creators have much more freedom here since nobody actually expects complete code compatibility between two compilers, even if they're for the same target CPU.
Re: Basic ASM question
by on (#158808)
DRW wrote:
You said there is a list of official opcodes. O.k., so we do have some kind of "standard" after all.

It's a standard for the names of opcodes.

There's no standard for assembly language on the 6502. MOS didn't specify an assembly language, they just gave names for the CPU's instruction set. (An assembler is much more than just mnemonics.)
Re: Basic ASM question
by on (#158812)
sempressimo wrote:
Given so many compilers, I wonder what compiler did professional studios used? And is it still available?


I'm not sure what the actual NES developers used, but all the source code I've seen (mostly music code on RHDN) looks very similar to the syntax currently used.

Here's an Apple Assembly program from 1982 called MAC/65...https://youtu.be/Z8F6TRwbGM4

Here's one for the Commodore 64...https://youtu.be/0e-gpzUAdWA

Kind of amazing that they were able to create great games when this was the programmers had to work with. I read somewhere they created graphics on early games by writing hex on top of a graph paper sketch and entering them in one hex byte at a time. (Music also).
Re: Basic ASM question
by on (#158814)
Quote:
And is it still available?


It would only run in an emulation of an obsolete computer (like the Apple II). And it wouldn't be able to do 100+ things that we take for granted today (like cut and paste).
Re: Basic ASM question
by on (#158816)
I'm pretty sure that a modern day programmer would be incredibly annoyed by all the limitations of an old assembler, and would never consider it for actual game development. Many of the things we have today, like macros, long labels, scoping, etc. were probably not available back then.
Re: Basic ASM question
by on (#158818)
dougeff wrote:
Here's one for the Commodore 64...https://youtu.be/0e-gpzUAdWA

This looks like a disassembly, not source code. BTW, what a weird way to share source code, using YouTube!
Re: Basic ASM question
by on (#158819)
Prince of Persia for the Apple II was written using the Merlin assembler.

Some info here, and links to the PoP source: http://fabiensanglard.net/prince_of_persia/

There's a lot of assemblers out there, past and present. It's normal for game development projects to involve the writing of proprietary tools. Nowadays most game studios wouldn't write their own C compiler, but a simple assembler is a small enough task that it would have been reasonable for a lot of them to have their own in-house assembler.
Re: Basic ASM question
by on (#158824)
tokumaru wrote:
dougeff wrote:
Here's one for the Commodore 64...https://youtu.be/0e-gpzUAdWA

This looks like a disassembly, not source code. BTW, what a weird way to share source code, using YouTube!


I was trying to show the awkwardness of the assembers used in the 80s. I think a video is helpful here.
Re: Basic ASM question
by on (#158826)
Isn't Nesasm based on an assembler by Hudson Soft that they used for PC Engine and/or Famicom or something?
Re: Basic ASM question
by on (#158828)
Pokun wrote:
Isn't Nesasm based on an assembler by Hudson Soft that they used for PC Engine and/or Famicom or something?

No, I don't think so.

It was originally part of MagicEngine / MagicKit which is an old assembler for PCE and NES, but by old I mean 15 years, not 25, and there's no connection to Hudson Soft, AFAIK.

(Also, whatever Hudson Soft used was probably worse than NESASM3 anyway, so it's not like it would be a good association to have. :P)
Re: Basic ASM question
by on (#158830)
DRW wrote:
Nobody in his right mind would design a 6502 compiler where he replaces LDA with another word.

Unless of course you're Martin "nocash" Korth and you have a hadron for x86-style syntax. This might make you faint.
Re: Basic ASM question
by on (#158832)
And that would lead to some of the dumbest programing ever... Just imagine messing up something as simple as this:

Code:
lda #$FF
sta $00
sta $01

with this:

Code:
lda #$FF
sta $00
lda #$FF
sta $01

which I'm pretty sure would equal this in x86:

Code:
mov word [0x00], 0xFF
mov word [0x01], 0xFF


Edit: I just changed the numbers from 16 bit to 8 bit because it makes more sense here.
Re: Basic ASM question
by on (#158838)
I don't think Martin's adding any faux addressing modes - there's no immediate -> memory mov listed there. It's just a different surface syntax.
Re: Basic ASM question
by on (#158840)
Oh... Never mind! :lol:

In a way though, that's slightly even more ridiculous... If you have to memorize the differences in how the processor functions, how hard would it be to just memorize a separate 3 letter word? I mean, "mov" and "lda" don't function exactly the same.
Re: Basic ASM question
by on (#158841)
Even though there may be established official names, there indeed are cases where assemblers decided to use different names for op codes for whatever reasons(maybe for copyright reasons or the people didn't even have any idea what the CPU was and drafted the names according to reverse-engineered information).

I remember a certain FDS hacking tool (possibly published by Hacker or its affiliates) could view deassembled files. It used really odd names for op codes such as JC for BCS, etc. (It's been > 20 years and my memory is vague.)
Re: Basic ASM question
by on (#158862)
When I see MOV, x86 is not the first thing that pops into my head... 68k is.

Quote:
Nobody in his right mind would design a 6502 compiler where he replaces LDA with another word.

What about the z80 and 8080?

Different syntax exist for x86 on the Wondersawn too (mednafen has a switch option for the disassembly window because of this - though I don't remember how big the difference was).

Code:
lda #$FF
sta $00
sta $01

as..
Code:
mov Acc,#$ff
mov $00,Acc
mov $01,Acc

(mov ds,sr)

Why would someone confuse it as something else?


I have zero problems switching between different syntax, if it has a benefit. I have 68k-ish macros for the 65x that I've used on non speed sensitive code, to be read as more compact and easier to sort through, etc. But leave it as an option for macro instructions, or at least an alt set of mnemonics. That is, if you want someone to actually use said assembler.
Re: Basic ASM question
by on (#158870)
rainwarrior wrote:
Pokun wrote:
Isn't Nesasm based on an assembler by Hudson Soft that they used for PC Engine and/or Famicom or something?

No, I don't think so.

It was originally part of MagicEngine / MagicKit which is an old assembler for PCE and NES, but by old I mean 15 years, not 25, and there's no connection to Hudson Soft, AFAIK.

Not sure where I heard it but I kind of thought MagicKit and Hudson's Develo had some kind of connection. Though the Develo assemblers are not for IBM-PC, so it might be that MagicKit is a fan-developed IBM-PC alternative to the commercial development kit? PCEAS and NESASM are separate in MagicKit, but I guess they were one and the same in earlier versions? In NESASM history file it certainly says that all PC Engine opcodes and stuff were removed.


Quote:
(Also, whatever Hudson Soft used was probably worse than NESASM3 anyway, so it's not like it would be a good association to have. :P)

Yeah well I'm not a fan of NESASM at all, what with the forced bank splitting no matter if you need it or not and all that.
Re: Basic ASM question
by on (#158873)
I've always felt the nocash 6502 syntax is dumb; to me, at least, it makes the processor seem more irregular and makes it harder to keep track of what is and isn't possible ("What do you mean I can't MOV X,[[foo]+y]?"). Sure, it becomes a bit more familiar for x86 or Z80 programmers, but I feel it isn't worth it. There's also the issue that, say, MOV doesn't change flags on x86, but LDA, LDX, and LDY do; using the word MOV might make it harder to keep the 6502 and x86 semantics separate in one's head.

tomaitheous wrote:
When I see MOV, x86 is not the first thing that pops into my head... 68k is.


Except the standard M68k mnemonic is "move". I can't think of a non-Intel processor that uses "mov" off the top of my head (other than the fictional processor used in the puzzle game TIS-100). (EDIT: ARM does.)
Re: Basic ASM question
by on (#158876)
Sony's syntax for SPC700 also uses MOV. Look how similar it is to the Intel-inspired Nocash syntax, differing mostly by an extra pair of brackets vs. # for immediate.