I want to know the switch value that i think that is contained in %eax in the last instruction.
When the code reaches the point where it has to add 2 times the value of 20ebp to the value of 8ebp being if I am not mistaken 8ebp a pointer to short I don't agree with the add in line 14.
1. proc1:
2. pushl %ebp
3. movl %esp, %ebp
4. subl $24, %esp
5. movl 16(%ebp), %edx
6. movl 20(%ebp), %eax
7. movb %dl, -20(%ebp)
8. movb %al, -24(%ebp)
9. movl $0, -8(%ebp)
10. movl $1, -4(%ebp)
11. movzbl -24(%ebp), %eax
12. leal (%eax,%eax), %edx
13. movl 8(%ebp), %eax
14. addl %edx, %eax
15. movswl (%eax), %eax
16. addl $7, %eax
17. cmpl $8, %eax
18. ja .L2
19. movl .L4(,%eax,4), %eax
20. jmp *%eax
21.
22. .L4:
23. .long .L7
24. .long .L2
25. .long .L6
26. .long .L2
27. .long .L12
28. .long .L12
29. .long .L3
30. .long .L2
31. .long .L3
32. .text
jut to make things clear I have to complete this C code
1. struct sta{
2. char c;
3. int L;
4. int M[3][5];
5. short V[5];
6. };
7. struct sta *V[6];
8. int K=4;
9. int proc1(short *vec, int mat[3][5],
unsigned char j, unsigned char i)
10. {
11. int x,y;
12. x=0;
13. y=1;
14. switch (______)
15. {
16. case ___:
17. if (______________________){
18. _________________;
19. }
20. break;
21. case ___:
22. for (___________________)
23. __________________;
24. break;
25. case ___:
26. case __;
27. while (_____){
28. _______________;
29. ______________;
30. ______________;
31. }
32. break;
33. case ___:
34. case ___:
35. _________________;
36. break;
37. default:
38. _______________;
39. break;
40. }
41. _________________;
42. }
43.
44.
45. void main(){
46. if (_________)
47. ______________________________;
48. else
49. _______________________________;
50. }
51.
I've been all day studying for tomorrow's exam and I couldn't do this exercise in all day
Related
I'm having trouble understanding how the following equivalents work:
x86-64:
/*long loop(long x, int n)*/
/*x in %rdi, n in %esi*/
1.loop:
2 movl %esi, %ecx
3 movl $1, %edx
4 movl $0, %eax
5 jmp .L2
6.L3:
7 movq %rdi,%r8
8 andq %rdx,%r8
9 orq %r8,%rax
10 salq %cl,%rdx
11.L2
12 testq %rdx,%rdx
13 jne .L3
14 rep; ret
C:
1 long loop(long x, int n)
2 {
3 long result = 0;
4 long mask;
5 for (mask = 1; mask != 0; mask = mask << n) {
6 result |= (x & mask);
7 }
8 return result;
9 }
From what I see,
n = %esi and is copied into %ecx.
1 is copied into mask.
0 is copied into result.
I would like to know why 1 is copied to mask when the first variable in the C code is result? Wouldn't result = 1 and mask = 0 since that is the correct order in the C program? Furthermore, when I convert the C code to assembly language, I get:
1.loop:
2 movl %rsi, %rcx
3 movl $1, %eax
4 movl $0, %edx
5 jmp .L2
...
So are the registers %eax and %edx interchangeable?
[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.
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
The following code computes the product of x and y and stores the result in memory. Data type ll_t is defined to
be equivalent to long long.
gcc generates the following assembly code implementing the computation:
typedef long long ll_t;
void store_prod(ll_t *dest, int x, ll_t y)
{
*dest = x*y;
}
dest at %ebp+8, x at %ebp+12, y at %ebp+16
1 movl 16(%ebp), %esi
2 movl 12(%ebp), %eax
3 movl %eax, %edx
4 sarl $31, %edx
5 movl 20(%ebp), %ecx
6 imull %eax, %ecx
7 movl %edx, %ebx
8 imull %esi, %ebx
9 addl %ebx, %ecx
10 mull %esi
11 leal (%ecx,%edx), %edx
12 movl 8(%ebp), %ecx
13 movl %eax, (%ecx)
14 movl %edx, 4(%ecx)
This code uses three multiplications to implement the multi precision arithmetic required to implement 64-bit arithmetic
on a 32-bit machine. Describe the algorithm used to compute the product, and annotate the assembly code to show how
it realizes your algorithm.
Question: What does line 5 do? what value is it moving to register ecx?
also what does line 11 do ?
Line 5: it's copying the value of some local variable to ECX. The value is unkown as of this listing, as we lack part of the original function code.
Line 11: it's equivalent to: EDX = EDX+ECX. The LEA instruction is used to compute the EA of a memory value and store that EA into a destination register, thus, it can be used to quickly do additions and constant multiplication.
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