tags:

views:

232

answers:

4
; int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
_wWinMain@16 proc near

var_4= dword ptr -4
hInstance= dword ptr  4
hPrevInstance= dword ptr  8
lpCmdLine= dword ptr  0Ch
nShowCmd= dword ptr  10h

From what I can see, the last 4 variables are the parameters passed to the WinMain function. Also, the var_4 must be a int variable I declared later in the function body. Now, I have a couple of questions:

a) What is the size of a word on a 32bit windows program? 4 bytes? being a dword 8?

b) Why is var_4 set to -4? Why not start at, let's say, 0?

c) The standard procedure for defining ints in c is though

var_x = dword ptr y?

Thanks

+2  A: 

a. DWORD is unsigned, 32 bit: see here (old name, MS started using it back when Windows was 16-bit).

b. the top of stack (dword ptr 0) is taken up by the return-address

c. a variable y here would not work. Anyway, this systematic use of dword ptr is characteristic of certain assemblers and disassemblers, not a "standard procedure".

Alex Martelli
Thanks for the answer. But I defined my variable as an int. How come it shows up as a unsigned 32 bit variable? Or that just means that it is a pointer(which obviously is an unsigned int?)
devoured elysium
Those are just macro defines to help make the assembly clear. They are offsets w.r.t. to the frame pointer.
sixlettervariables
@devoured elysiumThere is no difference between signed and unsigned data in ASM. They are just both 32 bit. The difference comes from what instructions you use to operate on them.
Ben Strasser
A: 

What you're seeing is because the method uses a common technique (perhaps using ENTER/LEAVE) where X number of bytes are added to the stack pointer to create the stack frame for the method. Local variables are at negative addresses from the frame pointer, the return address is at the top, and arguments to the method are at positive addresses from the frame pointer.

; Possible declaration for WinMain
PUSH EBP           ;
MOV EBP, ESP       ; optionally replace these lines with "ENTER 4,0"
SUB ESP, 4         ; 4 bytes for local variables (your INT32)

; ...

MOV [EBP - 4], 27  ; store 27 into the first local variable var_4
MOV EAX, [EBP + 4] ; put hInstance into EAX
MOV EBX, [EBP + 8] ; put hPrevInstance into EBX

; etc, ad nauseam

MOV ESP, EBP       ;
POP EBP            ; optionally replace these lines with "LEAVE"
RET                ;

You could use your macros to elucidate the code some:

hInstance= dword ptr 4
hPrevInstance= dword ptr 8

MOV ECX, [EBP + hInstance]     ; put hInstance into ECX
MOV EDX, [EBP + hPrevInstance] ; put hPrevInstance into EDX
CMP ECX, EDX
JE someLabel
sixlettervariables
A: 

(a) A dword is really a plain word, and it's 32-bits.

(b) Indexing on the stack isn't necessarily done via the stack pointer but via a frame pointer. ("Base" pointer in IA-land.) The frame, err, base, pointer will be set up to make stack traces possible. Locals and arguments are likely at lower addresses in memory, "higher" on the stack.

(c) Unlikely virtually every other assembler, the Intel format implements this abstraction where the data types have widths but not the typed-in-instructions, and so the assembler chooses the 8-, 16-, or 32-bit opcode1 based on your declaration of the operand. I've written lots of ia32 assembly, but only in various other assemblers2, so I can't comment on how this off-beat approach works in practice. It seems kind of clunky from a distance...


1. Technically the 16-bit and 32-bit opcodes are the same but an optional prefix byte switches between 16- and 32-bit mode.
2. The other IA32 assembler format is called AT&T Format for hysterical raisins.

DigitalRoss
+1  A: 

a.

  • word:2 bytes
  • dword:4 bytes
  • qword:8 bytes

A dword is the machine word. These names have been inherited from Win16 where 2 bytes actually formed a machine word.

b. That number represents the relative offset to the return address on the stack. bytes 0..3 are the return address itself. bytes < 0 are local variables and >= 4 are parameters to the function. Look at an assembler tutorial for details. Writing a couple of functions in pure ASM is the best way to understand these details.

c. ASM is not standardized. So there is no standard procedure.

Ben Strasser