Trouble creating an array loop in Y86 Assembly - arrays

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

Related

Disassembling IA32 32 bit AT&T assembly code of a function in C

[Edited]
Could someone explain to me how we get the values of M and N in this problem, going through each line of the corresponding assembly code?
I always get stumped at the movl array2 part.
M and N are constants defined using #define
#define M <some value>
#define N <some value>
int array1[M][N];
int array2[N][M];
int copy(int i, int j)
{
array1[i][j] = array2[j][i];
}
If the above code generates the following assembly code: How do we deduce the values of the constants M and N?
copy:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl 8(%ebp), %ecx
movl 12(%ebp), %ebx
leal (%ecx, %ecx, 8), %edx
sall $2, %edx
movl %ebx, %eax
sall $4, %eax
subl %ebx, %eax
sall $2, %eax
movl array2(%eax, %ecx, 4), %eax
movl %eax, array1(%edx, %ebx, 4)
popl %ebx
movl %ebp,%esp
popl %ebp
ret
You need to check other parts of the assembly. For example, if you define M and N as 8 both, you will find the following in the assembly
array1:
.zero 256
array2:
.zero 256
because on my machine, int is 4 bytes and 8 times 8 is 64. And 64 * 4 = 256. The sample assembly can be found here .
Alright guys, after much research I was able to find a solution. Correct me if I am wrong.
So going through the following assembly step by step: (Added line numbers for ease)
M and N are constants defined using #define
int array1[M][N];
int array2[N][M];
int copy(int i, int j)
{
array1[i][j] = array2[j][i];
}
copy:
1 pushl %ebp
2 movl %esp, %ebp
3 pushl %ebx
4 movl 8(%ebp), %ecx
5 movl 12(%ebp), %ebx
6 leal (%ecx, %ecx, 8), %edx
7 sall $2, %edx
8 movl %ebx, %eax
9 sall $4, %eax
10 subl %ebx, %eax
11 sall $2, %eax
12 movl array2(%eax, %ecx, 4), %eax
13 movl %eax, array1(%edx, %ebx, 4)
14 popl %ebx
15 movl %ebp,%esp
16 popl %ebp
ret
Push %ebp into stack
%ebp points to %esp
Push %ebx into stack
%ecx equals int i (index for array access)
%ebx equals int j (index for array access)
%edx equals 8 * %ecx + %ecx or 9i
%edx equals 36i after a left binary shift of 2
%eax equals %ebx or j
%eax equals 16j after a left binary shift of 4
%eax equals %eax - %ebx = 16j - j = 15j
%eax equals 60j after a left binary shift of 2
%eax equals array2 element with index [4%ecx + %ebx] or [4i + 60j]
Element with index [ 4%ebx + %edx ] or [ 4j + 36i ] of array1 equals %eax or [4i + 60j]
A swap of the two array elements done in 12 and 13 using %eax as
intermediary register.
%ebx popped
%esp's old value restored
%ebp popped
Now we assume array1[i][j]'s element access to be equal to 4Ni + 4j
And array2[j][i]'s element access to be equal to 4Mj + 4i.
( The 4 in each index term as int is of 4 bytes and i, j are individual offsets from starting array location )
This is true because C stores arrays in a row major form.
So equating we get, M = 15 and N = 9.

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

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

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