This question may have the apparent form of a question soliciting a "list" answer, but I'm expecting the list to be very short, so please bear with me.

What "unusual" syntax assembly languages are/were there? My reason for asking this was that the first assembly language programming I did was on the English Electric KDF9, whose weird and wonderful assembly syntax is described below.

That needs some explanation for sure.

Most assembly languages for current handware follow a fairly similar lexical stucture. The opcode maps to a alpahbetic symbol (occasionally augmented by digits or a couple of other characters, for example period or underscore)., generally suggesting a verb. An instruction has an optional label, followed by the opcode symbol, followed by the operands. The operands may include a handful of symbols which indicate indexing, indirection, address mode, etc.

That is, despite the variation in specifics, the general pattern is like

        ADD REG,BAR
        STORE REG,FOO 

So that's the sort of pattern I'm not interested in, for this question. A few weird delimiters added to the above don't count either.

In prestandard days, though, there were sometimes interesting variations.

Example 1

KDF9 Usercode, admittedly a fairly impoverished assembly language (no arbitrary user-defined symbols!) had what has been described as 'distributed syntax'. For example, an indexed load from memory to stack ("nest" in KDF9 terminoolog) is written like


'V42' is the name of some data item (no arbitrary user-defined symbols!), M7 means 'modified by register 7', and Q means that the modifier is to be incremented afterwards. (Where other machines had 'index registers', KDF9 had 'Q-registers', divided into modifier, counter, and increment parts, uxeful for indexing, base addresses, counting, and array access). The operation was implicitly a fetch; store would be indicated by '='.

Adding two numbers would thus look like

V42;  V43; +;  =V42;  (FOO = FOO + BAR);

This is "fetch V42 to stack; fetch V43 to stack; add top 2 stack words and leave sum on stack; pop stack and store in V42". The addition operation is indicated by '+' and not by, say, 'ADD'. It's a zero-address machine so the operands are implciit. The parenthetical clause is a comment. And newlines have no significance - this was fairly common in papertape cultures.

There were some data-manipulation instructions that did use 'words' for them, when there was no reasonably mnemonic symbol in the Flexowriter repertoire. For example, DUP; duplicated the top-of-stack value (i.e., pushed another copy on the stack).

Example 2

Manchester University's MU5 also had an interesting syntax. The addition example would be written as

      ACC = FOO
      ACC + BAR
      ACC => FOO

ACC is the name of a machine register, obviously the accumulator. The rest of the symbols should be self-explanatory.

(Bio note: I have programmed on the KDF9. I never met the MU5, though it was discussed in undergrad courses as an exciting example of a machine designed for higher-level languages, that the guys over in Manchester were inventing. I know there's at least one MU5 programmer in this forum).

Not an example

I'm excluding things like Turing's programming system at Manchester, since that just consisted in typing whatever teleprinter symbol made up the next 5 bits of the instruction stream.

So: was that the extent of the scenic detour off the highway to dull standardization, or are there other interesting examples?

Clarification: for this question, the assembly language should have been intended in principle for human programmers to use to write programs. Languages only intended for communication between programs, say as communication between different stages of a programming system, are excluded. Also, I'm only interested in actual code. No pseudo-ops, no directives, no macro definitions or calls, and not data declarations either.

  • 5
    Most Forth implementations had a reverse polish assembler. – NomadMaker Apr 18 at 13:09
  • 4
    Not at all retro, but Analog Devices' Blackfin CPUs use a very high-level-looking assembly language: R0 = R1 + R2 for example. – jasonharper Apr 18 at 13:16
  • 3
    Current count for this "not a list" answer is already up to 7. Highest voted answer should probably be converted to a Community Wiki. – Brian H Apr 18 at 14:19
  • 1
    @BrianH re list count. Indeed. There are more weird syntaxes in heaven and earth than are dreamt of in my philosophy! I should get out more. – another-dave Apr 18 at 14:23
  • 1
    How high level are you willing to consider as 'assembly' language? There are at least a few hardware/VHDL implementations of runtime VM's out there (Jazelle on ARM for example, and there have been research projects to do soft-core implementations of BEAM and the CIL runtime in hardware). Depending on how you consider those, that expands the list quite significantly. – Austin Hemmelgarn Apr 19 at 16:41

11 Answers 11


Example 1

The PDP-8 had only 8 kinds of instructions, but one of them was "microcoded" operate command: Different bits in this command would turn on different operations, which could be combined. Here's a list of the first group of such commands:

7000 NOP   no operation
7001 IAC   increment acc
7002 BSW   byte swap (-> rotate twice)
7004 RAL   rotate acc and link left one
7006 RTL   rotate acc and link left two
7010 RAR   rotate acc and link right one
7012 RTR   rotate acc and link right two
7020 CML   complement link
7040 CMA   complement acc
7100 CLL   clear link
7200 CLA   clear acc

So if you wanted to clear the accumulator and then increment it, effectively loading the constant 1 into the accumolator, you could combine the opcodes:


and the assembler would OR the corresponding bit patterns to give you 7201 as the octal opcode.

The same worked for all other combinations (but not all of them would do something useful).

Example 2

There are CPUs that use a subset of Forth as their assembly language, and Forth is of course quite different from the "standard" assmbler syntax you describe in the question.

One relatively modern example is an FPGA implementation called J1 Forth CPU. Here you can see how the Forth operations are defined in terms of this "machine language".

Example 3

The CDC 6000 series had a variation of the "standard" assembly syntax where you could mix in an arithmetic symbol on the right hand side, making it more look like a mathematical formula. Also, the result register was part of the operand mnemonic. So

BX1   X2 * X3

would calculate the logical product ("AND") of registers X2 and X3 and store it in register X1, while

BX1  -X2 + X3

would complement register X2, and then form the logical sum ("OR") with register X3 and store it in register X1. Both of these had a single opcode each.


FX1   X2 + X3

would calculate the floating point sum of X2 and X3, and store it in X1.

Example 4

The IAS family (ENIAC etc.) also had an assembler notation that looked more mathematical. Note that no actual assembler as a program existed, these were translated by hand into opcodes. An example from this site:

; adds up the values n+...+3+2+1(+0) in a loop and stores
; the sum in memory at the location labeled "sum"

loop:   S(x)->Ac+  n    ;load n into AC
        Cc->S(x)   pos  ;if AC >= 0, jump to pos
        halt            ;otherwise done
        .empty          ;a 20-bit 0
pos:    S(x)->Ah+  sum  ;add n to the sum
        At->S(x)   sum  ;put total back at sum
        S(x)->Ac+  n    ;load n into AC
        S(x)->Ah-  one  ;decrement n
        At->S(x)   n    ;store decremented n
        Cu->S(x)   loop ;go back and do it again   

n:     .data 5  ;will loop 6 times total
one:   .data 1  ;constant for decrementing n
sum:   .data 0  ;where the running/final total is kept

Possible other examples

I guess there's more, in particular for very early computers, assembler notation was all over the place. The reason for that is that the "standard" assembler notation makes it easy for an actual assembler program to do the translation. With translations done by hand, as in the above example, there is no pressure to make the notation easy to parse by a program.

| improve this answer | |
  • 1
    Example 1 sounds quite similar to the HP 1000 series CPU. It's assembly language contained two "groups" called "alter / skip" and "shift / rotate", in which instructions could be combined by ORing them. – Michael Karcher Apr 18 at 6:47
  • 1
    I was going to mention Forth CPUs, the example I was thinking of was the GreenArrays GA144 - which will seem familiar to those who have played TIS-100 :) . Example MD5 implementation on a GA144 : greenarraychips.com/home/documents/greg/AN001-141023-MD5.pdf – matja Apr 18 at 7:49
  • 1
    Maybe SHARC DSPs assembly, using infix notation and showing parallel execution of load/store, ALU... – TEMLIB Apr 18 at 10:47
  • For the CDC 6000 example, is BX1 X2 * X3 still a single machine instruction? – another-dave Apr 18 at 14:13
  • @another-dave Yes, it's a single instruction, like the other examples. – dirkt Apr 18 at 15:16

This is a frame challenge answer.

The Burroughs Large Systems B5000 was specifically designed for being able to run programs in high-level languages (meaning COBOL, ALGOL, FORTRAN), multiprocessing, virtual memory. It had tagged memory, and builtin concurrency and multiprocessing.

The feature relevant to this particular question, is rather lack of a feature: the B5000 doesn't have an assembly language. Its "lowest" system programming language is Executive Systems Problem Oriented Language (ESPOL), an extension of ALGOL 60.

ESPOL, however, does have direct equivalents for all low-level instructions.

The B5000 was a big influence on Alan Kay both in the design of OO in general and the design of the Smalltalk VM. It was also reportedly an influence on the Pascal P-Code system (which was also an influence on the Smalltalk VM). The Smalltalk VM and P-Code, in turn, were an influence on the JVM. So, in the biological sense of "success" (spreading your genes), it is one of the most successful hardware architectures in the history of computing.

| improve this answer | |
  • 2
    And of course the KDF9 mentioned in the question was a big influence on the Burroughs B5000, so it's not that surprising you also get a similar syntax. – dirkt Apr 18 at 14:05
  • 3
    I claim that a non-existent language doesn't have unusual syntax. I can think of lots of languages that don't exist, and they all have the exact same written form :-) – another-dave Apr 18 at 14:08
  • 2
    @another-dave: As I wrote in the preface, this is a frame challenge answer. I would argue that the language on the B5000 which plays the role that assembly languages play on almost all other architectures, has an unusual syntax for an assembly language. Now, the reason for that is, of course, that it isn't an assembly language, it is a high-level language in the ALGOL family which also has different semantics, but nevertheless, it is used in domains where you would otherwise use assembly language, and it is used by engineers who would otherwise use assembly language. – Jörg W Mittag Apr 19 at 7:13
  • 2
    @another-dave This would lead to the meta question: What is an assembly language? Does a Forth CPU that is programmed in a subset of Forth have an assembly language? Does that make (that subset of) Forth an assembly language? – Michael Graf Apr 19 at 7:14
  • 1
    @MichaelGraf My notes for the Burrough have a quote by Gary Kildall that says this series is an "offshoot of the English Electric KDF-9". I have not writting down the source of the quote, and I cannot find it quickly. I also didn't verify it. So it might be that Gary Kildall was mistaken, that the quote is wrong, or that the development of the B5000 series actually was inspired by the development of the KDF9, no matter which was released earlier - I don't know, and I didn't check. But they do look similar enough, if you look at it, so there's definitely an influence, in whatever direction. – dirkt Apr 19 at 8:06

[Preface: This question is not only quite broad, but as well rather opinion bases. After all, what is 'unusual' depends a lot on personal experience and preference. To me for example GNU assembler's reversion of target and source is quite unusual.

Having said that, I feel the question gives a great chance to create some overview]

As I understand it, the question is about how and Instruction Set Architecture (ISA) is represented in its (native) assembler, an what variations exist. It's important to keep in mind, that this quite influenced by the way an ISA is viewed (*1)

Basic Schools

There are several basic schools for ISA representation in Assembler:

(I tried to use as modern examples as possible to ease reading)

  1. One Opcode one Mnemonic

    Each and every binary opcode gets it's own mnemonic. A typical example would be the Datapoint 2200 or Intels 8008. Here each opcode gets its own name

    • LAB - Load register A with the content of register B
    • LAM - Load register A with the memory content addressed by the Memory pointer (HL)
    • LA # - Load register A with the constant # given as parameter

    Assemblers of this kind can be written very fast as all they have to follow is a one-on-one replacement of the mnemonic to an opcode and optional turning a simple, usually numeric value into a byte/word sized parameter. They are extreme close to the binary ISA representation. These tend to be quite small and are often the first stage to get a system running. The 6502 and the first cross assembler running on a timeshare system are a good example.

  2. One Mnemonic many opcodes

    Here each mnemonic describes a function, the opcode used is to be derivative from the parameter given. The most radical or clean, as one prefers, of the classic 8 bit age might be the Z80. Here all 161 possible encoding for data move between registers and register and memory as summarized in one mnemonic LD.

    This clearly eases learning as a new programmer can focus more on generic function used than specific encoding. Of course it comes with a more complex assembler structure, as now parameters must be scanned before deciding on the opcode to be generated - and it's parameter accordingly. It may end up with source constructions in need of additional specifiers to pick the right opcode. Motorolas 68000 .b/.w/.l postfix notation as example. Or the unique (*2) address syntax on a 6502.

  3. Encoding like Structure

    While this may sound like a sub section to #1, it's not much about giving a distinct encoding to each instruction, but about the mnemonic being the instruction - effectively reducing the assembler even more. An example would be the IBM TPM (Tape Processing Machine) and it's 701 follow up, were the opcodes were direct related to 5 bit TTY encoding. Like A for Add, W for Write - of course, it did work out way less easy to remember for many other instructions :)

  4. Synthetic Mnemonics

    Here no fixed opcodes are given, but an operation is syntesized from a set of symbols. It works somewhat like qualifiers, except, none of the elements are a base opcode. Operation is usually VLIW alike. The most prominent example here is maybe the Zuse Z22, were

  5. Single Parameter

    These syntax try to limit parameters to a single one, even if the abstract logic of the instruction is about two independent ones. This is much like the #1 attempt for opcodes. The 6502/6800 make a good examples by including one parameter into the instruction:

    • LDA - Load register A
    • LDY - Load register Y
    • LDAB- Load Accumulator B
  6. Multiple Parameters

    Other allow for two or more distinct parameters. While limited two address ISA can get around with byzantine mnemonic constructions (Like 6800's LDAA), full two address must go that way.

    This is much related to the move form a type #1 mnemonic structure to a type #2. And like it, an assembler handling such source statements will need to be more complex in it's decision tree - for example decoding different addressing modes and selecting the opcode accordingly.

  7. Embedded Parameter

    These syntax does not spread out parameters over separate elements (words) but concatenates them into the instruction. While this is to some degree true for #5 syntax, it goes beyond as no spaces or delimiters are used at all. 'Freiburger Code for the Z22 for example goes that way:

    • T5000T is a pseudo op working much like ORG in other assemblers, seting Drum location 5000 as next target.
    • CB3000 instruction to load a word from address 3000
  8. Parameter Order or Left to Right vs. Right to Left?

    Should parameters be given as source first or destination first? This is as much a source of holy wars (*3) as it is about history. Early (Load/Store) architectures often encoded one parameter as part of the instruction, using inherently both ways

    • like the 6502's LDA/X/Y register mentioned in the mnemonic would be the fist parameter, so making it destination, source, while
    • its STA/X/Y turns it into source, destination.

    Since most instructions, except stores, use the destination first notation, it does seam more natural when assemblers evolved/had to evolve from single to multiple parameter. Then again, some two address machines ISA was structured as source,destination from the very first iteration on.

    Of course, with more than two parameters, it gets even more arbitrary.

Real Assemblers:

While some assemblers are direct implementations of one of these schools (and mentioned above), many are a combinations. Examples may be:

  • 8080 and 6800/6502 are for example mixtures of #1 and #2.

    • While Intel did unify some instructions on the move from 8008 to 8080, like turning all load between registers into a single MOV mnemonic, it kept a separate mnemonic all other data transfers.

    • 6800/6502 did unify most instructions of the same function into a single mnemonic and have the parameter addressing decide which encoding, but at the same time all register to register transfers got their own mnemonic (TAX, TXA, ...)

  • 'Freiburger Code' might be something inbetween assembler, loader and script processor. It's basic syntax is meant to create the various bit of the instruction, but it as well can execute an instruction while assembling/loading if an Eis appended. Using an E as prefix in turn can load any instruction from memory and execute it (E4010 -> execute instruction at memory location 4010). There are several other such pseudo instructions and instruction modifiers as ell - effectively blurring any borders between assembler source, compiler script, command script and application.

*1 For example a /360 is usually seen as a single opcode to mnemonic relation (#1), as that's the way it is used in all documentation. But noone stops us from seeing the opcodes as structured in a 2+6 fashion with the top two bis holding the addressing modes (for most instructions).

*2 - But not always simple/intuitive.

*3 - Quite much like the war between using 'Move' vs. 'Load/Store'. While I, as a /360 guy, would like to see both, I've experienced quite fierce discussions favouring either.

| improve this answer | |
  • 2
    The gas syntax is also unusual and much less readable to me (esp. the memory dereference syntax). They made things even far worse by making everything harder to look up in the CPU manual – phuclv Apr 18 at 16:57
  • 2
    @phuclv: GAS was just being compatible with an existing Unix assembler for some existing 386 Unix at the time. That made sense at the time. It's really unfortunate that whoever those clowns were picked some craptastic syntax different from the Intel manuals, influenced by PDP11. What was the original reason for the design of AT&T assembly syntax? (And they even got the operands reversed vs. the normal AT&T convention for some x87 non-commutative instructions.) So blame them, not GNU; At least most tools can use .intel_syntax noprefix these days – Peter Cordes Apr 19 at 2:24
  • 1
    re: gas syntax - as a non-x86-assembly programmer who occasionally needed to read it, I found the Intel syntax to be incoherent. I think it's a matter of what you're used to. – another-dave Apr 19 at 13:18
  • 1
    @PeterCordes The Gnu Assembler was written originally for VAX/11 which used a source first format. Also Stallman started writing Gnu on a 68000 system, again a source first format. It was also expected to be used mainly as a backend for gcc generated output, not for humans to write in. – JeremyP Apr 20 at 9:15
  • @JeremyP: I guess that would explain why GAS picked the (pre-existing I think) source-first AT&T syntax for x86, then. GAS for ARM, MIPS, and plenty of other ISAs is destination-first, using the only syntax that ever existed for those platforms. (\@another-dave: if you want incomprehensible, PowerPC does it for me. So much functionality packed into each instruction, multiple immediate fields for (very nice) insns like rlwinm, but hard-to-read choices for mnemonics, numbering bits IBM-style from the top of the register, and there's even an eieio mnemonic.) – Peter Cordes Apr 20 at 9:29

SHARC and Blackfin architectures processors are said to have "rich algebraic assembly language syntax" and are unsual in their own way. The syntax is somewhat C-like

.VAR buffer3[ 0x100];

[I1] = R0;
R1 = 0X1234;

LSETUP (begin_loop, end_loop) LC0 = P1;
        R1 *= R2;
        R2 = [I0++];
         R0= R0 + R1 (NS) || R1 = [P0++] || NOP
R0 = R0 + R1
JUMP outer;

R0 = DLAB | EPS (z);

The TigerSHARC variant is a VLIW architecture and has similar highly readable instructions:

XR0 = CB [J3 += 1];;
if NLC0E, jump start;;
| improve this answer | |
  • TI TMS320 series also often have algebraic syntax – Igor Skochinsky Apr 18 at 22:05

It would be remiss if we're talking about assembler syntax to leave out the clever assemblers for Forth.

Clever in that writing assemblers for Forth is quite straightforward and historically requires very little code.

Forth assemblers are noted for their prefix syntax and they're idiomatic use of higher level branching and looping constructs in contrast to typical assembly leveraging comparisons, branch instructions, jumping and looping. Forth assemblers tend to not rely on things like labels. (They exist, they're simply not common in use.)

Forth assembly is also typically done in small chunks.

CODE (FIND)   (S here alf -- cfa flag | here false )
  DX POP   DX DX OR  0= IF   AX AX SUB   1PUSH   THEN            
  BEGIN   DX BX MOV   BX INC   BX INC                            
    DI POP  ( here )  DI PUSH   0 [BX] AL MOV                    
    0 [DI] AL XOR   63 # AL AND   0=                             
    IF  BEGIN  BX INC   DI INC   0 [BX] AL MOV                   
          0 [DI] AL XOR   0<> UNTIL   127 # AL AND   0=          
        IF   DI POP   BX INC   BX PUSH   DX BX MOV               
             BX INC   BX INC  0 [BX] AL MOV   64 # AL AND   0<>  
          IF   1 # AX MOV   ELSE   -1 # AX MOV   THEN   1PUSH    
    THEN  THEN   DX BX MOV  0 [BX] DX MOV                        

Commonly found is Forth meta-compilers that build Forth from Forth, the FIND routine is often one of the largest assembly routines in the system. But it shows off the assembler handily. Above is the (FIND) primitive in 8086 from F83.

This shows off the prefix format DX POP vs conventionally POP DX. The 0 [BX] AL MOV is normally MOV AL, [BX+0]. Finally, 63 # AL AND is AND AL, #63.

It also shows the use of the 0= IF ... THEN block. The 0= is testing the Zero flag, if true, it executes the block delimited by the IF and THEN. No labels here. Similarly, the BEGIN ... UNTIL syntax. It also shows simple macros like 1PUSH.

Finally it represents the nature of a bunch of assembly code arranged to fit on a single 1K byte, 64x16 screen of Forth source code.

| improve this answer | |
  • There are also Forth CPU for which the instruction set is simply a binary encoded version of Forth assembly. These are typically implemented as a subset of Forth and more complex instructions like the FIND above will be implemented as libraries – slebetman Apr 20 at 8:46

An honourable mention goes to Programma 101, arguably the first desktop computer. The "programming" was done essentially in an "assembler" corresponding to keystrokes, looking like this (taken from here):

B M↑
B ← M
A / A↑
D / A↓

This style has been generally carried on by other programming calculators, though later they started to include a general purpose CPU (with its own, hidden from the user, machine code).

| improve this answer | |
  • Oh, I even used one of those! How could I have forgotten it? – another-dave Apr 20 at 13:17

This thread would not be complete without a reference to The Story of Mel. According to the story, this was a Royal McBee RPC-4000, and its assembler was unique because

The new computer had a one-plus-one
addressing scheme,
in which each machine instruction,
in addition to the operation code
and the address of the needed operand,
had a second address that indicated where, on the revolving drum,
the next instruction was located.

In modern parlance,
every single instruction was followed by a GO TO!
| improve this answer | |
  • 3
    The assembler had it because the machine did it like that - no program counter, but each instruction specified its successor. That seems to have been common on machines where primary memory was rotating (either magnetic drum or ultrasonic storage). See Optimum Programming on Wikipedia, or the IBM 650 (page 10, instruction format) for a specific example. Eventually there were assemblers that did that for you. – another-dave Apr 19 at 20:38
  • @another-dave Sure, and that's basically true of all assemblers - they're really just a mnemonic layer on top of the hardware features. The structure of the processor's memory, whether that's rotating or RAM-based, Von Neumann or Harvard, and any registers, is always reflected in the assembler mnemonics and how they are fed input and output values. – Graham Apr 21 at 10:12
  • But my point for this topic is that the 1+1 address format does not make it syntactically strange. – another-dave Apr 21 at 12:19

I'm not 100% sure whether this answer qualifies, as the assembler it relates to is still available and updated for at least relatively modern architectures, but it does originally go baack to the 80s and supported 16-bit 8086 compatible CPUs, so perhaps it's appropriate:

Terse is an x86 assembler with a rather unique syntax, designed to resemble high level languages. An example from the web site is this code:

eax = ebx; bx + dog; cat - 14; cx & 0Fh; dx - 123?

Which is equivalent to the following traditional 8086 instruction sequence:

Mov eax,ebx
Add bx,dog
Sub cat,14
And cx,0Fh
Cmp dx,123

The language supports chaining multiple operations that use the same destination register in a single statement, and also higher level concepts like loops, if statements with blocks, and so on.

| improve this answer | |

I used an assembler that did this:

  call #function

  add  v_spc, #1

Seems pretty pedestrian until you take note of what happens. Trying to compile this

  call #function

  add  v_spc, #1

(missing function_ret) yielded an error message at the site of the call operation. function could still be compiled and jumped to, but calling it was an error. The disassembly revealed the truth.

  jmpret  L15, #L13

  add L16, #1
  jmpret nw 0, #0

The processor is stackless, and the assembler is generating the necessary stuff for function calls to work on the processor.

| improve this answer | |
  • IIRC that's similar to how the Parallax Propeller does subroutine calls. – Alex Hajnal Apr 24 at 4:48
  • @AlexHajnal: This is the Parallax Propeller processor. – Joshua Apr 24 at 16:29
  • LOL. That would explain the similarity! – Alex Hajnal Apr 24 at 18:27

SDS/Xerox Meta-Symbol was essentially a list processing language designed to generate machine code through side effects.


| improve this answer | |

Some people call the (original K&R) C programming language an assembly language for PDP-11's.

| improve this answer | |
  • 1
    They do, but they're wrong, at least on the basis of ++ and --, according to Dennis Ritchie. I'm inclined to consider him as authoritative. :-). – another-dave Apr 25 at 23:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.