assembly - What's the purpose of "AND AL,0xFF"? -


i'm reading through disassembled win32 c++ program , see quite few:

and al,0xff 

is pointless or why compiler generate these?

here longer example:

movsx   eax, byte ptr [ebx] shl     eax, 18h movsx   edx, byte ptr [ebx+1] shl     edx, 10h add     eax, edx movsx   ecx, byte ptr [ebx+2] shl     ecx, 8 add     eax, ecx movsx   edx, byte ptr [ebx+3] add     eax, edx xor     edx, edx call    sub_43b55c mov     ecx, eax mov     edx, eax sar     ecx, 10h ,     al, 0ffh      # <---- sar     edx, 8 ,     cl, 0ffh      # <---- mov     [esi], cl ,     dl, 0ffh      # <---- mov     [esi+1], dl mov     [esi+2], al add     ebx, 4 add     esi, 3 inc     ebp cmp     ebp, 6 jl      short loc_43b5e4 

the flags aren't being checked after these operations can't purpose. after and, values in al, cl, , dl being moved [esi + n].

as @fuz suggested, fault of optimizer not recognizing foo & 0xff being no-op in context in used in original function.

i compiled following code snippet borland c++ builder 6 after setting project's compilation settings "release" :

unsigned char foobar(int foo) { return (foo >> 16) & 0xff; } 

this resembles operations carried out in disassembly provided quite closely. have 32-bit value want shift given number of bits , turn byte value, returning bits 16-23 of original value 1 byte. input parameter of type int in order generate sar instruction instead of shr : int used in original code well.

after compiling , disassembling resulting .obj objconv (as couldn't figure out how enable assembly listings within c++ builder's ide), got :

@foobar$qi proc near ;  comdef @foobar$qi         push    ebp                                     ; 0000 _ 55         mov     ebp, esp                                ; 0001 _ 8b. ec         mov     eax, dword ptr [ebp+8h]                 ; 0003 _ 8b. 45, 08         sar     eax, 16                                 ; 0006 _ c1. f8, 10         ,     al, 0ffffffffh                          ; 0009 _ 24, ff         pop     ebp                                     ; 000b _ 5d         ret                                             ; 000c _ c3 @foobar$qi endp 

as can see, redundant and still there. 32-bit immediate in disassembly can disregarded, since instruction's encoding shows immediate in actual code stream 8-bit : there no other valid options 8-bit register anyway.

microsoft visual studio c++ 6 seems guilty of same thing, operates on whole 32-bit register (thus generating 3 bytes more due 32-bit immediate), clearing upper bits - needless, seeing how return value of function explicitly declared 8-bit :

?foobar@@yaeh@z proc near                               ; foobar ; 1    : unsigned char foobar(int foo) { return (foo >> 16) & 0xff; }   00000 55               push    ebp   00001 8b ec            mov     ebp, esp   00003 8b 45 08         mov     eax, dword ptr _foo$[ebp]   00006 c1 f8 10         sar     eax, 16                        ; 00000010h   00009 25 ff 00 00 00   ,     eax, 255               ; 000000ffh   0000e 5d               pop     ebp   0000f c3               ret     0 ?foobar@@yaeh@z endp                                    ; foobar 

meanwhile, the oldest version of gcc available on godbolt correctly compiles what's shift, except natural differences between listings due calling conventions.


Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -