Tuesday, April 25, 2017

Linux assemblers: A comparison of GAS and NASM


1. Assembling:

GAS (AT&T syntax)
as -o program.o program.s
NASM (Intel syntax)
nasm -f elf -o program.o program.asm

2. Linking
ld -o program program.o
ld --dynamic-linker /lib/ld-linux.so.2 -lc -o program program.o


AT&T syntax
Intel syntax
opposite order src&dest ops
movl $4, %eax
mov eax, 4
immediate operands
pushl $4
push 4
register operands
movl $4, %eax
mov eax, 4
the size of memory operands
movb foo, %al
#b(8-bit)/w(16)/l(32)
mov al, byte ptr foo
#byte/word/dword ptr
Immediate form long jumps and calls
lcall/ljmp $section, $offset
lret $stack-adjust
call/jmp far section:offset
ret far stack-adjust
declare 32-/16-/8-bit numbers
.long/.int/.byte
dd/dw/db
declare variables
.ascii/.asciz/.string

memory location address
(var1)
[var1]
comments
/* */, // or #
;
entry point(.text)
.global _start:
global _start:
BSS stands for "block storage segment". The memory reserved in BSS section is initialized to zero during the start of the program. Objects in BSS section have only a name and a size, and no value.
allocated space in BBS section
.lcomm varname, size
varname resb(w/d) size

Implementation of selection sort on an integer array
NASM
GAS
section .data
array db 89,10,67,1,4,27,12,34, 86, 3
  ARRAY_SIZE equ $ - array
  array_fmt db "  %d", 0
  usort_str db "unsorted array:", 0
  sort_str db "sorted array:", 0
  newline db 10, 0
section .text
   extern puts
   global _start
   _start:
      push  usort_str
      call  puts
      add   esp, 4
      push  ARRAY_SIZE
      push  array
      push  array_fmt
      call  print_array10
      add   esp, 12
      push  ARRAY_SIZE
      push  array
      call  sort_routine20
; Adjust the stack pointer
      add   esp, 8
      push  sort_str
      call  puts
      add   esp, 4
      push  ARRAY_SIZE
      push  array
      push  array_fmt
      call  print_array10
      add   esp, 12
      jmp   _exit
      extern printf
   print_array10:
      push  ebp
      mov   ebp, esp
      sub   esp, 4
      mov   edx, [ebp + 8]
      mov   ebx, [ebp + 12]
      mov   ecx, [ebp + 16]
      mov   esi, 0
   push_loop:
      mov   [ebp - 4], ecx
      mov   edx, [ebp + 8]
      xor   eax, eax
      mov   al, byte [ebx + esi]
      push  eax
      push  edx
      call  printf
      add   esp, 8
      mov   ecx, [ebp - 4]
      inc   esi
      loop  push_loop
      push  newline
      call  printf
      add   esp, 4
      mov   esp, ebp
      pop   ebp
      ret
   sort_routine20:
      push  ebp
      mov   ebp, esp
; Allocate a word of space in stack
      sub   esp, 4
; Get the address of the array
      mov   ebx, [ebp + 8]
; Store array size
      mov   ecx, [ebp + 12]
      dec   ecx
; Prepare for outer loop here
      xor   esi, esi
   outer_loop:
; This stores the min index
      mov   [ebp - 4], esi
      mov   edi, esi
      inc   edi
   inner_loop:
      cmp   edi, ARRAY_SIZE
      jge   swap_vars
      xor   al, al
      mov   edx, [ebp - 4]
      mov   al, byte [ebx + edx]
      cmp   byte [ebx + edi], al
      jge   check_next
      mov   [ebp - 4], edi
   check_next:
      inc   edi
      jmp   inner_loop
   swap_vars:
      mov   edi, [ebp - 4]
      mov   dl, byte [ebx + edi]
      mov   al, byte [ebx + esi]
      mov   byte [ebx + esi], dl
      mov   byte [ebx + edi], al
      inc   esi
      loop  outer_loop
      mov   esp, ebp
      pop   ebp
      ret
   _exit:
      mov   eax, 1
      mov   ebx, 0
      int   80h
.section .data
array: .byte 89,10,67,1,4,27,12,34, 86, 3
  array_end: .equ ARRAY_SIZE, array_end - array
  array_fmt: .asciz "  %d"
  usort_str: .asciz "unsorted array:"
  sort_str: .asciz "sorted array:"
  newline: .asciz "\n"
.section .text

   .globl _start
   _start:
      pushl $usort_str
      call  puts
      addl  $4, %esp
      pushl $ARRAY_SIZE
      pushl $array
      pushl $array_fmt
      call  print_array10
      addl  $12, %esp
      pushl $ARRAY_SIZE
      pushl $array
      call  sort_routine20
# Adjust the stack pointer
      addl  $8, %esp
      pushl $sort_str
      call  puts
      addl  $4, %esp
      pushl $ARRAY_SIZE
      pushl $array
      pushl $array_fmt
      call  print_array10
      addl  $12, %esp
      jmp   _exit

   print_array10:
      pushl %ebp
      movl  %esp, %ebp
      subl  $4, %esp
      movl  8(%ebp), %edx
      movl  12(%ebp), %ebx
      movl  16(%ebp), %ecx
      movl  $0, %esi
   push_loop:
      movl  %ecx, -4(%ebp) 
      movl  8(%ebp), %edx
      xorl  %eax, %eax
      movb  (%ebx, %esi, 1), %al
      pushl %eax
      pushl %edx
      call  printf
      addl  $8, %esp
      movl  -4(%ebp), %ecx
      incl  %esi
      loop  push_loop
      pushl $newline
      call  printf
      addl  $4, %esp
      movl  %ebp, %esp
      popl  %ebp
      ret
   sort_routine20:
      pushl %ebp
      movl  %esp, %ebp
# Allocate a word of space in stack
      subl  $4, %esp
# Get the address of the array
      movl  8(%ebp), %ebx
# Store array size
      movl  12(%ebp), %ecx
      decl  %ecx
# Prepare for outer loop here
      xorl  %esi, %esi
   outer_loop:
# This stores the min index
      movl  %esi, -4(%ebp)
      movl  %esi, %edi
      incl  %edi
   inner_loop:
      cmpl  $ARRAY_SIZE, %edi
      jge   swap_vars
      xorb  %al, %al
      movl  -4(%ebp), %edx
      movb  (%ebx, %edx, 1), %al
      cmpb  %al, (%ebx, %edi, 1)
      jge   check_next
      movl  %edi, -4(%ebp)
   check_next:
      incl  %edi
      jmp   inner_loop
   swap_vars:
      movl  -4(%ebp), %edi
      movb  (%ebx, %edi, 1), %dl
      movb  (%ebx, %esi, 1), %al
      movb  %dl, (%ebx, %esi, 1)
      movb  %al, (%ebx,  %edi, 1)
      incl  %esi
      loop  outer_loop
      movl  %ebp, %esp
      popl  %ebp
      ret
   _exit:
      movl  $1, %eax
      movl  0, %ebx
      int   $0x80

A program to read a string and display a greeting to the user
NASM
GAS
section .data
prompt_str db ‘Enter your name:’
STR_SIZE equ $ - prompt_str ;$ loca counter
greet_str  db  'Hello '
GSTR_SIZE  equ  $ - greet_str
section .bss
buff  resb  32 ; Reserve 32 bytes of memory

; A macro with two parameters
; Implements the write system call
   %macro write 2
      mov   eax, 4
      mov   ebx, 1
      mov   ecx, %1
      mov   edx, %2
      int   80h
   %endmacro
; Implements the read system call
   %macro read 2
      mov   eax, 3
      mov   ebx, 0
      mov   ecx, %1
      mov   edx, %2
      int   80h
   %endmacro
section .text
   global _start
   _start:
      write prompt_str, STR_SIZE
      read  buff, 32
; Read returns the length in eax
      push  eax
; Print the hello text
      write greet_str, GSTR_SIZE
      pop   edx
; edx  = length returned by read
      write buff, edx
   _exit:
      mov   eax, 1
      mov   ebx, 0
      int   80h
.section .data
prompt_str: .ascii "Enter Your Name: "
pstr_end: .set STR_SIZE, pstr_end - prompt_str
greet_str: .ascii "Hello "
gstr_end: .set GSTR_SIZE, gstr_end - greet_str
.section .bss
.lcomm buff, 32 //Reserve 32 bytes of memory

// A macro with two parameters
//  implements the write system call
   .macro write str, str_size
      movl  $4, %eax
      movl  $1, %ebx
      movl  \str, %ecx
      movl  \str_size, %edx
      int   $0x80
   .endm
// Implements the read system call
   .macro read buff, buff_size
      movl  $3, %eax
      movl  $0, %ebx
      movl  \buff, %ecx
      movl  \buff_size, %edx
      int   $0x80
   .endm
.section .text
   .globl _start
   _start:
      write $prompt_str, $STR_SIZE
      read  $buff, $32
// Read returns the length in eax
      pushl %eax
// Print the hello text
      write $greet_str, $GSTR_SIZE
      popl  %edx
// edx = length returned by read
   write $buff, %edx
   _exit:
      movl  $1, %eax
      movl  $0, %ebx
      int   $0x80


No comments:

Post a Comment