Is Assembly Language syntax the same for different architectures

Viewed 885

I know that i can not write assembly language that will run/compile on all machines because they have different instruction sets,opcodes,registers etc. My question is, even though the instruction set would be different, is the assembly syntax (or the language it self) the same for any architecture?

3 Answers

My question is, even though the instruction set would be different, is the assembly syntax (or the language it self) the same for any architecture?

No!

Just for x86, there are a dozen different assemblers, each having their own uniqueness making them each accept a slightly different language — there's GAS, MASM, NASM, TASM, FASM, ASM... Few programs will assemble with all of these x86 assemblers.

There's at&t syntax vs. intel — target first vs. target last.

There's varied requirements around directives: .proc, .endp, etc..

There's Intel's beautiful byte ptr syntax for determining operation size/width, vs. most of the rest of the world's .b, .w, .l opcode suffixes (sometimes without the .).

Some assemblers like the : after label, others don't allow it (or require a , instead).

Some require special characters to differentiate register names from other identifiers (e.g. % prefix for some, $ prefix for others), others don't.

Syntax for addressing modes also vary significantly, e.g. in ARM's [] notation, the unusual location of the constant after the brackets indicates pointer variable update.

And that's without getting into the names of the opcodes.

On intel we use call for the instruction that invokes a function (transfers pc to function while capturing return address), jal on MIPS & RISC V, bsr, jsr, or bl, jms on others, etc..

The term for invoking system calls, variously syscall, ecall, trap, sc, int, swi, svc etc..

In short, there's no standardization of language, grammar, or syntax across assemblers.


As for similarities, broadly speaking, there's the concepts of if-goto conditional branching (and unconditional branching) as the mechanism for control flow constructs, the concept of labels as branch targets and data targets, one instruction per line (as @Peter mentions), mnemonic opcode with separate operands — but these similarities are conceptual rather than syntactic.

There are broad similarities among most assemblers. It's always line-oriented, like

[label:]  mnemonic [operand list]

although a few assemblers use spaces instead of commas to separate operands.

And some historical assemblers distinguish label vs. mnemonic based on starting column instead of via a : after label names. (So they enforce good style: labels at the far left, mnemonics indented) A label defines a symbol name to refer to that position in the output. (In many assemblers, a non-mnemonic on a line by itself is also treated as a label, even without a :)

Some syntaxes put the destination operand last, many others put it first, but as far as the basic grammar of parsing lines into tokens, that's a semantic issue not syntactic.

A few assemblers with significantly different syntax exist, like x86 HLA where instructions look like C function calls.

The macro processor built-in to most assemblers differs significantly between assemblers. Directive names like .long vs. dd vs. dword.

Classic MIPS assembler has a .align directive that brings previous labels with it, instead of just emitting padding at the current location. (And without .set noreorder, the assembler will actually optimize your code to fill branch-delay slots.) Again that's not syntactic, but is a big semantic difference in what .align means.

Other than that, it's pretty much universal that each line of asm assembles to 0 or more bytes of output in some section, independent of surrounding lines.

There is a term like high-level assembler https://en.wikipedia.org/wiki/High-level_assembler. However now there is no sense in using it, since as this page says:

High-level assemblers typically provide instructions that directly assemble one-to-one into low-level machine code as in any assembler

Different architectures gives usually different features like, conditional instructions, which cannot be mapped to other assembly.

If you need to create portable code, use C language. It gives you a lot of possibilities to create low-level programs. If you need to use specific architecture feature, you can use inline assembler (in GCC it's extended ASM).

Related