Author Topic: [Solved] Segmentation fault in a snippet for C++  (Read 215 times)

Offline Xotes

  • Jr. Member
  • *
  • Posts: 4
[Solved] Segmentation fault in a snippet for C++
« on: April 20, 2019, 01:33:41 PM »
Hi,

I'm a student in computer science and I have to create a small program in assembly. This program must then be used in a C++ program.
Now onto the purpose : it must take a destination vector, a source vector and the length of thoses vectors (which is the same), take every number in the first vector, multiply it by two and then put it in the second vector.

My problem is this, for the core of the program, it looks like this :
    xor edi, edi ; initialising edi at 0 for the offset
table_multiplier:   
    mov esi, [edx + edi*4] ; getting the value from the source table
    shl esi, 1 ; multiplying the taken value by 2
    mov [eax + edi*4], esi ; putting the value in the destination table
    inc edi
    loopnz table_multiplier

ecx contains the length of the vector. When I run it in sasm, I don't have any problem. But when I try using it in my C++ code, I get a segmentation fault. I've been trying to wrap my head around this for a day now and I can't seem to find the problem.

Thanks in advance if anyone can help :)

« Last Edit: April 23, 2019, 01:14:27 AM by Xotes »

Offline fredericopissarra

  • Jr. Member
  • *
  • Posts: 34
Re: Segmentation fault in a snippet for C++
« Reply #1 on: April 20, 2019, 02:16:28 PM »
How you are implementing this routine for use of your C/C++ code? For what OS? What C/C++ compiler? 32 or 64 bits?

MS ABI and SysV ABI calling conventions are very different, in both cases (i386 and amd64), and non-static member functions have a hidden argument ("this" pointer)...
« Last Edit: April 20, 2019, 02:21:55 PM by fredericopissarra »

Offline dreamCoder

  • Full Member
  • **
  • Posts: 106
Re: Segmentation fault in a snippet for C++
« Reply #2 on: April 21, 2019, 11:32:37 AM »
LOOP instruction uses ECX implicitly.

Offline fredericopissarra

  • Jr. Member
  • *
  • Posts: 34
Re: Segmentation fault in a snippet for C++
« Reply #3 on: April 21, 2019, 02:20:38 PM »
LOOP instruction uses ECX implicitly.
Yep... but it is SLOW! That's why C compilers don't use it.

Offline dreamCoder

  • Full Member
  • **
  • Posts: 106
Re: Segmentation fault in a snippet for C++
« Reply #4 on: April 21, 2019, 05:00:58 PM »
LOOP instruction uses ECX implicitly.
Yep... but it is SLOW! That's why C compilers don't use it.
Maybe. Can't tell much from the snippet alone. Segmentation fault is basically memory-related issues. From the snippet, I can see two Scaled Base+Index addressing being used. Its either one of them pointing to "bad" memory or the loop is out of bound which in turn causing the addressing pointing to unauthorized memory area. I can't comment on the C++ part because I don't know his source and how he compiled them or which compiler he's using.

 

Offline fredericopissarra

  • Jr. Member
  • *
  • Posts: 34
Re: Segmentation fault in a snippet for C++
« Reply #5 on: April 21, 2019, 05:47:59 PM »
Can't tell much from the snippet alone. Segmentation fault is basically memory-related issues. From the snippet, I can see two Scaled Base+Index addressing being used. Its either one of them pointing to "bad" memory or the loop is out of bound which in turn causing the addressing pointing to unauthorized memory area. I can't comment on the C++ part because I don't know his source and how he compiled them or which compiler he's using.

I agree we cannot tell much about the snippet, since Xotes isn't using any standard calling convention, neighter MS ABI or Sys V ABI...

Offline fredericopissarra

  • Jr. Member
  • *
  • Posts: 34
Re: Segmentation fault in a snippet for C++
« Reply #6 on: April 21, 2019, 06:10:08 PM »
Since we are talking about x86 assembly here, LOOP is slower then:
Code: [Select]
  sub ecx,1
  jnz label
since the 386 processor.

And INC/DEC is slower than ADD/SUB as well (because they don't change the carry flag). So, this:

Code: [Select]
; SysV ABI x86-64 calling convetion...
; prototype: void f( int *destptr, int *srcptr, unsigned int count );
; Entry: RDI = destptr, RSI = srcptr, EDX = count
: Assume D Flag=0.
f:
  jmp  .while
.loop:
  lodsd
  add  eax,eax
  stosd
.while:
  sub  edx,1
  jnc  .loop   ; helps the static branch predictor!
  ret

Is faster than using loop and inc/dec.
« Last Edit: April 23, 2019, 01:23:49 AM by fredericopissarra »

Offline dreamCoder

  • Full Member
  • **
  • Posts: 106
Re: Segmentation fault in a snippet for C++
« Reply #7 on: April 21, 2019, 08:21:34 PM »
Ok thanks for the tips.

I was actually commenting on the possibility that the OP was dual-using ECX. One as the default loop count (in LOOPNZ) and the other one was for maintaining "length of vector" value? Wasn't very clear to me until I read it the second time.

Offline Xotes

  • Jr. Member
  • *
  • Posts: 4
Re: Segmentation fault in a snippet for C++
« Reply #8 on: April 23, 2019, 12:34:53 AM »
Sorry, I've had a busy week-end -_-

I have to implement it via an object file using "nasm -f elf32 -g" and use it as an extern function in c++.
32 bit, using gcc on ubuntu (18.10 to be precise).

I've tried fidgeting with ecx but it does not seem to have an effect.

EDIT : I had changed something else, rendering my code completely useless -_- Assembly is kinda driving me crazy
EDIT' : I'm just dumb -_- I put my parameters in the wrong order comparing to the function, so it would have had a hard time working. Now it works, just fine
« Last Edit: April 23, 2019, 01:11:36 AM by Xotes »

Offline Xotes

  • Jr. Member
  • *
  • Posts: 4
Re: [Solved] Segmentation fault in a snippet for C++
« Reply #9 on: April 23, 2019, 01:15:38 AM »
So thank you for your quick reply, even though I was slow to see it :)

Offline fredericopissarra

  • Jr. Member
  • *
  • Posts: 34
Re: Segmentation fault in a snippet for C++
« Reply #10 on: April 23, 2019, 01:20:39 AM »
Sorry, I've had a busy week-end -_-

I have to implement it via an object file using "nasm -f elf32 -g" and use it as an extern function in c++.
32 bit, using gcc on ubuntu (18.10 to be precise).

Then you must use SysV ABI calling convention for i386 processors. First, the function arguments must be passed through the stack. Second, registers as EBX, EDI, ESI and EBP must be preverved between calls. You can change, freely, EAX, ECX and EDX. So, if you will use ESI and EDI as base registers (for LODSD/STOSD instructions), they must be saved. Here's a simple solution:

Code: [Select]
  bits  32

  section .text

; f function stack frame.
struc fstk
.oldesi:  resd  1   ; We won't use this, but
.oldedi:  resd  1   ; ESP will be changed after saving
                    ; EDI and ESI in the stack.

.retaddr: resd  1   ; CALL f will put this on stack.

.destptr: resd  1   ; cdecl call will push arguments
.srcptr:  resd  1   ; from last to first.
.count:   resd  1
endstruc

; void f( int *destptr, int *srcptr, unsigned int count );
  global  f
f:
  ; Save EDI and ESI (SysV ABI i386 calling convention).
  push  edi
  push  esi

  ; Get arguments from stack.
  mov   edi,[esp+fstk.destptr]
  mov   esi,[esp+fstk.srcptr]
  mov   ecx,[esp+fstk.count]

  jmp   .test_cond

.loop:
  lodsb           ; Load EAX from DS:ESI
  add   eax,eax   ; EAX = EAX * 2
  stosb           ; Store EAX to ES:EDI

.test_cond:
  sub   ecx,1
  jnc   .loop     ; Stay on loop if ECX >= 0

  ; Restore EDI and ESI.
  pop   esi
  pop   edi
  ret

Quote from: Xotes
I might have found the problem -_- I read somewhere in the seldom documentation we where given that the first argument was at +8... Now, when I put +4 I at least get to the end of my code. But another problem arose, which I'm trying to figure out now.
To avoid the problem to calculate the offsets on the stack, use the structural stack frame tip I showed you above...

Offline Xotes

  • Jr. Member
  • *
  • Posts: 4
Re: [Solved] Segmentation fault in a snippet for C++
« Reply #11 on: April 23, 2019, 04:48:16 PM »
I kinda understand where you are going :O But unfortunately I think I might get spotted if I use these kind of lines, we've never even seen it in class :) Right now it works and I must say I'm not really asking for more :)