Assembly Language

Figure from https://cs.lmu.edu/~ray showing the basic parts of a program in Assembly.

nasmstructure.png]

To assemble we use:

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