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

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.

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.

Count even numbers in matrix

In this function I want to get even numbers in matrix. My parameters are a bidimensional pointer and the dimensions of matrix.
Anyone could help me? Where I got wrong...
subl $12, %esp # 12 bytes to local variables
movl $0, -12(%ebp) # counter = 0
movl 8(%ebp), %esi # **m
movl $0, %ebx # i = 0
it_rows:
cmpl 12(%ebp), %ebx # while(i != y)
jz end # if not equal jump
leal (%esi, %ebx, 4), %edi # m+i
movl $0, %ecx # j = 0
it_col:
cmpl 16(%ebp), %ecx # while(j != k)
jz next_row
movl (%edi, %ecx, 4), %eax # *(*(m+i)+j)
andl $0x1, %eax # LSB
cmpl $0, %eax # LSB == 0
jnz not_even
movl -12(%ebp), %eax # counter
incl %eax # counter++
movl %eax, -12(%ebp) # update local variable
not_even:
incl %ecx # j++
jmp it_col
next_row:
incl %ebx # i++
jmp it_rows
My implementation in C:
int count_even_matrix(int **m, int y, int k) {
int i, j;
int c = 0;
for(i = 0; i < y; i++) {
for(j = 0; j < k; j++) {
if(*(*(m+i)+j)%2 == 0) {
c++;
}
}
}
return c;
}
I'm just a beginner in C, but if you're passing the array name of your two dimensional array to your function, you're actually passing a pointer to the first element of the array, which in this case is a 3 element one dimensional array. So I believe that your pointer should be declared as int (*m)[3].
Change the if with
if ((m[i][j] % 2 ) == 0) {
c++;
}
i is your matrix rows index, and j the columns index. The two for already increment them.
I want to write my C implementation to assembly.
Your assembly has just one error: the leal, which has to be movl. Consider, what you call a bidimensional pointer is, as the type int ** conveys, a pointer to pointers to ints. With
leal (%esi, %ebx, 4), %edi # m+i
you only load the address of the pointer to the ints in the ebxth row, but you actually need the value of that pointer, i. e. the address of the ints, and that you get with
movl (%esi, %ebx, 4), %edi # *(m+i)

Assembly x86/C -Recursive Binomial Coefficient Segfault/printing pascals triangle

I've written some code (main in c, subprogram in assembly x86) to calculate all the binomial coefficients recursively and print out all the binomial coefficients with n=10, restricted by m<=n.
So basically I'm trying to output a pascals triangle for n=10. (without the whole format of a triangle)
My problem is that I'm getting a segfault on compile and I'm having trouble figuring out how to print the individual values generated by the recursive function.
Segmentation fault (core dumped)
Here's the main program:
#include <stdio.h>
unsigned int result,m,n,i;
unsigned int binom(int,int);
int main(){
n=10;
for (i=0; i<n+1;i++){
printf("i=%d | %d \n", i, binom(n,i) );
}
return;
}
And the recursive sub program:
.text
.globl binom
binom:
mov $0x00, %edx #for difference calculation
cmp %edi, %esi #m=n?
je equalorzero #jump to equalorzero for returning of value 1
cmp $0x00, %esi #m=0?
je equalorzero
cmp $0x01, %esi #m=1?
mov %esi,%edx
sub %edi, %edx
cmp $0x01, %edx # n-m = 1 ?
je oneoronedifference
jmp otherwise
equalorzero:
add $1, %eax #return 1
ret
oneoronedifference:
add %edi, %eax #return n
ret
otherwise:
sub $1, %edi #binom(n-1,m)
call binom
sub $1, %esi #binom(n-1,m-1)
call binom
This is what gcc is giving me
./runtimes
i=0 | 12
Segmentation fault (core dumped)
The two major issues with your assembly code are: 1) you niether add nor return the sum of the two recursive calls; 2) you don't save your locals on the stack so they are wiped out by the recursive calls -- you're using the wrong values once you return from the calls. Here's my rework of your code, some of the changes are due to my writing this under OSX:
The recursive sub program:
.text
.globl _binom
_binom:
pushq %rbp # allocate space on stack for locals
movq %rsp, %rbp
subq $24, %rsp
cmpl %edi, %esi # m == n ?
je equalorzero # jump to equalorzero for returning of value 1
cmpl $0, %esi # m == 0 ?
je equalorzero
movl %esi, %edx
subl %edi, %edx
cmpl $1, %edx # n - m == 1 ?
je oneoronedifference
subl $1, %edi # binom(n - 1, m)
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
callq _binom
movl %eax, -12(%rbp) # save result to stack
movl -4(%rbp), %edi
movl -8(%rbp), %esi
subl $1, %esi # binom(n - 1, m - 1)
callq _binom
addl -12(%rbp), %eax # add results of the two recursive calls
addq $24, %rsp # release locals space on stack
popq %rbp
retq
equalorzero:
movl $1, %eax # return 1
addq $24, %rsp # release locals space on stack
popq %rbp
retq
oneoronedifference:
movl %edi, %eax # return n
addq $24, %rsp # release locals space on stack
popq %rbp
retq
The main program:
#include <stdio.h>
extern unsigned int binom(int, int);
int main() {
int n = 10;
for (int i = 0; i <= n; i++) {
printf("i=%d | %d\n", i, binom(n, i));
}
return 0;
}
And the results:
i=0 | 1
i=1 | 10
i=2 | 45
i=3 | 120
i=4 | 210
i=5 | 252
i=6 | 210
i=7 | 120
i=8 | 45
i=9 | 10
i=10 | 1

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;

Translating Assembly to C

I'm reviewing a practice midterm at the moment. the question gives a piece of assembly code (IA32) and instructs to write the C equivalent of it. Just want to make sure I'm doing it correctly. Thanks!
Assembly program given:
.global _someOperation
_someOperation:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %ebx
movl 12(%ebp), %edx
decl %edx
xorl %esi, %esi
movl (%ebx, %esi, 4), %eax
continue:
incl %esi
cmpl (%ebx, %esi, 4), %eax
jl thelabel
movl (%ebx, %esi, 4), %eax
thelabel:
cmp %esi, %edx
jne continue
movl %ebp, %esp
popl %ebp
ret
This is the code I've written:
void someOperation(int *num, int count) //Given
{
int k; //Given
count--;
int i = 0;
k = num[i];
i++;
while(count != i)
{
if(k >= num[i]
k = num[i];
i++;
}
return (k);
}
Looks pretty close to me, although in the ASM the increment is only at the beginning of the loop, and the condition is not checked the first time through. Consider using DO...WHILE instead.
EDIT: also, your assignment is wrong. MOV instruction copies from the 2nd parameter to the first. You have it going the other way in your C code.

Resources