Author Topic: Segfaults in procedures and the stack  (Read 6023 times)

Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Segfaults in procedures and the stack
« on: January 08, 2021, 06:32:57 AM »
I've been using macros for most of this time, but I'm pretty sure using them too much could cause certain problems, and I see people using mostly procedures anyway, so i decided to give procedures a go.
Here is the procedure:
Code: [Select]
foo:
    pop dword [eax]
    mov ecx, eax
    mov edx, 1
    mov eax, 4
    mov ebx, 1
    int 80h
    add esp, 4
    ret
and here is how i envoke it:
Code: [Select]
push num
call foo
Here, I'm trying to pass num as a parameter, but when run this program, I get a segfault. It might be because of cleaning the stack. Any help would be greatly appreciated.
« Last Edit: January 08, 2021, 06:35:09 AM by MediocreVeg1 »

Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Re: Segfaults in procedures and the stack
« Reply #1 on: January 08, 2021, 08:41:32 AM »
Update: I realised I was being stupid with the [] so I changed my function to:
Code: [Select]
foo:
    mov eax, 4
    mov ebx, 1
    pop ecx
    mov edx, 1
    int 80h
    ret
This prints something (comes out as an unknown character) and then still gives a segfault. I'm not even sure why its printing an unknown character since num is 48, so it should print 0.

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 171
  • Country: br
Re: Segfaults in procedures and the stack
« Reply #2 on: January 08, 2021, 12:58:02 PM »
Update: I realised I was being stupid with the [] so I changed my function to:
Code: [Select]
foo:
    mov eax, 4
    mov ebx, 1
    pop ecx
    mov edx, 1
    int 80h
    ret
This prints something (comes out as an unknown character) and then still gives a segfault. I'm not even sure why its printing an unknown character since num is 48, so it should print 0.

For i386 syscalls ECX holds the pointer to a buffer, not the "character". If you 'push' the number to the stack you could do (assuming SS=DS):
Code: [Select]
f:
  mov eax,4
  mov ebx,1
  mov edx,ebx
  lea ecx,[esp+4]   ; ECX = address of 'num' in the stack.
  int 0x80
  ret

And call f() as:
Code: [Select]
  push num
  call f
  add esp,4  ; clear the stack.

Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Re: Segfaults in procedures and the stack
« Reply #3 on: January 08, 2021, 02:58:39 PM »
Sorry for getting this so late, i think i get it now though. Thanks for the help.
[EDIT] Wait, I'm still getting a segfault with this code. Ugh.
I know the stack kindof changes with 32 and 64 bit. Right now, I've put BITS 32 but i compiled it as elf64 and didnt put i386, maybe that's the issue, but I doubt it.
« Last Edit: January 08, 2021, 03:07:57 PM by MediocreVeg1 »

Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Re: Segfaults in procedures and the stack
« Reply #4 on: January 08, 2021, 04:36:09 PM »
[SORT OF UPDATE] About the segfault, I just realised I was being stupid with an ld typo. After that, the segfault went away
BUT
Now it prints... nothing. The program opens and just closes. Is there any reason why this could be?

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 171
  • Country: br
Re: Segfaults in procedures and the stack
« Reply #5 on: January 08, 2021, 09:29:29 PM »
Sorry... my bad..

Pushing a number on stack won't help. A single decimal digit is a char which code is between 0x30 and 0x39
You can push a char...

Code: [Select]
  push byte '3'
  call f
  add esp,4
  ...

Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Re: Segfaults in procedures and the stack
« Reply #6 on: January 10, 2021, 02:44:44 PM »
Ok, ill try this out
« Last Edit: January 10, 2021, 03:02:31 PM by MediocreVeg1 »

Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Re: Segfaults in procedures and the stack
« Reply #7 on: January 10, 2021, 03:01:06 PM »
Ah man, wait, I'm still getting nothing even with push byte '3'. And I have a few extra questions too:
1. I'm pretty sure NASM can't really differentiate between numbers and characters (like i mean that add eax, '0' is identical to add eax, 48), and i pushed 48 (0 in ascii), so how would that and '0' be different?
2. I read that you can't push bytes into the stack, only words and doublewords. So how does this new line work, exactly?

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 171
  • Country: br
Re: Segfaults in procedures and the stack
« Reply #8 on: January 10, 2021, 11:43:49 PM »
Ah man, wait, I'm still getting nothing even with push byte '3'.
Then you are doing something wrong. For x86-64, try this (change the registers, the syscall instruction to int 0x80, the EAX to corresponding syscalls  and the offset to +4, instead of +8, for i386 code):

Code: [Select]
; test.asm
;
; $ nasm -felf64 -o test.o test.asm
; $ ld -s -o test test.o
;

  bits  64
  default rel

  section .text

  global  _start
_start:
  push  byte '3'
  call  f
  add   rsp,8         ; Get rid of pushed data.
 
  mov   eax,60
  xor   edi,edi
  syscall

;---------------
  align 4
f:
  mov   eax,1         ; SYS_WRITE.
  mov   edi,eax       ; STDOUT_FILENO.
  mov   edx,eax       ; 1 char.
  lea   rsi,[rsp+8]   ; Points to data pushed on stack.
                      ; The stack:
                      ;
                      ;          +-----------------------------------------+
                      ; RSP+8 -> | 0x33 0x00 0x00 0x00 0x00 0x00 0x00 0x00 |
                      ;          +-----------------------------------------+
                      ; RSP->    |             return address              |
                      ;          +-----------------------------------------+
  syscall
  ret

Quote
And I have a few extra questions too:
1. I'm pretty sure NASM can't really differentiate between numbers and characters (like i mean that add eax, '0' is identical to add eax, 48), and i pushed 48 (0 in ascii), so how would that and '0' be different?

'0' is 0x30, and 0 is 0...

Quote
2. I read that you can't push bytes into the stack, only words and doublewords. So how does this new line work, exactly?
I'm not pushing one single byte... the 'byte' there is to use the shorter version of push. This will zero extend the 'byte' to a DWORD (i386) or QWORD (x86-64).
« Last Edit: January 11, 2021, 11:17:15 AM by fredericopissarra »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2500
  • Country: us
Re: Segfaults in procedures and the stack
« Reply #9 on: January 11, 2021, 05:25:28 AM »
Nitpick: '0' is 0x30  - 48 decimal. 0x48 would be 'H'.

In 64 bit code. push byte '0' goes on rsp... [esp + x] is not the same place. I suspect that this is a good example of why using 32 bit syscalls in 64 bit code can be a problem.

Best,
Frank


Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Re: Segfaults in procedures and the stack
« Reply #10 on: January 12, 2021, 12:54:50 PM »
Ok, the new code works. Thanks a lot (and I'm sorry if i came off as annoying here). There are some questions I still have, like how your printing syscall is different from what I've generally seen and how you seem to be using edi as opposed to ebx, but I think I might have stretched this thread out too far and my original question is answered, so I'll try to figure out the rest myself. Once again, thanks a bunch :)

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 171
  • Country: br
Re: Segfaults in procedures and the stack
« Reply #11 on: January 12, 2021, 06:13:11 PM »

Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Re: Segfaults in procedures and the stack
« Reply #12 on: January 12, 2021, 06:19:18 PM »
I also found the syscalls here https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md , but thanks for the link

Offline Dr1v3n

  • Jr. Member
  • *
  • Posts: 6
Re: Segfaults in procedures and the stack
« Reply #13 on: January 13, 2021, 02:30:12 AM »
There are many differences between 64-bit and 32-bit programs in assembly. For example the calling conventions could also be different... So if you were calling a function and you thought arguments needed to all be on the stack, they may need to be in registers and so on... You need to be aware of these differences.

Offline MediocreVeg1

  • Jr. Member
  • *
  • Posts: 26
Re: Segfaults in procedures and the stack
« Reply #14 on: January 13, 2021, 04:17:41 AM »
Ok. I also know that there are specific registers where arguments are passed now like rdi too, and rax is generally the return / error code register. The stack is proving to be a little problematic since I don't think I can push a string larger than 8 characters, so I might just use registers for params.