Assembling code in WinDbg
I was recently asked why the following code used byte ptr modifier for MOV instruction when assigning a number to a memory location pointed to by a register:
C/C++ code:
int a;
int *pa = &a;
void foo()
{
__asm
{
// ...
mov eax, [pa]
mov [eax], 1
// ...
}
}
Generated x86 assembly language code:
0:000:x86> uf foo
[...]
0042d64e c60001 mov byte ptr [eax],1
[…]
It looks like by default Visual C++ inline assembler treats MOV as “byte ptr” because it doesn’t know about C or C++ language semantics. Originally I thought that was the sign of a code optimization because the resulted binary code is smaller than the one generated by dword ptr. In order to check that I used a WinDbg command:

0:000> a
77067dfe mov dword ptr [eax], 1
mov dword ptr [eax], 1
77067e04
0:000> u 77067dfe
ntdll!DbgBreakPoint:
77067dfe c70001000000 mov dword ptr [eax],1
77067e04 0c8b or al,8Bh
77067e06 54 push esp
77067e07 2408 and al,8
77067e09 c70200000000 mov dword ptr [edx],0
77067e0f 897a04 mov dword ptr [edx+4],edi
77067e12 0bff or edi,edi
77067e14 741e je ntdll!RtlInitString+0×34 (77067e34)
This could be possible because the variable “a” is global, initialized to 0 during the program startup, so it is safe to change just one byte. If “a” was a local variable (on stack) than other 3 bytes of DWORD could contain garbage from the previously used stack memory. However, I noticed that the program was compiled as Debug target with all optimization turned off. If Visual C++ compiler was used it should have assumed that the variable “a” could have been referenced from other compilation units and no longer contained 0 before the assignment in foo function. I recreated the same code in C/C++, built the new Debug executable, and indeed, it used dword ptr instead of byte ptr as expected from C/C++ semantics.
- Dmitry Vostokov @ DumpAnalysis.org -