Update
This commit is contained in:
parent
f850c6c59b
commit
3eaceb1bb7
23 changed files with 125 additions and 65 deletions
16
assembly.md
16
assembly.md
|
@ -4,25 +4,27 @@ Assembly (also ASM) is, for any given hardware computing platform ([ISA](isa.md)
|
|||
|
||||
**Assembly is NOT a single language**, it differs for every architecture, i.e. every model of CPU has potentially different architecture, understands a different machine code and hence has a different assembly (though there are some standardized families of assembly like x86 that work on wide range of CPUs); therefore **assembly is not [portable](portability.md)** (i.e. the program won't generally work on a different type of CPU or under a different [OS](os.md))! And even the same kind of assembly language may have several different [syntax](syntax.md) formats which may differ in comment style, order of writing arguments and even instruction abbreviations (e.g. x86 can be written in [Intel](intel.md) and [AT&T](at_and_t.md) syntax). For the reason of non-portability (and also for the fact that "assembly is hard") you shouldn't write your programs directly in assembly but rather in a bit higher level language such as [C](c.md) (which can be compiled to any CPU's assembly). However you should know at least the very basics of programming in assembly as a good programmer will come in contact with it sometimes, for example during hardcore [optimization](optimization.md) (many languages offer an option to embed inline assembly in specific places), debugging, reverse engineering, when writing a C compiler for a completely new platform or even when designing one's own new platform. **You should write at least one program in assembly** -- it gives you a great insight into how a computer actually works and you'll get a better idea of how your high level programs translate to machine code (which may help you write better [optimized](optimization.md) code) and WHY your high level language looks the way it does.
|
||||
|
||||
**OK, but why doesn't anyone make a portable assembly?** Well, people do, they just usually call it a [bytecode](bytecode.md) -- take a look at that. [C](c.md) is portable and low level, so it is often called a "portable assembly".
|
||||
**OK, but why doesn't anyone make a portable assembly?** Well, people do, they just usually call it a [bytecode](bytecode.md) -- take a look at that. [C](c.md) is portable and low level, so it is often called a "portable assembly", though it still IS significantly higher in abstraction and won't usually give you the real assembly vibes.
|
||||
|
||||
The most common assembly languages you'll encounter nowadays are **[x86](x86.md)** (used by most desktop [CPUs](cpu.md)) and **[ARM](arm.md)** (used by most mobile CPUs) -- both are used by [proprietary](proprietary.md) hardware and though an assembly language itself cannot (as of yet) be [copyrighted](copyright.md), the associated architectures may be "protected" (restricted) e.g. by [patents](patent.md). **[RISC-V](risc_v.md)** on the other hand is an "[open](open.md)" alternative, though not yet so wide spread. Other assembly languages include e.g. [AVR](avr.md) (8bit CPUs used e.g. by some [Arduinos](arduino.md)) and [PowerPC](ppc.md).
|
||||
The most common assembly languages you'll encounter nowadays are **[x86](x86.md)** (used by most desktop [CPUs](cpu.md)) and **[ARM](arm.md)** (used by most mobile CPUs) -- both are used by [proprietary](proprietary.md) hardware and though an assembly language itself cannot (as of yet) be [copyrighted](copyright.md), the associated architectures may be "protected" (restricted) e.g. by [patents](patent.md) (see also [IP cores](ip_core.md)). **[RISC-V](risc_v.md)** on the other hand is an "[open](open.md)" alternative, though not yet so wide spread. Other assembly languages include e.g. [AVR](avr.md) (8bit CPUs used e.g. by some [Arduinos](arduino.md)) and [PowerPC](ppc.md).
|
||||
|
||||
To be precise, a typical assembly language is actually more than a set of nicknames for machine code instructions, it may offer helpers such as [macros](macro.md) (something aking the C preprocessor), pseudoinstructions (commands that look like instructions but actually translate to e.g. multiple instructions), [comments](comment.md), directives, named labels for jumps (as writing literal jump addresses would be extremely tedious) etc.
|
||||
To be precise, a typical assembly language is actually more than a set of nicknames for machine code instructions, it may offer helpers such as [macros](macro.md) (something akin the C preprocessor), pseudoinstructions (commands that look like instructions but actually translate to e.g. multiple instructions), [comments](comment.md), directives, named labels for jumps (as writing literal jump addresses would be extremely tedious) etc.
|
||||
|
||||
Assembly is extremely low level, so you get no handholding or much programming "safety" (apart from e.g. CPU operation modes), you have to do everything yourself -- you'll be dealing with things such as function [call conventions](call_convention.md), [interrupts](interrupt.md), [syscalls](syscall.md) and their conventions, how many CPU cycles different instructions take, memory segments, [endianness](endianness.md), raw addresses/[goto](goto.md) jumps, [call frames](call_frame.md) etc.
|
||||
Assembly is extremely low level, so you get no handholding or much programming "safety" (apart from e.g. CPU operation modes), you have to do everything yourself -- you'll be dealing with things such as function [call conventions](call_convention.md), [interrupts](interrupt.md), [syscalls](syscall.md) and their conventions, counting CPU cycles of individual instructions, looking up exact hexadecimal memory addresses, defining memory segments, dealing with [endianness](endianness.md), raw [goto](goto.md) jumps, [call frames](call_frame.md) etc.
|
||||
|
||||
Note that just replacing assembly mnemonics with binary machine code instructions is not yet enough to make an executable program! More things have to be done such as [linking](linking.md) [libraries](library.md) and converting the result to some [executable format](executable_format.md) such as [elf](elf.md) which contains things like header with metainformation about the program etc.
|
||||
|
||||
## Typical Assembly Language
|
||||
|
||||
Assembly languages are usually unstructured, i.e. there are no control structures such as `if` or `while` statements: these have to be manually implemented using labels and jump ([goto](goto.md)) instructions. There may exist macros that mimic control structures. The typical look of an assembly program is however still a single column of instructions with arguments, one per line, each representing one machine instruction.
|
||||
Assembly languages are usually unstructured, i.e. there are no control structures such as `if` or `while` statements: these have to be manually implemented using labels and jump ([goto](goto.md), branch) instructions. There may exist macros that mimic control structures. The typical look of an assembly program is however still a single column of instructions with arguments, one per line, each representing one machine instruction.
|
||||
|
||||
The working of the language reflects the actual [hardware](hardware.md) architecture -- most architectures are based on [registers](register.md) so usually there is a small number (something like 16) of registers which may be called something like R0 to R15, or A, B, C etc. Sometimes registers may even be subdivided (e.g. in x86 there is an *eax* 32bit register and half of it can be used as the *ax* 16bit register). These registers are the fastest available memory (faster than the main RAM memory) and are used to perform calculations. Some registers are general purpose and some are special: typically there will be e.g. the FLAGS register which holds various 1bit results of performed operations (e.g. [overflow](overflow.md), zero result etc.). Some instructions may only work with some registers (e.g. there may be kind of a "[pointer](pointer.md)" register used to hold addresses along with instructions that work with this register, which is meant to implement [arrays](array.md)). Values can be moved between registers and the main memory (with instructions called something like *move*, *load* or *store*).
|
||||
In assembly it is also common to blend program instructions and data, i.e. sometimes you create a label after which you just put bytes that will represent e.g. text strings or images and after that you start to write program instructions that work with these data, which will likely physically be placed this way (after the data) in the final program. This may cause quite nasty bugs if you by mistake jump to a place where data reside and try to treat them as instructions.
|
||||
|
||||
The working of the language reflects the actual [hardware](hardware.md) architecture -- most architectures are based on [registers](register.md) so usually there is a small number (something like 16) of registers which may be called something like R0 to R15, or A, B, C etc. Sometimes registers may even be subdivided (e.g. in x86 there is an *eax* 32bit register and half of it can be used as the *ax* 16bit register). These registers are the fastest available memory (faster than the main RAM memory, they are literally INSIDE the CPU, even in front of the [cache](cache.md)) and are used to perform calculations. Some registers are general purpose and some are special: typically there will be e.g. the FLAGS register which holds various 1bit results of performed operations (e.g. [overflow](overflow.md), zero result etc.). Some instructions may only work with some registers (e.g. there may be kind of a "[pointer](pointer.md)" register used to hold addresses along with instructions that work with this register, which is meant to implement [arrays](array.md)). Values can be moved between registers and the main memory (with instructions called something like *move*, *load* or *store*).
|
||||
|
||||
Writing instructions works similarly to how you call a [function](function.md) in high level language: you write its name and then its [arguments](argument.md), but in assembly things are more complicated because an instruction may for example only allow certain kinds of arguments -- it may e.g. allow a register and immediate constant (kind of a number literal/constant), but not e.g. two registers. You have to read the documentation for each instruction. While in high level language you may write general [expressions](expression.md) as arguments (like `myFunc(x + 2 * y,myFunc2())`), here you can only pass specific values.
|
||||
|
||||
There are also no complex [data types](data_type.md), assembly only works with numbers of different size, e.g. 16 bit integer, 32 bit integer etc. Strings are just sequences of numbers representing [ASCII](ascii.md) values, it is up to you whether you implement null terminated strings or Pascal style strings. [Pointers](pointer.md) are just numbers representing addresses. It is up to you whether you interpret a number as signed or unsigned (some instructions treat numbers as unsigned, some as signed).
|
||||
There are also no complex [data types](data_type.md), assembly only works with numbers of different size, e.g. 16 bit integer, 32 bit integer etc. Strings are just sequences of numbers representing [ASCII](ascii.md) values, it is up to you whether you implement null terminated strings or Pascal style strings. [Pointers](pointer.md) are just numbers representing addresses. It is up to you whether you interpret a number as signed or unsigned (some instructions treat numbers as unsigned, some as signed, some don't care because it doesn't matter).
|
||||
|
||||
Instructions are typically written as three-letter abbreviations and follow some unwritten naming conventions so that different assembly languages at least look similar. Common instructions found in most assembly languages are for example:
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue