Search code examples
debuggingassemblyx86gdbx86-64

What does movsbl (%rax, %rcx, 1),%eax and $0xf, %eax do?


movsbl (%rax, %rcx, 1),%eax
and $0xf, %eax

I have:

%rax=93824992274748
%eax=1431693628
%rcx=0

I really don't know what the reason why I have these results: How does the first instruction gives me %eax=97? Why does the and between the binary representation of 97 and 1111 give me 1?


Solution

  • Bitwise AND compares the bits of both operands. In this case, 97 AND 15:

    0110 0001  ;97
    0000 1111  ;15
    

    For each column of bits, if both bits in the column are 1, the resulting bit in that column is 1. Otherwise, it's zero.

    0110 0001  ;97
    0000 1111  ;15
    ---------------
    0000 0001  ;1
    

    You might be wondering what purpose this serves. There's a lot of things you can do with AND actually, many of which aren't obvious at first glance. It's very helpful to think of one of the operands as your data and the other as a "filter."


    For example, let's say we have a function called rand that returns a random 32-bit unsigned integer in %eax every time you call it. Assume that all possible values are equally likely. Now, let's say that we have some function called myEvent, and whether we call it or not shall be based on the outcome of rand. If we want this event to have a 1 in 16 chance of occurring, we can do this:

    call rand
    and $0xf, %eax
    jnz skip
       call myEvent
    skip:
    

    The reason this works is because every multiple of 16 has the bottom 4 bits clear. So those are the only bits we're interested in, and we can use and $0xf, %eax ignore everything to the left of those 4 bits, since they'll all turn into zeroes after the and. Once we've done the and, we can then see if %eax contains zero. If it does, %eax contained a multiple of 16 prior to the and.


    Here's another example. This tells you if %eax is odd or even:

    and $1, %eax
    jnz isOdd
    

    This works because a number is odd if its rightmost binary digit is 1. Any time you do a n % 2 in a high-level language, the compiler replaces it with n & 1 rather than doing actual division.