The following is a disassembly and analysis of the command line parsing for Visual C++ version 10 (VC++ 10.0, Visual Studio 2010) as found in file msvcr100d.dll. See parameters.htm#WINCRULES
1024B319 CCCCCCCCCCCCCC Align 8 1024B320 SUB_L1024B320: 1024B320 8BFF mov edi,edi 1024B322 55 push ebp 1024B323 8BEC mov ebp,esp 1024B325 83EC14 sub esp,00000014h 1024B328 8B4518 mov eax,[ebp+18h] ;length of output string (length it would be if we were building one) 1024B32B C70000000000 mov dword ptr [eax],00000000h 1024B331 8B4D14 mov ecx,[ebp+14h] ;argc count 1024B334 C70101000000 mov dword ptr [ecx],00000001h 1024B33A 8B5508 mov edx,[ebp+08h] 1024B33D 8955FC mov [ebp-04h],edx 1024B340 837D0C00 cmp dword ptr [ebp+0Ch],00000000h 1024B344 7411 jz L1024B357 ;no argv array to build 1024B346 8B450C mov eax,[ebp+0Ch] ;argv array ptr 1024B349 8B4D10 mov ecx,[ebp+10h] 1024B34C 8908 mov [eax],ecx 1024B34E 8B550C mov edx,[ebp+0Ch] ;argv array ptr 1024B351 83C204 add edx,00000004h ;point to next argv element 1024B354 89550C mov [ebp+0Ch],edx 1024B357 L1024B357: 1024B357 C745F800000000 mov dword ptr [ebp-08h],00000000h ;clear In Double Quoted Part flag 1024B35E L1024B35E: ; parse off program filename (argv[0]) 1024B35E 8B45FC +-------------------->mov eax,[ebp-04h] ; pointer to wchar from command line 1024B361 0FB708 | movzx ecx,[eax] ; get wchar pointer points to 1024B364 83F922 | cmp ecx,00000022h ; " ? 1024B367 7521 | +-jnz L1024B38A ; not a " 1024B369 33D2 | | xor edx,edx ; edx=0 1024B36B 837DF800 | | cmp dword ptr [ebp-08h],00000000h ; test In Double Quoted Part flag 1024B36F 0F94C2 | | setz dl ; toggle In Double Quoted Part flag 1024B372 8955F8 | | mov [ebp-08h],edx ; store In Double Quoted Part flag 1024B375 8B45FC | | mov eax,[ebp-04h] ; pointer to wchar from command line 1024B378 668B08 | | mov cx,[eax] ; get wchar pointer points to 1024B37B 66894DF0 | | mov [ebp-10h],cx ; save wchar from command line here 1024B37F 8B55FC | | mov edx,[ebp-04h] ; pointer to wchar from command line 1024B382 83C202 | | add edx,00000002h ; move to next wchar 1024B385 8955FC | | mov [ebp-04h],edx ; store updated pointer into command line 1024B388 EB3B | +------------|-jmp L1024B3C5 1024B38A | | L1024B38A:| 1024B38A 8B4518 | | +>mov eax,[ebp+18h] ;pointer to length of output string (length it would be if we were building one) 1024B38D 8B08 | | mov ecx,[eax] ;count of output chars 1024B38F 83C101 | | add ecx,00000001h ;increment count of output chars 1024B392 8B5518 | | mov edx,[ebp+18h] ;fetch pointer to count of output chars ;length of output string (length it would be if we were building one) 1024B395 890A | | mov [edx],ecx ;save count 1024B397 837D1000 | | cmp dword ptr [ebp+10h],00000000h ;are we building an output string? 1024B39B 7415 | | +---jz L1024B3B2 ;no | | | ;add wchar to output string 1024B39D 8B4510 | | | mov eax,[ebp+10h] ;pointer to output string 1024B3A0 8B4DFC | | | mov ecx,[ebp-04h] ;pointer to wchar from command line 1024B3A3 668B11 | | | mov dx,[ecx] ;wchar from command line 1024B3A6 668910 | | | mov [eax],dx ;add char to output string 1024B3A9 8B4510 | | | mov eax,[ebp+10h] ;pointer to output string 1024B3AC 83C002 | | | add eax,00000002h ;move to next wchar in output string 1024B3AF 894510 | | v mov [ebp+10h],eax ;store new position into output string 1024B3B2 | | L1024B3B2: 1024B3B2 8B4DFC | | mov ecx,[ebp-04h] ;pointer to wchar from command line 1024B3B5 668B11 | | mov dx,[ecx] ;the wchar 1024B3B8 668955F0 | | mov [ebp-10h],dx ;save wchar from command line here 1024B3BC 8B45FC | | mov eax,[ebp-04h] ;pointer to wchar from command line 1024B3BF 83C002 | | add eax,00000002h ;move to next wchar 1024B3C2 8945FC | | mov [ebp-04h],eax ;save position of next wchar 1024B3C5 | +->L1024B3C5: 1024B3C5 0FB74DF0 | movzx ecx,[ebp-10h] ;saved wchar from command line 1024B3C9 85C9 | test ecx,ecx ;Are we at the end of the input command line? 1024B3CB 741C | +---jz L1024B3E9 ;at end of input command line 1024B3CD 837DF800 | | cmp dword ptr [ebp-08h],00000000h ; test In Double Quoted Part flag 1024B3D1 758B +---------------------jnz L1024B35E ;jump if In Double Quoted Part (accept character) 1024B3D3 0FB755F0 | | movzx edx,[ebp-10h] ;saved wchar from command line 1024B3D7 83FA20 | | cmp edx,00000020h ;space? 1024B3DA 740D | +---jz L1024B3E9 ;end of parameter 1024B3DC 0FB745F0 | | movzx eax,[ebp-10h] ;saved wchar from command line 1024B3E0 83F809 | | cmp eax,00000009h ;tab? 1024B3E3 0F8575FFFFFF +-----------------|---jnz L1024B35E ;no, go to next wchar | v 1024B3E9 L1024B3E9: ;end of program filename (argv[0]) 1024B3E9 0FB74DF0 movzx ecx,[ebp-10h] ;saved wchar from command line 1024B3ED 85C9 test ecx,ecx ;00h? (indicating we're at the end of command line) 1024B3EF 750B +---jnz L1024B3FC ;no 1024B3F1 8B55FC | mov edx,[ebp-04h] ;pointer to wchar from command line 1024B3F4 83EA02 | sub edx,00000002h ;back up to previous wchar 1024B3F7 8955FC | mov [ebp-04h],edx ;store updated pointer into command line 1024B3FA EB0F v +-jmp L1024B40B 1024B3FC L1024B3FC:| 1024B3FC 837D1000 | cmp dword ptr [ebp+10h],00000000h ;end of input command line? 1024B400 7409 +-jz L1024B40B ;yes 1024B402 33C0 | xor eax,eax ;eax=0 1024B404 8B4D10 | mov ecx,[ebp+10h] ;pointer into output program filename (arg[0]) 1024B407 668941FE | mov [ecx-02h],ax ;add terminating NULL to output program filename (arg[0]) 1024B40B L1024B40B:| 1024B40B C745F800000000 +>mov dword ptr [ebp-08h],00000000h ;clear In Double Quoted Part flag ;PARSE OFF NEXT PARAMETER 1024B412 +-------------L1024B412: 1024B412 8B55FC | mov edx,[ebp-04h] ;pointer to wchar from command line ;fetch next character 1024B415 0FB702 | movzx eax,[edx] ;wchar from command line 1024B418 85C0 | test eax,eax ;end of command line? 1024B41A 7421 | +----------------jz L1024B43D ;yes 1024B41C | | L1024B41C: ;SKIP MULTIPLE SPACES/TABS BETWEEN PARAMETERS 1024B41C 8B4DFC | | +------------>mov ecx,[ebp-04h] ;pointer to wchar from command line 1024B41F 0FB711 | | | movzx edx,[ecx] ;wchar from command line 1024B422 83FA20 | | | cmp edx,00000020h ;space? 1024B425 740B | | | +---jz L1024B432 ;yes. Move to next character 1024B427 8B45FC | | | | mov eax,[ebp-04h] ;pointer to wchar from command line 1024B42A 0FB708 | | | | movzx ecx,[eax] ;wchar from command line 1024B42D 83F909 | | | | cmp ecx,00000009h ;tab? 1024B430 750B | | | v +-jnz L1024B43D ;no. (Beginning of next parameter) 1024B432 | | | L1024B432:| 1024B432 8B55FC | | | | mov edx,[ebp-04h] ;move to next wchar 1024B435 83C202 | | | | add edx,00000002h 1024B438 8955FC | | | | mov [ebp-04h],edx 1024B43B EBDF | | +-----------|-jmp L1024B41C | | | 1024B43D | | L1024B43D:| ;BEGINNING OF NEXT PARAMETER 1024B43D 8B45FC | +--------------+>mov eax,[ebp-04h] ;pointer to next wchar 1024B440 0FB708 | movzx ecx,[eax] ;next wchar 1024B443 85C9 | test ecx,ecx ;are we at the end of the command line? 1024B445 7505 | +-jnz L1024B44C ;no 1024B447 E96A010000 | | jmp L1024B5B6 ;end of command line. (Go to end) 1024B44C | L1024B44C:| 1024B44C 837D0C00 | +>cmp dword ptr [ebp+0Ch],00000000h ;are we building argv array ptrs? 1024B450 7411 | +---jz L1024B463 ;no 1024B452 8B550C | | mov edx,[ebp+0Ch] ;argv array ptr 1024B455 8B4510 | | mov eax,[ebp+10h] ;address of output string 1024B458 8902 | | mov [edx],eax ;save current address of output string as next argv ptr (argv[0]) 1024B45A 8B4D0C | | mov ecx,[ebp+0Ch] ;argv array ptr 1024B45D 83C104 | | add ecx,00000004h ;move to next argv 1024B460 894D0C | v mov [ebp+0Ch],ecx ;(and save new address of next ptr) 1024B463 | L1024B463: 1024B463 8B5514 | mov edx,[ebp+14h] ;pointer to argc counter 1024B466 8B02 | mov eax,[edx] ;argc count 1024B468 83C001 | add eax,00000001h ;increment argc count (assume we have at least 1 parameter and not just trailing spaces?) 1024B46B 8B4D14 | mov ecx,[ebp+14h] ;pointer to argc counter 1024B46E 8901 | mov [ecx],eax ;argc count | | ;process this wchar stored at [ebp-04h] 1024B470 | L1024B470: 1024B470 C745F401000|00 +-------------------->mov dword ptr [ebp-0Ch],00000001h ;do add this character to output string 1024B477 C745EC00000|00 | mov dword ptr [ebp-14h],00000000h ;number of backslashes 1024B47E | | L1024B47E: ;count backslashes 1024B47E 8B55FC | | +----->mov edx,[ebp-04h] ;pointer to wchar 1024B481 0FB702 | | | movzx eax,[edx] ;wchar 1024B484 83F85C | | | cmp eax,0000005Ch ; \ 1024B487 7514 | | | +---jnz L1024B49D ; not a \ 1024B489 8B4DFC | | | | mov ecx,[ebp-04h] ;pointer to wchar 1024B48C 83C102 | | | | add ecx,00000002h ;move to next wchar 1024B48F 894DFC | | | | mov [ebp-04h],ecx ;save updated pointer to wchar 1024B492 8B55EC | | | | mov edx,[ebp-14h] ;retrieve number of backslashes 1024B495 83C201 | | | | add edx,00000001h ;increment count of backslashes 1024B498 8955EC | | | | mov [ebp-14h],edx ;save number of backslashes 1024B49B EBE1 | | +--|---jmp L1024B47E | | v 1024B49D | | L1024B49D: ;first character that's not a \. Is it a " ? 1024B49D 8B45FC | | mov eax,[ebp-04h] ;pointer to wchar in command line string 1024B4A0 0FB708 | | movzx ecx,[eax] ;wchar 1024B4A3 83F922 | | cmp ecx,00000022h ; " ? 1024B4A6 7548 | | +------------------jnz L1024B4F0 ;jump if char not " | | | | | | ;this char a ". Do we have an even or odd number of backslashes before the " 1024B4A8 8B45EC | | | mov eax,[ebp-14h] ;number of backslashes 1024B4AB 33D2 | | | xor edx,edx ;zero 1024B4AD B902000000 | | | mov ecx,00000002h ;divide number of backslashes by 2 1024B4B2 F7F1 | | | div ecx ;EDX:EAX is divided by ecx 1024B4B4 85D2 | | | test edx,edx ;remainder in edx. Even number of backslashes? 1024B4B6 7530 | | | +--------------jnz L1024B4E8 ;no (we have odd number of backslashes) | | | | | | | | ;Even number of \. Are we in a double quoted part? 1024B4B8 837DF800 | | | | cmp dword ptr [ebp-08h],00000000h ; test In Double Quoted Part flag 1024B4BC 7417 | | | | +---jz L1024B4D5 ;not in a double quoted part, even number of backslashes, this wchar a " | | | | | | | | | | ;in double quoted part, even number of backslashes, this wchar a ". If next wchar is also ", skip first " and take second ". 1024B4BE 8B55FC | | | | | mov edx,[ebp-04h] ;pointer to wchar in command line string 1024B4C1 0FB74202 | | | | | movzx eax,[edx+02h] ;peek ahead without moving. Is next wchar also a " ? 1024B4C5 83F822 | | | | | cmp eax,00000022h ;is next wchar a " ? 1024B4C8 750B | | | | +---jnz L1024B4D5 ;next wchar not a " | | | | | | | | | | ;in double quoted part AND this wchar and next wchar both are ". Skip over this " (we'll take the next one) 1024B4CA 8B4DFC | | | | | mov ecx,[ebp-04h] ;pointer to wchar in command line string 1024B4CD 83C102 | | | | | add ecx,00000002h ;move to next wchar in command line string (skipping over first ") 1024B4D0 894DFC | | | | | mov [ebp-04h],ecx ;save updated pointer to wchar in command line string 1024B4D3 EB13 | | | | | +-jmp L1024B4E8 | | | | v | 1024B4D5 | | | | L1024B4D5:| ;(not in a double quoted part, even number of backslashes, this wchar a ") | | | | | ;OR (in a double quoted part, even number of backslashes, this wchar a " and next wchar NOT a ") | | | | | ;TOGGLE IN DOUBLE QUOTED PART FLAG 1024B4D5 C745F400000|00 | | | | mov dword ptr [ebp-0Ch],00000000h ;clear flag so we don't add this wchar to output string? 1024B4DC 33D2 | | | | | xor edx,edx ;edx=0 1024B4DE 837DF800 | | | | | cmp dword ptr [ebp-08h],00000000h ; test In Double Quoted Part flag 1024B4E2 0F94C2 | | | | | setz dl ;toggle In Double Quoted Part flag (set dl based on FLAGS register) 1024B4E5 8955F8 | | | | | mov [ebp-08h],edx ;store updated In Double Quoted Part flag 1024B4E8 | | | +->L1024B4E8:| 1024B4E8 8B45EC | | | +>mov eax,[ebp-14h] ;number of backslashes 1024B4EB D1E8 | | | shr eax,1 ;backslashes/2 (number to actually insert) 1024B4ED 8945EC | | | mov [ebp-14h],eax ;save number of backslashes to insert | | | | | | ;ADD BACKSLASHES TO OUTPUT STRING 1024B4F0 | | +----->L1024B4F0: 1024B4F0 8B4DEC | | | mov ecx,[ebp-14h] ;number of backslashes to insert 1024B4F3 8B55EC | | | mov edx,[ebp-14h] ;number of backslashes to insert 1024B4F6 83EA01 | | | sub edx,00000001h ;decrement number of backslashes to insert 1024B4F9 8955EC | | | mov [ebp-14h],edx ;store number of backslashes to insert 1024B4FC 85C9 | | | test ecx,ecx ;any more backslashes to add? 1024B4FE 7429 | | | +---------------jz L1024B529 ;no more backslashes to insert 1024B500 837D1000 | | | | cmp dword ptr [ebp+10h],00000000h ;are we building an output string? 1024B504 7414 | | | | jz L1024B51A ;no 1024B506 B85C000000 | | | | mov eax,0000005Ch ; \ 1024B50B 8B4D10 | | | | mov ecx,[ebp+10h] ; output string 1024B50E 668901 | | | | mov [ecx],ax ; add a backslash to output string 1024B511 8B5510 | | | | mov edx,[ebp+10h] ; output string 1024B514 83C202 | | | | add edx,00000002h ; move to next wchar in output string 1024B517 895510 | | | | mov [ebp+10h],edx ; output string 1024B51A | | | | L1024B51A: 1024B51A 8B4518 | | | | mov eax,[ebp+18h] ;fetch pointer to count of output chars ;length of output string (length it would be if we were building one) 1024B51D 8B08 | | | | mov ecx,[eax] ;count of output chars 1024B51F 83C101 | | | | add ecx,00000001h ;increment count 1024B522 8B5518 | | | | mov edx,[ebp+18h] ;fetch pointer to count of output chars ;length of output string (length it would be if we were building one) 1024B525 890A | | | | mov [edx],ecx ;save count 1024B527 EBC7 | | +--|---------------jmp L1024B4F0 1024B529 | | +-->L1024B529: | | ;done adding backslashes to output string 1024B529 8B45FC | | mov eax,[ebp-04h] ;pointer to character from command line 1024B52C 0FB708 | | movzx ecx,[eax] ;character from command line 1024B52F 85C9 | | test ecx,ecx ;end of command line? 1024B531 741C | | +----jz L1024B54F ;yes (then end of parameter) 1024B533 837DF800 | | | cmp dword ptr [ebp-08h],00000000h ; In Double Quoted Part flag 1024B537 7518 | | | +-jnz L1024B551 ; jump if " flag set 1024B539 8B55FC | | | | mov edx,[ebp-04h] ; " flag not set. Fetch wchar. Space or Tab terminates this parameter. Else we continue 1024B53C 0FB702 | | | | movzx eax,[edx] ;(Space or Tab or EOL signifies end of parameter) 1024B53F 83F820 | | | | cmp eax,00000020h ;Space? 1024B542 740B | | +--|-jz L1024B54F ;end of this parameter 1024B544 8B4DFC | | | | mov ecx,[ebp-04h] ;pointer to wchar 1024B547 0FB711 | | | | movzx edx,[ecx] ;the wchar 1024B54A 83FA09 | | | | cmp edx,00000009h ;tab? 1024B54D 7502 | | v +-jnz L1024B551 ;no 1024B54F | | L1024B54F:| 1024B54F EB3C | | +--------------|-jmp L1024B58D ;end of this parameter 1024B551 | | | L1024B551:| ;not at end of parameter yet 1024B551 837DF400 | | | +>cmp dword ptr [ebp-0Ch],00000000h ;should we add this wchar to output string? 1024B555 7428 | | | +-------------jz L1024B57F ;no 1024B557 837D1000 | | | | cmp dword ptr [ebp+10h],00000000h ;are we building an output string? 1024B55B 7415 | | | | +---jz L1024B572 ;no 1024B55D 8B4510 | | | | | mov eax,[ebp+10h] ;output string 1024B560 8B4DFC | | | | | mov ecx,[ebp-04h] ;pointer to wchar 1024B563 668B11 | | | | | mov dx,[ecx] ;wchar 1024B566 668910 | | | | | mov [eax],dx ;add wchar to output string 1024B569 8B4510 | | | | | mov eax,[ebp+10h] ;output string 1024B56C 83C002 | | | | | add eax,00000002h ;move to next wchar in output string 1024B56F 894510 | | | | v mov [ebp+10h],eax ;output string 1024B572 | | | | L1024B572: 1024B572 8B4D18 | | | | mov ecx,[ebp+18h] ;fetch pointer to count of output chars 1024B575 8B11 | | | | mov edx,[ecx] ;count of output chars 1024B577 83C201 | | | | add edx,00000001h ;increment count of output chars 1024B57A 8B4518 | | | | mov eax,[ebp+18h] ;and 1024B57D 8910 | | | | mov [eax],edx ;save count of output chars 1024B57F | | | | L1024B57F: 1024B57F 8B4DFC | | | +------------>mov ecx,[ebp-04h] ;pointer to wchar 1024B582 83C102 | | | add ecx,00000002h ;move to next wchar (in input string) 1024B585 894DFC | | | mov [ebp-04h],ecx ;pointer to next wchar (in input string) 1024B588 E9E3FEFFFF | +----|----------------jmp L1024B470 ;process this character | | | | ;end of this parameter 1024B58D | | L1024B58D: 1024B58D 837D1000 | +--------------->cmp dword ptr [ebp+10h],00000000h ;are we building an output string? 1024B591 7411 | +---jz L1024B5A4 ;no 1024B593 33D2 | | xor edx,edx 1024B595 8B4510 | | mov eax,[ebp+10h] ;output string 1024B598 668910 | | mov [eax],dx ;trailing 0 to output string (ASCIIZ) 1024B59B 8B4D10 | | mov ecx,[ebp+10h] ;output string 1024B59E 83C102 | | add ecx,00000002h ;move to next character in output string 1024B5A1 894D10 | v mov [ebp+10h],ecx ;output string 1024B5A4 | L1024B5A4: 1024B5A4 8B5518 | mov edx,[ebp+18h] ;fetch pointer to count of output chars 1024B5A7 8B02 | mov eax,[edx] ;count of output chars 1024B5A9 83C001 | add eax,00000001h ;increment count of output chars 1024B5AC 8B4D18 | mov ecx,[ebp+18h] ;and 1024B5AF 8901 | mov [ecx],eax ;store count of output chars 1024B5B1 E95CFEFFFF +-------------------------jmp L1024B412 ;PARSE OFF NEXT PARAMETER ;end 1024B5B6 L1024B5B6: 1024B5B6 837D0C00 cmp dword ptr [ebp+0Ch],00000000h ;are we building argv array ptrs? 1024B5BA 7412 +---jz L1024B5CE ;no 1024B5BC 8B550C | mov edx,[ebp+0Ch] ;argv array ptr 1024B5BF C70200000000 | mov dword ptr [edx],00000000h ;set current argv ptr to zero (terminate argv array?) 1024B5C5 8B450C | mov eax,[ebp+0Ch] ;and save it 1024B5C8 83C004 | add eax,00000004h ;move to next argv ptr 1024B5CB 89450C v mov [ebp+0Ch],eax ;and save it 1024B5CE L1024B5CE: 1024B5CE 8B4D14 mov ecx,[ebp+14h] ;pointer to argc counter 1024B5D1 8B11 mov edx,[ecx] 1024B5D3 83C201 add edx,00000001h ;increment argc counter 1024B5D6 8B4514 mov eax,[ebp+14h] 1024B5D9 8910 mov [eax],edx 1024B5DB 8BE5 mov esp,ebp 1024B5DD 5D pop ebp 1024B5DE C3 retn