display | more...

The lowest level programming language. Machine languages are always processor-specific (though different "families" of processors, usually from same manufacturer, are compatible with each other).

Basically, machine language is numeric. A computer sees the code as series of bits (binary code); For human consumption, the code is often represented as numbers (traditionally as hexadecimal because that way you always have at most two numbers per byte.)

Here's a live example of machine language:

a9 2b 85 fb a9 c0 85 fc a2 00 a0 00 b1 fb 20 d2 ff c8 b1 fb 20 d2 ff c8 b1 fb 20 d2 ff e6 fb e8 ec 5c c0 d0 e5 a9 0d 20 d2 ff 60

Editing the program is very painful. The code contains several jump and branch instructions - if you insert or remove a command, you first need to move a code block and then correct all of your jumps and branches.

Typically, machine language program has opcodes and operands (in HLL talk, this means "commands" and "parameters"). For example, near the end, we see pattern "20 d2 ff". Here, 20 is the opcode, d2 ff is the operand. Looking at the reference, we know that this translates to assembler "JSR $FFD2" - "Jump to Subroutine at address $FFD2, do that until we come to RTS there). The last "60" is an opcode with no operands, which translates to "RTS" ("Return from Subroutine" - basically, exit our program).

It is important to note that different commands have several different opcodes! This is because an opcode always refers to one addressing mode of one command. (Note: I've been told that there are False Processors out there that do not follow this Divine Distinction. Never give in! Long Live 6502!) For example, 8D, 85, 95, 9D, 99, 81 and 91 all mean "STA" (Store Accumulator in Memory) - all take different types of operands and do different things to them, but in the end, the contents of accumulator get stored somewhere.

It should be noted that programming on raw memory is not as hard as you may think first! All you need to do is to think of the routines in advance, think of the program's structure, estimate how much space each routine takes, and then write the routines to those spaces. This way you minimize the code moving, always as frustrating. "Careful planning is half of the work." =)

(Some games were made with raw memory editing - Uuno Turhapuro Muuttaa Maalle, for example...)

For the rest of us, using assembler is recommended. There are some machine language monitors that allow you to enter symbolic assembly - this is cool because you don't need to remember the hex numbers, but you still need to do the memory move thingy and calculate addresses in your head. Symbolic assembler takes commands and produces machine language without need to mess around. Those things are highly recommended.

If you're interested of seeing the above hex mess in assembly form, see Comparison of programming language types. Oh, and all opcodes and commands here refer to the God's Chosen Microprosessor, 6502. =)

See also: Assembler, Assembly, The Story of Mel
