Assembly Language
Figure from https://cs.lmu.edu/~ray showing the basic parts of a program in Assembly.
- The sections correspond (sort of) to the sections we have seen in the executables, e.g. .textis for code,.datais for constant data.
- Labels are used for identifying instructions in the code (such as the start of the code or places we might want to jump to). Labels are also used for labeling constant strings.
 ]
]
To assemble we use:
- nasm -f elf32 fileName.asmto generate a 32-bit object file
- nasm -f elf64 fileName.asmto generate a 64-bit object file
Simple examples
x86
; fileName: hw32.asm
; Minimal example invoking a system function (64 bits)
section .data                        
  helloStr: db 'Hello, world!',0 
section .text
  global main                    
main:          
  mov eax, 4             ; eax = 4, means "call the write system call"
  mov ebx, 1             ; ebx = 1 means "use the stdout"
  mov ecx, helloStr      ; ecx must contain the address of the string to be printed
  mov edx, 14            ; edx must contain the string length
  int 0x80
  mov eax, 1             ; eax = 1 means "call exit fuction"
  mov ebx, 0             ; ebx = 0 means "passing a 0 as argument"
  int 0x80
Assuming that you name the file hw32.asm, you can assemble using:
nasm -f elf32 hw32.asm
which generates hw32.o
Then link into an executable using:
ld  -dynamic-linker -m elf_i386 /lib/ld-linux.so.2 -e main hw32.o -o hw32
AMD-64
; fileName: hw64.asm
; Minimal example invoking a system function (64 bits)
section .data
  helloStr: db 'Hello, world!',0 
section .text
  global main                    
main:
    mov rax, 1          ; rax = 1 for the write syscall
    mov rdi, 1          ; rdi = 1, filedescriptor stdout
    mov rsi, helloStr   ; rsi = address of the string
    mov rdx, 12         ; rdx = length of the string
    syscall             ; make the system call
    mov rax, 60         ; use the _exit syscall
    mov rdi,0           ; error code 0
    syscall             ; make syscall
Assuming that you name the file h64.asm, you can assemble using:
nasm -f elf64 hw64.asm
ld -s  -dynamic-linker /lib64/ld-linux-x86-64.so.2  -e main hw64.o -o hw64  
Example using an external (non system call) function
; fileName: hwExt32.asm
; Minimal example invoking a library function (32 bits)
extern puts                      
section .data
  helloStr: db 'Hello, world!',0 
section .text
  global main                    
main:
  push helloStr
  call puts
nasm -f elf32 hwExt32.asm
ld -lc  -dynamic-linker -m elf_i386 /lib/ld-linux.so.2 -e main hwExt32.o -o hwExt32
; fileName: hwExt64.asm
; Minimal example invoking a library function (64 bits)
extern puts                      
section .data
  helloStr: db 'Hello, world!',0 
section .text
  global main                    
main:
  mov rdi, helloStr
  call puts
nasm -f elf64 hwExt64.asm
ld -lc  -dynamic-linker /lib64/ld-linux-x86-64.so.2  -e main hwExt64.o -o hwExt64
Display the content of the address pointed to by the ESP
x/wx $esp
which is the same as:
x/wx  (char *) $esp
Display the content of the address pointed to by the ESP
x/s *( (char **) $esp)
Get the content pointed to by the $esp + 0x8
x/s  *( (char **) ($esp + 0x8) )
Command line arguments in x86 stack
a.outis a executable generated from a c Source fIle.
Here is gdb analyzing the call ./a.out uno dos tres and breakpointed just after entering main. Notice that the content of argv is at ESP + 12.
[-------------------------------------code-------------------------------------]
   0x80483d6 <frame_dummy+38>:  jmp    0x8048350 <register_tm_clones>
   0x80483db <main>:    push   ebp
   0x80483dc <main+1>:  mov    ebp,esp
=> 0x80483de <main+3>:  mov    eax,0x0
   0x80483e3 <main+8>:  pop    ebp
   0x80483e4 <main+9>:  ret    
   0x80483e5:   xchg   ax,ax
   0x80483e7:   xchg   ax,ax
[------------------------------------stack-------------------------------------]
0000| 0xffffc9b8 --> 0x0 
0004| 0xffffc9bc --> 0xf7e06637 (<__libc_start_main+247>:   add    esp,0x10)
0008| 0xffffc9c0 --> 0x4 
0012| 0xffffc9c4 --> 0xffffca54 --> 0xffffccd6 ("/tmp/a.out")
0016| 0xffffc9c8 --> 0xffffca68 --> 0xffffccee ("XDG_SEAT=seat0")
Command line arguments in AMD-64 stack
a.out is a AMD-64 binary generated from a C source file.
Here is gdb analyzing the call ./a.out uno dos tres and breakpointed just after entering main. Notice that the content of argv is at ESP + 24.
[-------------------------------------code-------------------------------------]
   0x4004d1 <frame_dummy+33>:   jmp    0x400450 <register_tm_clones>
   0x4004d6 <main>: push   rbp
   0x4004d7 <main+1>:   mov    rbp,rsp
=> 0x4004da <main+4>:   mov    DWORD PTR [rbp-0x4],edi
   0x4004dd <main+7>:   mov    QWORD PTR [rbp-0x10],rsi
   0x4004e1 <main+11>:  mov    eax,0x0
   0x4004e6 <main+16>:  pop    rbp
   0x4004e7 <main+17>:  ret
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd720 --> 0x4004f0 (<__libc_csu_init>:   push   r15)
0008| 0x7fffffffd728 --> 0x7ffff7a2d830 (<__libc_start_main+240>:   mov    edi,eax)
0016| 0x7fffffffd730 --> 0x4 
0024| 0x7fffffffd738 --> 0x7fffffffd808 --> 0x7fffffffdcd6 ("/tmp/a.out")
0032| 0x7fffffffd740 --> 0x4f7ffcca0 
0040| 0x7fffffffd748 --> 0x4004d6 (<main>:  push   rbp)
0048| 0x7fffffffd750 --> 0x0 
0056| 0x7fffffffd758 --> 0xed614e9c5c7408b8 
[------------------------------------------------------------------------------]
[-------------------------------------code-------------------------------------]
   0x40027b <exit@plt+11>:  jmp    0x400250
   0x400280 <main>: push   rbp
   0x400281 <main+1>:   mov    rbp,rsp
=> 0x400284 <main+4>:   mov    rdi,QWORD PTR [rsp+0x10]
   0x400289 <main+9>:   mov    rdi,QWORD PTR [edi+0x8]
   0x40028e <main+14>:  call   0x400260 <puts@plt>
   0x400293 <main+19>:  mov    edi,0x0
   0x400298 <main+24>:  call   0x400270 <exit@plt>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd808 --> 0x0 
0008| 0x7fffffffd810 --> 0x4 
0016| 0x7fffffffd818 --> 0x7fffffffdce2 --> 0x7500652f706d742f ('/tmp/e')
0024| 0x7fffffffd820 --> 0x7fffffffdce9 --> 0x736f64006f6e75 ('uno')
0032| 0x7fffffffd828 --> 0x7fffffffdced --> 0x7365727400736f64 ('dos')
0040| 0x7fffffffd830 --> 0x7fffffffdcf1 --> 0x4744580073657274 ('tres')
0048| 0x7fffffffd838 --> 0x0 
0056| 0x7fffffffd840 --> 0x7fffffffdcf6 ("XDG_SEAT=seat0")
[------------------------------------------------------------------------------]
extern puts
global main
section .data
  callDenied: db 'call denied!',0x0a,0
  tooFew: db 'call small !',0x0a,0
section .text
main:
  push ebp
  mov ebp, esp
  ; write your code here -------------------------------
check_argc:
  mov eax, [ebp + 4]
  cmp eax, 1
  jg check_argv1 ; we're ok
  push tooFew
  call puts
  jmp done
  ; ----------------------------------------------------
check_argv1:
  mov eax, [ebp+12]
  movzx   eax, byte [eax] 
  cmp al, 0x2e
  jne do_execve
  push callDenied
do_execve:
  mov eax, 11         ; 11 is the system call number
  mov ebx, [ebp+12]   ; ebp+12 is the address of argv[1]
  lea ecx, [esp+08]   ; esp + 0x8 is the address of the argv
  mov edx, 0
  int 0x80            ; int 0x80 is the invocation to the system call
done:
  leave
  ret
nasm -f elf32 execve.asm; ld  -m elf_i386 -lc  -dynamic-linker /lib/ld-linux.so.2 -e main execve.o -o execve