Search code examples
assemblyx86att

Why does this function work but give me a segmentation fault?


.code32
.text


.globl _start
_start:

;  .globl main
  .extern printf

  pushl %ebp
  movl %esp, %ebp
;  subl $4, %esp

  movl 4(%ebp), %eax 
;  movl 12(%ebp), %ebx
 ; movl $0, %ecx

  cmp $2, %eax
  jne argCount  

  pushl %eax
  pushl $msg2
  call printf
  add $8, %esp

  movl %ebp, %esp
  popl %ebp

;  movl $1, %eax
 ; movl $0, %ebx
 ; int $0x80
  call exit

argCount:
  pushl %ebp
  movl %esp, %ebp

  pushl $msg3
  call printf
  add $4, %esp

  movl %ebp, %esp
  popl %ebp

  ret


.data

;  .asciz "Arg = %s"
  msg2: .asciz "Arg Count = %d\n"
  msg3: .asciz "This program takes 1 argument -> sizeOfArray\n"

Why does function argCount get correctly executed if the argument count on the command line is not equal to 2 but give me a segmentation fault? The overall control flow of the program seems to be working correctly otherwise. Perhaps there is something wrong with the function prologue or epilogue?


Solution

  • The immediate problem is that the ret at the end of argCount goes to the wrong place because it doesn't have a valid return address.

    Furthermore, you should use main if you intend to work with libc, and also be careful to maintain required stack alignment as per the ABI. Using a frame pointer is optional and doesn't usually help with anything, so I have omitted it.

    Here is a possible version:

      .globl main
    main:                 # main because we use libc
      subl $12, %esp      # stack alignment
      movl 16(%esp), %eax # argc
      cmpl $2, %eax
      movl $msg3, (%esp)  # preset for msg3
      jne argCount        # if argc!=2 use that
      movl $msg2, (%esp)  # otherwise msg2
      movl %eax, 4(%esp)  # and argc
    argCount:
      call printf         # print
      call exit           # exit
    
    .data
      msg2: .asciz "Arg Count = %d\n"
      msg3: .asciz "This program takes 1 argument -> sizeOfArray\n"
    

    Be sure to compile and link using gcc so that libc is pulled in properly, and supply -m32 if you are on a 64 bit environment to produce 32 bit program (because this code only works as 32 bit).