Converting C program into 32-bit assembly code - c

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

Related

GAS Assembly program segmentation fault (writing to auto variable)

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.

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?

Trouble creating an array loop in Y86 Assembly

I need to create a program that sorts an array of integers into ascending order. Simple enough problem in C, and the code is given to us.
void bubble(int *data, int count)
{
int i, last;
for(last = count‐1; last>0;last‐‐)
{
for(i=0;i<last;i++)
if
(data[i+1] < data[i])
{
/* Swap adjacent elements */
int t=data[i+1];
data[i+1]=data[i];
data[i]=t;
}
}
}
but when I try to implement it into assembly, I get either
Error on line 90: Invalid line
Line 90, Byte 0x00d0: .comm *data,20,4 //data = memory location
or, if I comment that line out (I don't think I should) I get this
Error on line 39: Expecting ')'
Line 39, Byte 0x005a: mrmovl (%edx,%ebx,4),%eax //%eax = data[i]
Error on line 41: Expecting ')'
Line 41, Byte 0x0066: mrmovl 4(%edx,%ebx,4),%edi //%edi = data[i++]
Error on line 46: Expecting ')'
Line 46, Byte 0x0073: mrmovl 4(%edx,%ebx,4),%edi //%edi = data[i++]
Error on line 47: Expecting ')'
Line 47, Byte 0x0079: rmmovl %edi, (%edx,%ebx,4) //data[i] = data[i++]
Error on line 48: Expecting ')'
Line 48, Byte 0x007f: rmmovl %eax, 4(%edx,%ebx,4) //data[i++] = data[i]
The following is my code as it stands:
.pos 0
init: irmovl Stack, %esp //Set up stack pointer
irmovl Stack, %ebp //Set up base pointer
call main //call main program
halt //Terminate program
bubble: pushl %ebp //setup
rrmovl %esp, %ebp
pushl %edx //declaring *data
mrmovl 8(%ebp), %edx
pushl %ecx //declaring count
mrmovl 12(%ebp), %ecx
pushl %ebx //declaring i
pushl %esi //declaring last
pushl %edi
pushl %eax
irmovl $1, %edi //%edi = 1
rrmovl %ecx,%esi //last=count
subl %edi,%esi //last--
L1:
irmovl $0, %edi //%edi = 0
subl %edi,%esi //last -= 0
jle L9 //ends loop if last <= 0
irmovl $0, %ebx //i = 0
L2:
rrmovl %ebx, %edi //%edi = copy of i
subl %esi,%edi //%edi = i-last
jge L8 //ends loop if i >= last
mrmovl (%edx,%ebx,4),%eax //%eax = data[i]
irmovl $1, %edi //%edi = 1
mrmovl 4(%edx,%ebx,4),%edi //%edi = data[i++]
subl %eax,%edi //%edi = data[i++]-data[i]
jge L7 //cancel if statement if data[i++]>=data[i]
mrmovl 4(%edx,%ebx,4),%edi //%edi = data[i++]
rmmovl %edi, (%edx,%ebx,4) //data[i] = data[i++]
rmmovl %eax, 4(%edx,%ebx,4) //data[i++] = data[i]
L7:
irmovl $1, %edi //%edi = 1
addl %edi,%ebx //i++
jmp L2 //go to beginning of loop
L8:
irmovl $1, %edi //%edi = 1
subl %edi,%esi //last--
jmp L1
L9:
popl %ebx //finish
popl %esi
popl %edi
popl %eax
popl %ebp
ret
main: pushl %ebp //setup
rrmovl %esp, %ebp
pushl %ebx //declaring *data
mrmovl data, %ebx
pushl %esi //declaring count
mrmovl count, %esi
rmmovl %ebx, (%esp) //move data to be used by bubble
rmmovl %esi, 4(%esp) //move count to be used by bubble
call bubble
popl %ebx //finish
popl %esi
popl %ebp
ret
.comm data,20,4 //data = memory location
.align 4
count: .long 5 //count = memory location
data: .long 2 //data array assignment
.long 1
.long 3
.long 5
.long 4
.pos 0x200
Stack: .long 0
y86 does not support the full x86 effective address syntax with the index and scale, it only allows displacement(base). You have to perform the address calculation yourself.
The y86 assembler doesn't support .comm either, just define your data using .long

assembly, two functions in 1 file, getting Error: junk `(%ebp)' after expression

The assembly functions with commented c version:
/*
int f (int x)
{
return x+2;
}
void map2 (int* one, int * another, int n)
{
int i;
for (i=0; i<n; i++)
*(another+i) = f(*(one+i));
}
*/
.text
.globl f
f:
/********************************** prologue *************************************/
pushl %ebp
movl %esp, %ebp
/********************************************************************************/
movl 8(%ebp), %eax
addl $2, %eax
/************************************* end **************************************/
movl %ebp, %esp
popl %ebp
ret
/*********************************************************************************/
.text
.globl map2
map2:
/********************************** prologue *************************************/
pushl %ebp
movl %esp, %ebp
pushl %ebx
pushl %esi
pushl %edi
/********************************************************************************/
movl $0, %ebx
L1: cmpl $16(%ebp), %ebx // error
jge out
movl $12(%ebp), %esi // error
addl %ebx, %esi
movl $8(%ebp), %edi // error
addl %ebx, %edi
/********************************** calls f *************************************/
pushl %eax
pushl %ecx
pushl %edx
pushl (%edi)
call f
movl %eax, (%esi) /* *(another+i) = f(*(one+i)); */
popl %edx
popl %ecx
popl %eax
/********************************************************************************/
/************************************* end **************************************/
popl %edi
popl %esi
popl %ebx
movl %ebp, %esp
popl %ebp
ret
/********************************************************************************/
I'm getting
fmap2.s:44: Error: junk `(%ebp)' after expression
fmap2.s:47: Error: junk `(%ebp)' after expression
fmap2.s:50: Error: junk `(%ebp)' after expression
Why? There is something to do with having 2 prologues and endings in the same file?
The base-dislocation numbers of those error lines are correct.
According to gcc documentation, you need to remove dollar signs in front of the numeric constants used for displacement:
One point to bear in mind is that, when a constant is used for disp/scale, ’$’ shouldn’t be prefixed.
movl $0, %ebx
L1: cmpl 16(%ebp), %ebx
jge out
movl 12(%ebp), %esi
addl %ebx, %esi
movl 8(%ebp), %edi
addl %ebx, %edi

Resources