I am having trouble understanding working with structs in assembly from disassembly. can you please explain the code below. Disassembly below:

disassembly snippet

Source code:

source code snippet

  • 2
    Could you please copy and paste the disassembly instead of posting screenshots? It'd really help others in the future as it improves indexing by search engines. Thanks!
    – 0xC0000022L
    Jun 6 '18 at 9:56
  • 1
    apologies for not being clear in my comment. I meant that you should edit your own question to replace the screenshots with the textual form. For this question this would seem to apply to both screenshots. Thank you.
    – 0xC0000022L
    Jun 6 '18 at 10:39
  • previous discussion on this optimization: reverseengineering.stackexchange.com/questions/10839
    – Igor Skochinsky
    Jun 6 '18 at 19:10
  • I downvoted your question because images of text are not useful at all. There is no need to supply this text as images. Will remove the downvote if you replace the images with text.
    – Jongware
    Jun 24 '18 at 12:47

This is called inlining. strcpy was substituted by mov instructions, because compiler decided that in such way code will run faster.


This is manual string assignment. Notice how all DWORDs are composed of printable characters? hit r in IDA to convert the hex values to string characters.

This code seems to be assigning strings into different stack addresses, 4 characters at a time. This is a common optimization over calling a function that iterates over strings byte by byte.

As others pointed out, this optimization is usually called "loop unrolling" as it unrolls several iterations of a loop into sequential assembly, however I often find that type of direct string characters assignment to be more commonly the output of a code similar to the following:

char str[] = "this is a string";
  • 1
    Key word: unrolled loop. Probably an inlined memmove (or strcpy).
    – 0xC0000022L
    Jun 6 '18 at 9:57
  • @0xC0000022L does it have to be, though? I think it can also be a direct assignment, say char a[] = "this is a string";, no?
    – NirIzr
    Jun 6 '18 at 16:18

the optimizations mantras of the answers got me intrigued so i thought i'll check what actual optimizations are being done on the code (OP appears to be beginner and i doubted OP would be capable of optimizing at all )

it appears this is default compilation without optimization enabled in gcc

gcc version 8.1.0 (i686-win32-dwarf-rev0, Built by MinGW-W64 project)

visual studio 2017 15.7.3 doesn't do this kind of code at all whether optimized or not

with optimizations disabled vs resorts to calling strcpy ()

:\>cl /nologo /Zi booky.cpp

:\>cdb -c ".lines;uf booky!main;q" booky.exe | grep -E "  15|  16|  17"

   15 001c6b35 6850be2100      push    offset booky!__xt_z+0x108 (0021be50)
   15 001c6b3a 8d8530ffffff    lea     eax,[ebp-0D0h]
   15 001c6b40 50              push    eax
   15 001c6b41 e86bb2ffff      call    booky!ILT+3500(_strcpy) (001c1db1) <<<<
   15 001c6b46 83c408          add     esp,8
   16 001c6b49 685cbe2100      push    offset booky!__xt_z+0x114 (0021be5c)
   16 001c6b4e 8d8d62ffffff    lea     ecx,[ebp-9Eh]
   16 001c6b54 51              push    ecx
   16 001c6b55 e857b2ffff      call    booky!ILT+3500(_strcpy) (001c1db1) <<<<
   16 001c6b5a 83c408          add     esp,8
   17 001c6b5d 6868be2100      push    offset booky!__xt_z+0x120 (0021be68)
   17 001c6b62 8d5594          lea     edx,[ebp-6Ch]
   17 001c6b65 52              push    edx
   17 001c6b66 e846b2ffff      call    booky!ILT+3500(_strcpy) (001c1db1)  <<<<
   17 001c6b6b 83c408          add     esp,8

optimising for space (O2) or full optimisations (Ox) vs2017 resorts to using sse2 moves

:\>cl /Zi /O2 booky.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26430 for x86

:\>cdb -c ".lines;uf booky!main;q" booky.exe | grep -E "  15|  16|  17"
   15 00f7aae4 a158befc00      mov     eax,dword ptr [booky!`string'+0x8 (00fcbe58)]

:\>cdb -c ".lines;uf booky!main;q" booky.exe | grep -A 5 -E "  15|  16|  17"
   15 00f7aae4 a158befc00      mov     eax,dword ptr [booky!`string'+0x8 (00fcbe58)]
   19 00f7aae9 b933000000      mov     ecx,33h
   19 00f7aaee f30f7e0550befc00 movq    xmm0,mmword ptr [booky!`string' (00fcbe50)] <<<<<<<<
   19 00f7aaf6 89442408        mov     dword ptr [esp+8],eax
   19 00f7aafa 0fb60568befc00  movzx   eax,byte ptr [booky!`string'+0x8 (00fcbe68)] <<<<<<<
   19 00f7ab01 8844243a        mov     byte ptr [esp+3Ah],al

:\>cl /Zi /Ox booky.cpp

:\>cdb -c ".lines;uf booky!main;q" booky.exe | grep -A 5 -E "  15|  16|  17"
   15 0138ac74 a198e83d01      mov     eax,dword ptr [booky!__newctype+0x308 (013de898)]
   19 0138ac79 b933000000      mov     ecx,33h
   19 0138ac7e f30f7e0590e83d01 movq    xmm0,mmword ptr [booky!__newctype+0x300 (013de890)]
   19 0138ac86 89442408        mov     dword ptr [esp+8],eax
   19 0138ac8a 0fb605a4e83d01  movzx   eax,byte ptr [booky!__newctype+0x314 (013de8a4)]
   19 0138ac91 8844243a        mov     byte ptr [esp+3Ah],al

mingw gcc 8.10 seems to break the strings into dwords even when explicitly disabling optimization with O0

:>gcc -g -O0 booky.cpp

g++ -g -O0 also disassembles to same construct as below

:\>objdump -d --start-address 0x4015c0 --stop-address 0x401600 -M intel a.exe

a.exe:     file format pei-i386

Disassembly of section .text:

004015c0 <_main>:
  4015c0:       55                      push   ebp
  4015c1:       89 e5                   mov    ebp,esp
  4015c3:       57                      push   edi
  4015c4:       56                      push   esi
  4015c5:       53                      push   ebx
  4015c6:       83 e4 f0                and    esp,0xfffffff0
  4015c9:       81 ec 70 02 00 00       sub    esp,0x270
  4015cf:       e8 ec 01 00 00          call   4017c0 <___main>
  4015d4:       8d 84 24 a4 01 00 00    lea    eax,[esp+0x1a4]
  4015db:       c7 00 50 72 6f 67       mov    DWORD PTR [eax],0x676f7250
  4015e1:       c7 40 04 72 61 6d 6d    mov    DWORD PTR [eax+0x4],0x6d6d6172
  4015e8:       c7 40 08 69 6e 67 00    mov    DWORD PTR [eax+0x8],0x676e69
  4015ef:       8d 84 24 a4 01 00 00    lea    eax,[esp+0x1a4]
  4015f6:       83 c0 32                add    eax,0x32
  4015f9:       c7 00 4e 75 68 61       mov    DWORD PTR [eax],0x6168754e
  4015ff:       c7                      .byte 0xc7

to disable this -fno-builtin-strcpy needs to be passed to gcc in commandline if -fno-builtin-strcpy is passed gcc wont chunk the strings even when compiled with -O3 optimization



:\>g++ -O3 -g -fno-builtin-strcpy -o booky.exe booky.cpp

booky.cpp  booky.exe


ProgrammingTelecom Billing


:\>objdump -d --start-address=0x402670 --stop-address=0x4026b0 -M intel booky.exe

booky.exe:     file format pei-i386

Disassembly of section .text:

00402670 <_main>:
  402670:       55                      push   ebp
  402671:       89 e5                   mov    ebp,esp
  402673:       57                      push   edi
  402674:       56                      push   esi
  402675:       53                      push   ebx
  402676:       83 e4 f0                and    esp,0xfffffff0
  402679:       81 ec 80 02 00 00       sub    esp,0x280
  40267f:       e8 ec ef ff ff          call   401670 <___main>
  402684:       8d 74 24 1c             lea    esi,[esp+0x1c]
  402688:       c7 44 24 04 44 40 40    mov    DWORD PTR [esp+0x4],0x404044
  40268f:       00
  402690:       8d bc 24 b4 01 00 00    lea    edi,[esp+0x1b4]
  402697:       89 34 24                mov    DWORD PTR [esp],esi
  40269a:       8d 9c 24 b4 01 00 00    lea    ebx,[esp+0x1b4]
  4026a1:       e8 ee fe ff ff          call   402594 <_strcpy>
  4026a6:       8d 44 24 4e             lea    eax,[esp+0x4e]
  4026aa:       c7                      .byte 0xc7
  4026ab:       44                      inc    esp
  4026ac:       24 04                   and    al,0x4
  4026ae:       50                      push   eax
  4026af:       40                      inc    eax

an analysed output from radare2

|           ; JMP XREF from 0x0040262f (sym.___getmainargs)
|           0x00402671      89e5           mov ebp, esp
|           0x00402673      57             push edi
|           0x00402674      56             push esi
|           0x00402675      53             push ebx
|           0x00402676      83e4f0         and esp, 0xfffffff0
|           0x00402679      81ec80020000   sub esp, 0x280
|           0x0040267f      e8ecefffff     call sym.___main
|           0x00402684      8d74241c       lea esi, [local_1ch]        ; 0x1c ; 28
|           0x00402688      c74424044440.  mov dword [local_4h], str.Programming ; 
[0x404044:4]=0x676f7250 ; "Programming" ; const char * src
|           0x00402690      8dbc24b40100.  lea edi, [local_1b4h]       ; 0x1b4 ; 436
|           0x00402697      893424         mov dword [esp], esi        ; char * dest
|           0x0040269a      8d9c24b40100.  lea ebx, [local_1b4h]       ; 0x1b4 ; 436
|           0x004026a1      e8eefeffff     call sym._strcpy            ;
 char *strcpy(char *dest, const char *src)
|           0x004026a6      8d44244e       lea eax, [local_4eh]        ; 0x4e ; 'N' ; 78
|           0x004026aa      c74424045040.  mov dword [local_4h], str.Nuha_Ali ; 
[0x404050:4]=0x6168754e ; "Nuha Ali" ; const char * src
|           0x004026b2      890424         mov dword [esp], eax        ; char * dest
|           0x004026b5      e8dafeffff     call sym._strcpy            ;
 char *strcpy(char *dest, const char *src)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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