include 'C:\fasm\INCLUDE\win32a.inc'

;ap = register to store va_list in, v = last argument before va_list
;vSize = size of argument v.
macro va_start ap*, v*, vSize*
{
	lea ap, v
	add ap, vSize
}

;ap = va_list, t = size of argument that is being taken out of va_list
;value is returned in eax register.
macro va_arg ap*, t*
{
	mov eax, [ap]
	add ap, t
}

;ap = va_list, lSize = overall size of remaining arguments in va_list
;if you picked all values from va_list by using va_arg then you should
;not specify lSize.
;if you did not pick all arguments from va_list using va_arg or you
;picked up only few, but not all, specify overall size of remaining
;args you left in the list. this value is used in cleaning stack.
macro va_end ap*
{
	xor ap, ap
}

format PE console 4.0
  push ebx		   ;ebx is saved, it must survive accross the calls!
  ;these 3 values simulate call with va list
  ;function would look like func(arg0, ...);
  push 2;va_arg 2
  push 1;va_arg 1
  push 0;arg0

  va_start ebx, [esp], 4  ;[esp] = arg0

  push ebx		  ;va_list
  push fmt		  ;format
  call [vprintf]	  ;printing whole va_list
  add  esp, 8

  va_arg ebx, 4
  push eax		  ;va_list
  push fmt2		  ;format
  call [printf] 	  ;printing first arg from the list
  add  esp, 8

  va_arg ebx, 4
  push eax		  ;va_list
  push fmt2		  ;format
  call [printf] 	  ;printing second arg from the list
  add  esp, 8

  add esp, 0Ch		  ;remove arg0 and va_args
  va_end ebx

  pop ebx		  ;ebx restored
  call [getchar]
  ret 8 		  ;The space for the parameters passed to main func has been released


fmt db "%u %u", 10, 0
fmt2 db "%u", 10, 0

data import
 library kernel32,'KERNEL32.DLL',\
	 msvcrt,'MSVCRT.DLL '

 import kernel32,\
	ExitProcess,'ExitProcess'

 import msvcrt,\
	getchar, 'getchar',\
	printf ,'printf', \
	vprintf, 'vprintf'
end data