Note: The uninterrupted disassembly is at the bottom

Hey, I'm looking at the the assembly and I'm trying to reverse engineer the function

Here, it seems like we are saving the previous rbp. Though, it seems like there is no new value for rbp

0x004010b0      push    rbp

We are clearing the xmm0 registers

0x004010b1      pxor    xmm0, xmm0

Moving 0x40202c into rdi for the call fgets. This would be the first argument. If I were to view the address at 0x40402c, I would see the string Input

0x004010b5      lea     rdi, str.Input: ; 0x40202c ; const char *s

Making room for local variables, but it seems odd to be doing it after the lea and pxor. So the previous stack frame never de-alloacted so we just increased it by much larger

0x004010bc      sub     rsp, 0x50

Moving the xmm0 onto the top of stack. I don't think I've ever seen an xmmword before. I also imagine this is a local variable.

0x004010c0      movaps  xmmword [rsp], xmm0

Ah, here's the rest of prologue! We are setting the value of rbp to rsp so the stack frame is 0

0x004010c4      mov     rbp, rsp

Creating local variables!

0x004010c7      movaps  xmmword [rsp + 0x10], xmm0
0x004010cc      movaps  xmmword [rsp + 0x20], xmm0
0x004010d1      movaps  xmmword [rsp + 0x20], xmm0

Assigning a loval variable 0. Because it is a byte, it is probably a char

0x004010d6      mov     byte [rsp + 0x40], 0

We passed Input into rdi and called puts so we outputted Input

0x004010db      call    puts       

Arguments are passed into rdi, rsi, and rdx. So we have: fgets(rbp, 0x41, stdin). It's also worth nothing that rbp is probably the buffer and we passed 0x41 as the size which is a large buffer. The stack frame is 0 because we only recently moved the value of rsp into rbp. (i.e., rbp = rsp). And we did not not allocated space after the mov rbp, rsp.

0x004010e0      mov     rdx, qword [stdin] ; 0x404090 ; FILE *stream
0x004010e7      mov     esi, 0x41 
0x004010ec      mov     rdi, rbp   
0x004010ef      call    fgets     

rbp was the buffer so we're moving the string into the first argument. The buffer might have been 65, but the char array could have terminated before that so the string length could have shorter.

0x004010f4      mov     rdi, rbp 
0x004010f7      call    strlen  

Pass the string itself, rbp, and the length of the string, which was the return value of strlen (and return values are placed in eax) and pass it into the function

0x004010fc      mov     rdi, rbp
0x004010ff      mov     esi, eax
0x00401101      call    fcn.0040152b

Clean up the stack and return 0!

0x00401106      add     rsp, 0x50
0x0040110a      xor     eax, eax
0x0040110c      pop     rbp
0x0040110d      ret

So, I imagine main looks like

#include <stdio.h>
#include <string.h>

int main()
    char str[65];

    float local_var_1 = 0;
    float local_var_2 = 0;
    float local_var_3 = 0;
    char  rsp_40      = 0;


    fgets(str, 65, stdin);
    int str_length = strlen(str);

    some_fun(str, str_length);

    return 0;

Is there anything wrong with this assessment?

The original assembly:

0x004010b0      push    rbp
0x004010b1      pxor    xmm0, xmm0
0x004010b5      lea     rdi, str.Input: ; 0x40202c ; const char *s
0x004010bc      sub     rsp, 0x50
0x004010c0      movaps  xmmword [rsp], xmm0
0x004010c4      mov     rbp, rsp
0x004010c7      movaps  xmmword [rsp+0x10], xmm0
0x004010cc      movaps  xmmword [rsp+0x20], xmm0
0x004010d1      movaps  xmmword [rsp+0x30], xmm0
0x004010d6      mov     byte [rsp+0x40], 0
0x004010db      call    puts       ; sym.imp.puts ; int puts(const char *s)
0x004010e0      mov     rdx, qword [stdin] ; 0x404090 ; FILE *stream
0x004010e7      mov     esi, 0x41  ; 'A' ; 65 ; int size
0x004010ec      mov     rdi, rbp   ; char *s
0x004010ef      call    fgets      ; sym.imp.fgets ; char *fgets(char *s, int size, FILE *stream)
0x004010f4      mov     rdi, rbp   ; const char *s
0x004010f7      call    strlen     ; sym.imp.strlen ; size_t strlen(const char *s)
0x004010fc      mov     rdi, rbp   ; int64_t arg1
0x004010ff      mov     esi, eax   ; uint64_t arg2
0x00401101      call    fcn.0040152b
0x00401106      add     rsp, 0x50
0x0040110a      xor     eax, eax
0x0040110c      pop     rbp
0x0040110d      ret
  • movaps is similar to doing a memset (....) in your example it clears of 0x40 bytes to NULL [rsp],[rsp+10] , [rsp+20] , [rsp+30] something roughly equal to char foo[0x40] ={0};
    – blabb
    Oct 8, 2022 at 3:00

1 Answer 1


As i commented there are no float or xmm operations that are happening in your code

the xmm operations are compiler optimizations to set a small buffer to Zero
or memset the buffer to NULL

roughly equivalent to memset(buff,0,size); or most probably a declaration like char foo[SIZE] ={0} optimized away;

see the demo below

source code

:\>type movaps.cpp
#include <stdio.h>
#include <string.h>
int main(void) {
        char foo[0x41] = {0};
        printf("%s\tsize=%zd\n" ,foo,strlen(fgets(foo,0x41,stdin)));
        return 0;

compiling with maximum optimizations enabled in vs2019 community as x64

:\>cl /Zi /W4 /analyze /Ox movaps.cpp /link /release
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30146 for x64

executing the compiled binary


disassembling the relevant function main() in this case

:\>cdb -c "uf movaps!main;q" movaps.exe

Microsoft (R) Windows Debugger Version 10.0.19041.685 AMD64

00007ff8`516e0930 cc              int     3
0:000> cdb: Reading initial command 'uf movaps!main;q'
00007ff6`14501000 4881ec88000000  sub     rsp,88h
00007ff6`14501007 488b05fadf0600  mov     rax,qword ptr [movaps!__security_cookie (00007ff6`1456f008)]
00007ff6`1450100e 4833c4          xor     rax,rsp
00007ff6`14501011 4889442470      mov     qword ptr [rsp+70h],rax
00007ff6`14501016 0f57c0          xorps   xmm0,xmm0
00007ff6`14501019 488d0d60c30500  lea     rcx,[movaps!__xt_z+0x8 (00007ff6`1455d380)]
00007ff6`14501020 33c0            xor     eax,eax
00007ff6`14501022 0f11442420      movups  xmmword ptr [rsp+20h],xmm0
00007ff6`14501027 88442460        mov     byte ptr [rsp+60h],al
00007ff6`1450102b 0f11442430      movups  xmmword ptr [rsp+30h],xmm0
00007ff6`14501030 0f11442440      movups  xmmword ptr [rsp+40h],xmm0
00007ff6`14501035 0f11442450      movups  xmmword ptr [rsp+50h],xmm0
00007ff6`1450103a e861110100      call    movaps!puts (00007ff6`145121a0)
00007ff6`1450103f 33c9            xor     ecx,ecx
00007ff6`14501041 e8fa080100      call    movaps!__acrt_iob_func (00007ff6`14511940)
00007ff6`14501046 4c8bc0          mov     r8,rax
00007ff6`14501049 488d4c2420      lea     rcx,[rsp+20h]
00007ff6`1450104e ba41000000      mov     edx,41h
00007ff6`14501053 e8240c0100      call    movaps!fgets (00007ff6`14511c7c)
00007ff6`14501058 49c7c0ffffffff  mov     r8,0FFFFFFFFFFFFFFFFh
00007ff6`1450105f 90              nop

00007ff6`14501060 49ffc0          inc     r8
00007ff6`14501063 42803c0000      cmp     byte ptr [rax+r8],0
00007ff6`14501068 75f6            jne     movaps!main+0x60 (00007ff6`14501060)

00007ff6`1450106a 488d542420      lea     rdx,[rsp+20h]
00007ff6`1450106f 488d0d12c30500  lea     rcx,[movaps!__xt_z+0x10 (00007ff6`1455d388)]
00007ff6`14501076 e885000000      call    movaps!printf (00007ff6`14501100)
00007ff6`1450107b 33c0            xor     eax,eax
00007ff6`1450107d 488b4c2470      mov     rcx,qword ptr [rsp+70h]
00007ff6`14501082 4833cc          xor     rcx,rsp
00007ff6`14501085 e856010000      call    movaps!__security_check_cookie (00007ff6`145011e0)
00007ff6`1450108a 4881c488000000  add     rsp,88h
00007ff6`14501091 c3              ret

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.