-1

Heres an disas of a function which takes input and stops a bomb from exploding.

0x00000000004011ca <+0>:     sub    $0x8,%rsp                 #reserve 8 bytes on stack
0x00000000004011ce <+4>:     cmpb   $0x37,0x1(%rdi)           #compare 0x37 ('7') with second character of input
0x00000000004011d2 <+8>:     jne    0x4011df <phase_1+21>     #explode bomb if not equal
0x00000000004011d4 <+10>:    cmpb   $0x5d,0x2(%rdi)           #compare 0x5d (']') with third character of input
0x00000000004011d8 <+14>:    jne    0x4011df <phase_1+21>     #explode bomb if not equal
0x00000000004011da <+16>:    cmpb   $0x5a,(%rdi)              #compare 0x5a ('Z') with first character of input
0x00000000004011dd <+19>:    je     0x4011ed <phase_1+35>     #if all equal, skip bomb explosion
0x00000000004011df <+21>:    callq  0x401c01 <bomb_ignition>  #bomb explode
0x00000000004011e4 <+26>:    mov    $0xffffffffffffffff,%rax  #rax = -1
0x00000000004011eb <+33>:    jmp    0x401200 <phase_1+54>     #end 
0x00000000004011ed <+35>:    movsbl 0xf(%rdi),%eax            //need help here
0x00000000004011f1 <+39>:    add    $0x1b,%eax
0x00000000004011f4 <+42>:    movsbl 0xe(%rdi),%edx
0x00000000004011f8 <+46>:    cmp    %edx,%eax
0x00000000004011fa <+48>:    sete   %al
0x00000000004011fd <+51>:    movzbl %al,%eax
0x0000000000401200 <+54>:    add    $0x8,%rsp
0x0000000000401204 <+58>:    retq 

I have annotated what i think its doing with #. Please tell me if im wrong anywhere. I need help in figuring out what its doing at and after the first movsbl. From just reading, I think it extends %rdi by 15, then puts it in %eax. then adds 27. To what, I dont know. Then it extends %rdi by 14 and put it in %edx. It compares, and if equal, then sets flag %al? Then moves %al to %eax. Then clears up stack space. Then returns.

Did I go wrong anywhere in my understanding of anything? Can someone clarify what movsbl is doing in this? ANY HELP APPRECIATED. Thanks

Alonzo Robbe
  • 465
  • 1
  • 8
  • 23
  • https://stackoverflow.com/questions/7861095/what-does-movsbl-instruction-do – Mitch Wheat Sep 09 '17 at 06:16
  • @MitchWheat Ive seen that, and ones like it. They all seem to go over my head and dont seem to clearly explain what it does or why the examples behave the way they do (imo). Would you mind explaining it as if i was 5 – Alonzo Robbe Sep 09 '17 at 06:19
  • If this were written as `mov 0xf(%rdi),%eax` would it make more sense to you? You can't (quite) write that, since the source (`0xf(%rdi)`) is intended to be a byte, and the destination is a 32bit int (`eax`). Since the destination is 32bits long, you have to tell the assembler what to do with the other 24bits. Telling it to extend the sign bit (ie if the byte is negative, make the int negative) is one way of doing that. – David Wohlferd Sep 09 '17 at 06:44
  • `movsbl` is a **sign-extending load from memory** from 8-bit to 32-bit. – Peter Cordes Sep 09 '17 at 06:50

1 Answers1

1
movsbl 0xf(%rdi),%eax

movsbl is move byte to long using sign extension, so int8_t is promoted to int32_t; i.e.

int32_t eax = *((int8_t *)(rdi + 0xf));

This means that the signed value as interpreted according to the two's complement stays the same, so if the int8_t held e.g. -1, the int32_t would also hold -1. However if interpreted as unsigned, the corresponding values would be 0xFF and 0xFFFFFFFF which clearly are not the same. Unsigned promotion would zero-extend instead, so using movzbl here would extend 0xFF to 0x000000FF; zero extension ensures that the unsigned value after the extension is the same.

Then another not so obvious instruction is

sete   %al

Which is equal to

uint8_t al = <previous comparison equal/set zero flag> ? 1: 0;

Setting al does not reset the rest of the bits in eax, rax, so, the instruction

movzbl %al,%eax

moves byte to long, using zero extension, i.e. unsigned promotion:

uint32_t eax = (uint8_t)al;

This essentially zeroes all the higher order bits 8-63 in rax, because setting eax would also reset the higher order bits.

The default return value is in the accumulator, so the function returns either 1 or 0 and all intN_t and uintN_t for N of 8, 16, 32, 64 would work alike for the return type in the prototype.