문제

I'm reading a book Computer Systems: A Programmer's Perspective (2nd Edition) and Practice Problem 3.23 are little confused me:

A function fun_b has the following overall structure:

int fun_b(unsigned x) {
   int val = 0;
   int i;
   for ( ____;_____;_____) {
   }
   return val;
}

The gcc C compiler generates the following assembly code:

x at %ebp+8
1 movl 8(%ebp), %ebx
2 movl $0, %eax
3 movl $0, %ecx
.L13:
5 leal (%eax,%eax), %edx
6 movl %ebx, %eax
7 andl $1, %eax
8 orl  %edx, %eax
9 shrl %ebx   Shift right by 1
10 addl $1, %ecx
11 cmpl $32, %ecx
12 jne .L13

Reverse engineer the operation of this code and then do the following:

A. Use the assembly-code version to fill in the missing parts of the C code.

My solution.

int fun_b(unsigned x) {
   int val = 0;
   int i;
   for ( i = 0 ;i < 32;i++) {
      val  += val; //because leal (%eax,%eax), edx  --> %edx = %eax + %eax
      val = val | x & 0x1;
      x >>= 1;
   }
   return val;
}

Book's solution.

int fun_b(unsigned x) {
  int val = 0;
  int i;
  for (i = 0; i < 32; i++) {
    val = (val << 1) | (x & 0x1);
    x >>= 1;
  }
 return val;
}

Please, explain to me why leal function has non typical behavior in this function. And I dont understand how this assembly code is yielding this statement val = (val << 1) | (x & 0x1)

도움이 되었습니까?

해결책

In your code:

val  += val;
val = val | x & 0x1;

Here, val += val which is equivalent to (val*2) which is effectively equal to val left shifted by 1.

But I think your solution is correct only if the assembly code was something like:

x at %ebp+8
1 movl 8(%ebp), %ebx
2 movl $0, %eax
3 movl $0, %ecx
.L13:
5 addl  %eax, %eax
6 movl %ebx, %edx
7 andl $1, %edx
8 orl  %edx, %eax
9 shrl %ebx   # shift right by 1
10 addl $1, %ecx
11 cmpl $32, %ecx
12 jne .L13

Because if val + val was a separate statement, compiler usually places it in eax register rather than in edx (i'm not sure this is the case always). So, for the code you have given, the possible solutions are:

val = (val << 1) | (x & 0x1);

or

val = (val + val) | (x & 0x1);

or

val = (val * 2) | (x & 0x1);

다른 팁

x >>= 1; means multiplying x by 2 which in binary is shifting to the left or adding 0 at the right side

x >>= 1; == x * 2; == x +=x;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top