GAS Assembly program segmentation fault (writing to auto variable) - c

I intend to do this in C:
#include<stdio.h>
int main() {
int arr[5];
arr[0] = 5;
arr[1] = 0;
arr[2] = 1;
arr[3] = 3;
arr[4] = 4;
int max = 0;
for(int i = 0;i < 5;i++)
if(max < arr[i])
max = arr[i];
printf("%d\n", max);
return 0;
}
This is my code link: array_max.s. This is my assembly code in AT&T format :
.data
.text
.globl _start
_start:
movl $5, -20(%ebp)
movl $0, -16(%ebp)
movl $1, -12(%ebp)
movl $3, -8(%ebp)
movl $4, -4(%ebp)
movl $0, %ecx
movl $5, %eax
loop:
cmp $0, %eax
je terminate
cmp %ecx, -20(%ebp,%eax,4)
jg assign
jmp loop
terminate:
movl $4, %eax
movl $1, %ebx
movl $1, %edx
int $0x80
movl $1, %eax
int $0x80
ret
assign:
movl -20(%ebp,%eax,4), %ecx
ret
I am having a segmentation fault on the very first instruction movl $5, -20(%ebp). I am new to this, please help.

I am having a segmentation fault on the very first instruction movl $5, -20(%ebp).
You are not allocating any space on the stack for arr (i.e.: int arr[5]):
pushl %ebp
movl %esp, %ebp
subl $20,%esp //<--- memory allocation
In order to deallocate the memory allocated on the stack by restoring the previous stack frame, use the leave instruction just before ret.

Related

Looping on stack, gas assembly code(AT&T format) [duplicate]

This question already has answers here:
GAS Assembly program segmentation fault (writing to auto variable)
(1 answer)
How to exit a loop in assembly
(2 answers)
Closed 5 years ago.
This was the problem statement to be coded using GAS assembler.
Write an ALP program to find the largest number from a given array of numbers(stored contiguously in memory) and display the number.
I wrote this code:
.data
.text
.globl _start
_start:
movl $5, -20(%ebp)
movl $0, -16(%ebp)
movl $1, -12(%ebp)
movl $3, -8(%ebp)
movl $4, -4(%ebp)
movl $0, %ecx # max value
movl $5, %eax # iterator
loop:
subl -1, %eax
cmp $0, %eax
# loop code here
terminate:
movl $4, %eax
movl $1, %ebx
movl $1, %edx
int $0x80
movl $1, %eax
int $0x80
ret
What I wanted to write in equivalent in C is:
#include<stdio.h>
int main() {
int arr[5];
arr[0] = 5;
arr[1] = 0;
arr[2] = 1;
arr[3] = 3;
arr[4] = 4;
int max = 0;
for(int i = 0;i < 5;i++)
if(max < arr[i])
max = arr[i];
printf("%d\n", max);
return 0;
}
How can I implement a loop in GAS assembler? I am new to this and know very less about this. Please help.

Segmentation fault when pushing to stack in assembly

I am writing a problem to calculate smallest common multiple in assembly. GDB shows sigsegv exception at the very first line pushl %ebp. Can you tell me how to fix this?
test.c
#include <stdio.h>
extern int nww(int a, int b); // Funkcja z asm
int main()
{
int a = 10, b = 3;
int nw= nww(a,b);
printf("NWW %d i %d = %d ",a,b,nw);
return 0;
}
nww.s
.text
.global nww
.type nww, #function
nww:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
movl 12(%ebp), %ebx
nwd:
movl $0, %edx # miejsce na reszte
divl %ebx # podziel a przez b, reszta w d
movl %ebx, %eax
movl %edx, %ebx # przygotowanie nastepnego dzielenia
cmp $0, %edx
jnz nww
movl %eax, %edx # NWD do dx
movl 8(%ebp), %eax # nowe A i B
movl 12(%ebp), %ebx
imull %ebx, %eax
divl %edx
exit:
movl %ebp, %esp
popl %ebp
ret

Stack smashing detected - from C to assembly

I'm trying to translate from C to assembly two functions, one that sort an array of index and one that find the minimum number starting from an index. When I run the program it works , the new array is sorted but at the end it gives me this error
1 2 3 3 4 6 7
*** stack smashing detected ***: ./invidia terminated
Annullato (core dump creato)
this is my .c file
#include <stdio.h>
#include <stdlib.h>
int* sort(int* v, int dim);
int min(int v[], int dim, int t);
int main(){
int v[] = {1,3,2,4,6,7,3};
int dim = 7,i;
int *c = sort(v,dim);
for (i = 0; i<dim; i++)
printf("%d ", c[i]);
return 0;
}
/*int* sort(int* v, int dim){
int i,j=0,t;
int mino,temp;
for (t = 0; t<dim; t++){
for(i=t;i<dim;i++){
mino = min (v,dim,t); <- min number from index t
if (v[i]==mino){
temp = v[j];
v[j] = v[i];
v[i] = temp;
j++;
break;
}
}
}
return v;
}
int min(int v[], int dim, int t){
int i, min = 1000;
for (i=t; i<dim;i++)
if (v[i]<min)
min = v[i];
return min;
}
*/
and my .s file
.globl sort
sort: #v->ebx dim-> esi i->edi, j->ecx t->edx, mino->eax, temp ->ebp
pushl %ebx
pushl %esi
pushl %edi
pushl %ebp
subl $32, %esp
movl 52(%esp), %ebx
movl 56(%esp), %esi
movl $0, %edi
movl $0, %ecx
movl $0, %eax
movl $0, %edx
movl $0, %ebp
FOR1:
cmpl %esi, %edx
jge EXIT
movl %edx, %edi
FOR2:
cmpl %esi, %edi
jge EXIT2
movl %ebx, (%esp)
movl %esi, 4(%esp)
movl %edx, 8(%esp)
movl %ebx, 12(%esp)
movl %eax, 16(%esp)
movl %ecx, 20(%esp)
movl %edx, 24(%esp)
call min
movl 12(%esp), %ebx
movl 20(%esp), %ecx
movl 24(%esp), %edx
cmpl (%ebx, %edi, 4), %eax
jne PSEUDOEND
movl (%ebx, %ecx, 4), %ebp
movl %esi, 12(%esp)
movl (%ebx, %edi, 4), %esi
movl %esi, (%ebx, %ecx, 4)
movl %ebp, (%ebx, %edi, 4)
movl 12(%esp), %esi
incl %ecx
incl %edx
jmp FOR1
PSEUDOEND:
incl %edi
jmp FOR2
EXIT:
movl %ebx, %eax
popl %ebp
popl %edi
popl %esi
popl %ebx
addl $32, %esp
ret
EXIT2:
incl %edx
jmp FOR1
.globl min
min:
movl 4(%esp), %ecx
movl 8(%esp), %edx
movl 12(%esp), %ebx
movl $1000, %eax
FOR:
cmpl %edx, %ebx
jge END
cmpl %eax, (%ecx, %ebx, 4)
cmovl (%ecx, %ebx, 4), %eax
incl %ebx
jmp FOR
END:
ret
to compile I use
gcc -m32 filename.c filename.s -o filename
I don't think that the problem is in the assembly translation because it prints correctly the new array. What could be the problem?

Converting C program into 32-bit assembly code

I am stuck with converting C code into assembly. Here is the code that I need to convert:
#include <stdio.h>
define N 50 int x[N], y[N], z[2 * N];
void convolve(int[], int[], int[], int);
int main(void)
{
int i, n;
printf("Enter vector size (<=%d): ", N);
scanf("%d", &n);
printf("Enter first vector (%d elements):\n", n);
for (i = 0; i < n; i++)
**scanf("%d", &x[i]);
**printf("Enter second vector (%d elements):\n", n);
for (i = 0; i < n; i++)
scanf("%d", &y[i]);
convolve(x, y, z, n);
printf("Convolution:\n");
for (i = 0; i < ((n + n) - 1); i++)
printf("%d ", z[i]);
printf("\n");
return 0;
}
void convolve(int x[], int y[], int z[], int n)
{
int i, j;
for (i = 0; i < ((n + n) - 1); i++)
z[i] = 0;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
z[i + j] += x[i] * y[j];
return;
}
I am stuck at this line:
scanf("%d", &x[i]);
How do I insert into array?
Here is what I have so far:
.data
.align 4
state: .long 0
.bss
N = 50
int x[N], y[N], z[2*N]
.data
.equ N, 50
.comm i,4,4 #int b
.comm n,4,4 #int n
.comm j,4,4 #int j
.comm x,N*4,4 #int x[N] where N is 50
.comm y,N*4,4 #int x[N] where N is 50
.comm z,N*8,4 #int x[N] where N is 100
.section .rodata #to format strings
fmt0: .string "Enter vector size (<=%d): "
fmt1: .string "%d"
fmt2: .string "Enter first element (%d elements):\n"
fmt3: .string "Enter second element (%d elements):\n"
fmt4: .string "Convolution:\n"
fmt5: .string "\n"
fmt6: .string .%d .
.text
.globl main
main:
pushl %ebp #prolog
movl %esp, %ebp
pushl %esi #save callee-save registers %esi, %edi, and %ebx onto stack
pushl %edi # where %esi at -4(%ebp),%edi at -8(%ebp), and %ebx at -12(%ebp)
pushl %ebx
pushl %eax #for array where %eax at -16(%ebp)------------------------------
/* Allocate space for i and n on the stack */
subl $8, %esp
/* i is at address -20(%ebp) */
/* n is at address -24(%ebp) */
pushl $fmt0 #push fmt0
call printf #printf("Enter vector size (<=%d): ")
addl $4, %esp #deallocate parm to printf
leal -24(%ebp), %ebx #%ebx = address of n
pushl %ebx #push address of n
pushl $fmt1 #push fmt1 "%d"
call scanf #scanf ("%d", &n)
addl $8, %esp #dealoccate parms for scanf
pushl $fmt2 #push fmt2
call printf #printf("Enter first element (%d elements):\n")
addl $4, %esp #deallocate parm to printf
movl $0, -20(%ebp) #i=0
movl -20(%ebp), %edi #%edi=i
movl -24(%ebp), %esi #esi=n
cmpl %esi, %edi #compare i:n
jg for_done #jump to for_done if i>n
for_loop:
pushl %edi #push i
pushl %esi #push n
pushl %eax #push array
pushl $fmt1 #push fmt1 ("%d")
call scanf #scanf("%d", n)
addl $8, %esp #dealocate parms to scanf
movl (address of x,%edi,4), %eax------------------------------------------------------
incl %edi #%edi++ (i++)
movl %edi,-20(%ebp) #i=%edi
compl %esi, %edi #compare i:n
jle for_loop #jump to for_loop if i<n
for_done:
addl $8, %esp #deallocate local vars from stack
popl %ebx #restore %ebx
popl %edi #restore %edi
popl %esi #restore %esi
/*next loop for second vector*/
pushl %esi #save callee-save registers %esi, %edi, and %ebx onto stack
pushl %edi # where %esi at -4(%ebp),%edi at -8(%ebp), and %ebx at -12(%ebp)
pushl %ebx
pushl $fmt3 #push fmt3
call printf #printf("Enter second element (%d elements):\n")
addl $4, %esp #deallocate parm to printf
movl $0, -20(%ebp) #i=0
movl -20(%ebp), %edi #%edi=i
movl -24(%ebp), %esi #esi=n
cmpl %esi, %edi #compare i:n
jg for_done #jump to for_done if i>n
for_loop:
pushl %edi #push i
pushl %esi #push n
pushl %eax #push array
pushl $fmt1 #push fmt1 ("%d")
call scanf #scanf("%d", n)
addl $8, %esp #dealocate parms to scanf
movl (address of y,%edi,4), %eax------------------------------------------------------
incl %edi #%edi++ (i++)
movl %edi,-20(%ebp) #i=%edi
compl %esi, %edi #compare i:n
jle for_loop #jump to for_loop if i<n
for_done:
addl $8, %esp #deallocate local vars from stack
popl %ebx #restore %ebx
popl %edi #restore %edi
popl %esi #restore %esi
leave #epilog
ret
convolve:
pushl %ebp #prolog
movl %esp, %ebp
pushl %esi #save callee-save registers %esi, %edi, and %ebx onto stack
pushl %edi # where %esi at -4(%ebp),%edi at -8(%ebp), and %ebx at -12(%ebp)
pushl %ebx
/* Allocate space for x, y, z, n, i, and j on the stack */
subl $24, %esp
/* x is at address 4(%ebp) */
/* y is at address 8(%ebp) */
/* z is at address 12(%ebp) */
/* n is at address 16(%ebp) */
/* i is at address -16(%ebp) */
/* n is at address -20(%ebp) */
movl $0, -16(%ebp) #i=0
movl -16(%ebp), %edi #%edi=i
movl -20(%ebp), %esi #esi=n
addl %esi, %esi #2 times n
subl $1, %esi #2n - 1
cmpl %esi, %edi #compare i:n
jg for_done #jump to for_done if i>n
I can't help but notice you've got two different for_loop and for_done defined; you might want to differentiate them somehow.
as per some of the other suggestions, maybe something like this, for example, could work:
for_loop1:
pushl %edi #push i
pushl %esi #push n
leal x(,%edi,4), %eax
pushl %eax #push array
...
for_loop2:
pushl %edi #push i
pushl %esi #push n
leal y(,%edi,4), %eax
pushl %eax #push array

Why "movl $1, %edx" instead of "movl $0, %edx" in a do while

Recent times I am having a look at assembly IA32, I did a simple toy example:
#include <stdio.h>
int array[10];
int i = 0;
int sum = 0;
int main(void)
{
for (i = 0; i < 10; i++)
{
array[i] = i;
sum += array[i];
}
printf("SUM = %d\n",sum);
return 0;
}
Yes, I know it is not very recommended to use global variables. I compiled the above code without optimizations and using the flag -s, I got this assembly :
main:
...
movl $0, %eax
subl %eax, %esp
movl $0, i
.L2:
cmpl $9, i
jle .L5
jmp .L3
.L5:
movl i, %edx
movl i, %eax
movl %eax, array(,%edx,4)
movl i, %eax
movl array(,%eax,4), %eax
addl %eax, sum
incl i
jmp .L2
Nothing too fancy and easy to understand, it is a normal while loop. Then I compiled the same code with -O2 and got the following assembly :
main:
...
xorl %eax, %eax
movl $0, i
movl $1, %edx
.p2align 2,,3
.L6:
movl sum, %ecx
addl %eax, %ecx
movl %eax, array-4(,%edx,4)
movl %edx, %eax
incl %edx
cmpl $9, %eax
movl %ecx, sum
movl %eax, i
jle .L6
subl $8, %esp
pushl %ecx
pushl $.LC0
call printf
xorl %eax, %eax
leave
ret
In this case it transformed in a do while type of loop. From the above assembly what I am not understanding is why "movl $1, %edx" and then "movl %eax, array-4(,%edx,4)".
The %edx starts with 1 instead of 0 and then when accessing the array it does -4 from the initial position (4 bytes = integer) . Why not simply ?
movl $0, %edx
...
array (,%edx,4)
instead of starting with 1 if you need to do -4 all the time.
I am using "GCC: (GNU) 3.2.3 20030502 (Red Hat Linux 3.2.3-24)", for educational reasons to generate easily understandable assembly.
I think I finally get the point, I test with:
...
int main(void)
{
for (i = 0; i < 10; i+=2)
{
...
}
}
and got:
movl $2, %edx
and with for (i = 0; i < 10; i +=3) and got :
movl $3, %edx
and finally with (i = 1; i < 10; i +=3) and got:
movl $4, %edx
Therefore, the compiler is initializing %edx = i (initial value of i) + incrementStep;

Resources