This example will give you a reading knowledge of assembly code. My favorite introduction to Intel assembly language is here: http://www.x86-64.org/documentation/assembly.html The rest of this discussion shows you an extended example of assembly code. I generated the assembly code file, factorial.s, using: gcc -c -g -Wa,-alh,-L factorial.c > factorial.s using gcc version 4.6.3 on a standard Intel 64-bit x86_64 CPU. These notes are based on the file, factorial.s, which you can generate again, or else just read my copy in this directory. In reading factorial.s, here are some hints for how to read it. First note that the Intel CPU began to be widely used when it was a 8-bit CPU. So, a "word" for Intel is 16 bits. A "long word" is 32 bits. A "quad-word" is 64 bits. (They kept a word as meaning 16 bits for backwards compatibility, even though a modern Intel CPU is a 64-bit CPU, and registers now hold a quad-word instead of just a 16-bit word. Again for backwards compatibility, there was originally an 8-bit register, "a". Later, the 16-bit CPU referred to "ea", an "Extended a register" holding 16 bits. Still later, the 32-bit CPU referred to "eax", an "Extended a eXtended again register" holding 32 bits. Finally, the 64-bit CPU referred to "rax", holding 64 bits. If you refer to "eax", you are using only the lower 32 bits, and ignoring the remaining bits of the 64-bit register, rax. Assembly commands starting with "." are assembly directives: .file "factorial.c" -- a comment that this came from factorial.c .text -- this is the beginning of the "text" (code) segment .globl factorial -- "factorial" is a global variable or global function factorial: -- We're using "factorial" here as the label for this line of code. The instruction "call factorial" will come here. .Ltext0: .LFB0: .LC0 etc. -- These are the names of labels chosen by the the compiler. An example of where they're used is: movl $.LC0, %eax -- copy the word from address .LC0 in memory, to register $eax pushq %rbp -- push the quad-word data in register %rbp onto the stack movq %rsp, %rbp -- move (copy) the quad-word from register %rsp to register %rbp jmp .L3 -- jump (goto) the address at label .L3 call factorial -- goto the function factorial, and save the return address somewhere so that the instruction "ret" (return) will do the right thing. movl -4(%rbp), %eax -- move (copy) the long word at address -4(%rbp) to the register %eax. The notation -4(%rbp) is ugly. But it means: take the address in memory referred to by register %rbp (and so %rbp is being used as a pointer here). then add "-4" to that address (and so move backwards by 4 bytes). Take that new address as the address of a long word. Copy the data from that address to register %eax. imull -4(%rbp), %eax -- "integer multiply" by a long word. Treat the data at address "-4(%rbp)" as a long word holding an integer. Multiply: %eax = %eax * [the integer at -4(%rbp)] subq $16, %rsp -- subtract a quad-word: %rsp = %rsp - 16 The notation "$16" means the decimal number "16" (not hexadecimal). %rsp is the stack pointer. Here, the code is creating a new function call frame that of size 16 bytes. So, the stack pointer is pointing 16 bytes earlier in memory. (The stack is growing from high memory towards address 0. Although not shown here, the "rip" is the "instruction pointer register", the register holding the address of the next instruction to execute. In other versions of assembly, it might be called "pc" (the "program counter"). pushq %rbp movq %rsp, %rbp subq $16, %rsp push $rbp (the base pointer) onto the stack. %rbp points to the previous call frame. Then copy %rsp into %rbp. %rsp points to the current call frame. The subtract 16 from %rsp. Now, %rsp points to the new call frame that will be used in this new function call.