Low-level programming language: Difference between revisions

Content deleted Content added
hello
Tag: Reverted
m Reverted edits by 89.197.109.74 (talk) (HG) (3.4.10)
Line 24:
C14AEBF1 5BC3
 
==Assembly language==
poo
Second-generation languages provide one abstraction level on top of the machine code. In the early days of coding on computers like [[TX-0]] and [[PDP-1]], the first thing MIT hackers did was to write assemblers.<ref>{{cite book|last=Levy|first=Stephen|year=1994|title=Hackers: Heroes of the Computer Revolution|title-link=Hackers: Heroes of the Computer Revolution|publisher=Penguin Books|page=32|isbn=0-14-100051-1}}</ref>
[[Assembly language]] has little [[Semantics (computer science)|semantics]] or formal specification, being only a mapping of human-readable symbols, including symbolic addresses, to [[opcode]]s, [[memory address|addresses]], numeric constants, [[string (computer science)|strings]] and so on. Typically, one [[machine instruction (computing)|machine instruction]] is represented as one line of assembly code. Assemblers produce [[object file]]s that can [[linker (computing)|link]] with other object files or be [[loader (computing)|loaded]] on their own.
 
Most assemblers provide [[macro (computer science)|macros]] to generate common sequences of instructions.
 
Example: The same [[Fibonacci number]] calculator as above, but in x86-64 assembly language using [[AT&T syntax]]:
<syntaxhighlight lang="asm">
_fib:
movl $1, %eax
xorl %ebx, %ebx
.fib_loop:
cmpl $1, %edi
jbe .fib_done
movl %eax, %ecx
addl %ebx, %eax
movl %ecx, %ebx
subl $1, %edi
jmp .fib_loop
.fib_done:
ret
</syntaxhighlight>
 
In this code example, hardware features of the x86-64 processor (its [[Processor register|registers]]) are named and manipulated directly. The function loads its input from ''%edi'' in accordance to the [[x86 calling conventions#System V AMD64 ABI|System V ABI]] and performs its calculation by manipulating values in the '''EAX''', '''EBX''', and '''ECX''' registers until it has finished and returns. Note that in this assembly language, there is no concept of returning a value. The result having been stored in the '''EAX''' register, the '''RET''' command simply moves code processing to the code ___location stored on the stack (usually the instruction immediately after the one that called this function) and it is up to the author of the calling code to know that this function stores its result in '''EAX''' and to retrieve it from there. x86-64 assembly language imposes no standard for returning values from a function (and in fact, has no concept of a function); it is up to the calling code to examine state after the procedure returns if it needs to extract a value.
 
Compare this with the same function in [[C (programming language)|C]], a [[high-level language]]:
 
<syntaxhighlight lang="c">
unsigned int fib(unsigned int n) {
if (!n)
return 0;
else if (n <= 2)
return 1;
else {
unsigned int a, c;
for (a = c = 1; ; --n) {
c += a;
if (n <= 2) return c;
a = c - a;
}
}
}
</syntaxhighlight>
 
This code is very similar in structure to the assembly language example but there are significant differences in terms of abstraction:
 
* The input (parameter '''n''') is an abstraction that does not specify any storage ___location on the hardware. In practice, the C compiler follows one of many possible [[Calling convention | calling conventions]] to determine a storage ___location for the input.
* The assembly language version loads the input parameter from the stack into a register and in each iteration of the loop decrements the value in the register, never altering the value in the memory ___location on the stack. The C compiler could load the parameter into a register and do the same or could update the value wherever it is stored. Which one it chooses is an implementation decision completely hidden from the code author (and one with no [[Side effect (computer science)|side effects]], thanks to C language standards).
* The local variables a, b and c are abstractions that do not specify any specific storage ___location on the hardware. The C compiler decides how to actually store them for the target architecture.
* The return function specifies the value to return, but does not dictate ''how'' it is returned. The C compiler for any specific architecture implements a '''standard''' mechanism for returning the value. Compilers for the x86 architecture typically (but not always) use the EAX register to return a value, as in the assembly language example (the author of the assembly language example has ''chosen'' to copy the C convention but assembly language does not require this).
 
These abstractions make the C code compilable without modification on any architecture for which a C compiler has been written. The x86 assembly language code is specific to the x86 architecture.
 
==Low-level programming in high-level languages==