News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

An extended JWASM 64bit sample

Started by johnsa, July 27, 2011, 03:10:19 PM

Previous topic - Next topic

johnsa

I finally tried moving to 64bit code.. I've been avoiding it like the plague for ages!
I took one of the base samples, and extended it with some working 32bit masm code I had which includes some nice memory related features not present in the std windows.inc/kernel32.inc... I also had to extract a load of the functions from masm32lib and macros.asm to and manually make them 64bit/jwasm friendly.. all included in this source for reference.

Hope this is helpful to someone start, I wish I had the time to fully port the available macros.asm/m32lib to jwasm 64bit :)



;--- Win64 console application with exception handler, uses WinInc v2+
;--- assemble: jwasm -c -win64 -Zp8 Win64_5.asm
;--- link: link /subsystem:console /Libpath:\WinInc\Lib64 Win64_5.obj

;--- UPDATE (Must ensure you have latest WinInc, PellesC, run POLIB as per details to generate Lib64 in WinInc):
;--- assemble: jwasm -c -Zi  -Zd -Zf -win64 -Zp8 Win64_5.asm
;--- link:     link /subsystem:console /debug /pdb:win64_5.pdb /Libpath:"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib\x64" /Libpath:"c:\jwasm\wininc\lib64" /Libpath:"c:\masm32\lib" win64_5.obj

option win64:1
option casemap:none
    option frame:auto
.mmx
.xmm

    .nolist
    .nocref
WIN32_LEAN_AND_MEAN equ 1
    include ..\WinInc\Include\windows.inc
    .list
    .cref

include ..\WinInc\Include\shellapi.inc

includelib msvcrt.lib

externdef printf : near
externdef kbhit  : near
externdef strlen : near


    includelib <kernel32.lib>
    includelib <gdi32.lib>
    includelib <user32.lib>
includelib <shell32.lib>

PROCESS_MEMORY_COUNTERS STRUCT
  dwLength       DWORD ?
  PageFaultCount DWORD ?
  PeakWorkingSetSize dq ?
  WorkingSetSize dq ?
  QuotaPeakPagedPoolUsage dq ?
  QuotaPagedPoolUsage dq ?
  QuotaPeakNonPagedPoolUsage dq ?
  QuotaNonPagedPoolUsage dq ?
  PagefileUsage dq ?
  PeakPagefileUsage dq ?
PROCESS_MEMORY_COUNTERS ENDS

StdOut64 proto lpszText:QWORD

dwtoa proto :DWORD, :QWORD

GetPhysicallyInstalledSystemMemory PROTO :QWORD
K32GetProcessMemoryInfo PROTO :DWORD, :DWORD, :DWORD
GetProcessMemoryInfo EQU <K32GetProcessMemoryInfo>

   


  ; -----------------------------------------------------------
  ; This macro replaces quoted text with a DATA section OFFSET
  ; and returns it in ADDR "name" format. It is used by other
  ; macros that handle optional quoted text as a parameter.
  ; -----------------------------------------------------------
    reparg MACRO arg
      LOCAL nustr
        quot SUBSTR <arg>,1,1
      IFIDN quot,<">            ;; if 1st char = "
        .data
          nustr db arg,0        ;; write arg to .DATA section
        .code
        EXITM <ADDR nustr>      ;; append name to ADDR operator
      ELSE
        EXITM <ADDR arg>             ;; else return arg
      ENDIF
    ENDM

    print MACRO arg1:REQ,varname:VARARG      ;; display zero terminated string
        invoke StdOut64,reparg(arg1)
      IFNB <varname>
        invoke StdOut64,CStr(varname)
      ENDIF
    ENDM

      ustr$ MACRO DDvalue   ;; unsigned integer from string
        LOCAL rvstring
        .data
          rvstring db 20 dup (0)
        align 4
        .code
        invoke dwtoa,DDvalue,ADDR rvstring
;        invoke crt__ultoa,DDvalue,ADDR rvstring,10
        EXITM <OFFSET rvstring>
      ENDM
         
.data?

memStatus MEMORYSTATUSEX <?>
procMem PROCESS_MEMORY_COUNTERS <?>
totalMem dq ?
     
;--- CStr(): macro function to simplify defining a string

CStr macro Text:VARARG
local szText
    .const
szText  db Text,0
    .code
    exitm <offset szText>
endm

  ; ------------------------------------------------
  ; Function return value version of the above macro
  ; ------------------------------------------------
    rv MACRO FuncName:REQ,args:VARARG
      arg equ <invoke FuncName>         ;; construct invoke and function name
      FOR var,<args>                    ;; loop through all arguments
        arg CATSTR arg,<,reparg(var)>   ;; replace quotes and append arg
      ENDM
      arg                               ;; write the invoke macro
      EXITM <eax>                       ;; EAX as the return value
    ENDM
   
    .CODE

align 4

dwtoa proc dwValue:DWORD, lpBuffer:QWORD

    ; -------------------------------------------------------------
    ; convert DWORD to ascii string
    ; dwValue is value to be converted
    ; lpBuffer is the address of the receiving buffer
    ; EXAMPLE:
    ; invoke dwtoa,edx,ADDR buffer
    ;
    ; Uses: eax, ecx, edx.
    ; -------------------------------------------------------------

    push rbx
    push rsi
    push rdi

    mov eax, dwValue
    mov rdi, [lpBuffer]

    or eax,eax
    jnz sign

  zero:
    mov word ptr [rdi],30h
    ret

  sign:
    jns pos
    mov byte ptr [rdi],'-'
    neg eax
    inc rdi

  pos:
    mov ecx, 3435973837
    mov rsi, rdi

    .while (eax > 0)
      mov ebx,eax
      mul ecx
      shr edx, 3
      mov eax,edx
      lea edx,[edx*4+edx]
      add edx,edx
      sub ebx,edx
      add bl,'0'
      mov [rdi],bl
      inc rdi
    .endw

    mov byte ptr [rdi], 0       ; terminate the string

    ; We now have all the digits, but in reverse order.

    .while (rsi < rdi)
      dec rdi
      mov al, [rsi]
      mov ah, [rdi]
      mov [rdi], al
      mov [rsi], ah
      inc rsi
    .endw

    pop rdi
    pop rsi
    pop rbx

    ret

dwtoa endp

StdOut64 proc FRAME lpszText:QWORD

    LOCAL hOutPut  :QWORD
    LOCAL bWritten :DWORD

    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov hOutPut,rax

mov rsi,lpszText

invoke lstrlen,rsi
mov edi,eax
invoke WriteConsole,hOutPut,rsi,edi,ADDR bWritten,NULL

    mov eax, bWritten
    ret

StdOut64 endp

exchdl proc pRecord:ptr, ulframe:qword, pContext:ptr, x4:ptr

    add qword ptr [r8].CONTEXT.Rip_, 1  ;1=size of "in EAX, DX" opcode
    mov eax, 0  ;0=continue execution?
    ret

exchdl endp

VMwareInstalled proc FRAME:exchdl

    mov eax, 0564D5868h
    mov ebx, 08685D465h
    mov ecx, 10
    mov dx, 05658h
    in eax, dx
    cmp ebx, 564D5868h
    setz al
    movzx eax,al
    ret

VMwareInstalled endp

main proc FRAME uses rbx rsi rdi

local dwWritten:DWORD

    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov rbx,rax
    invoke VMwareInstalled
    .if ( eax )
invoke StdOut64,CStr("Running under VMWare")
print " ",13,10
    .else
invoke StdOut64,CStr("Not Running under VMWare")
print " ",13,10   
.endif

invoke GetPhysicallyInstalledSystemMemory, ADDR totalMem
mov ecx,sizeof(MEMORYSTATUSEX)
xor eax,eax
lea rdi,memStatus
rep stosb
lea rdi,memStatus
mov dword ptr (MEMORYSTATUSEX PTR [rdi]).dwLength,sizeof(MEMORYSTATUSEX)
invoke GlobalMemoryStatusEx, ADDR memStatus
invoke GetProcessMemoryInfo,rv(GetCurrentProcess),ADDR procMem,sizeof(PROCESS_MEMORY_COUNTERS)

print "Physically Installed Ram (KB):     "
mov rax,totalMem
print ustr$(eax)
print " ",13,10

print "Memory Load:                       "
lea rdi,memStatus
mov eax,dword ptr (MEMORYSTATUSEX PTR [rdi]).dwMemoryLoad
print ustr$(eax)
print "%",13,10

print "Total OS Visible Ram (KB):         "
lea rdi,memStatus
mov eax,dword ptr (MEMORYSTATUSEX PTR [rdi]).ullTotalPhys
mov edx,dword ptr (MEMORYSTATUSEX PTR [rdi]).ullTotalPhys+4
mov ebx,1024
div ebx
print ustr$(eax)
print " ",13,10

print "Total Available Physical Ram (KB): "
lea rdi,memStatus
mov eax,dword ptr (MEMORYSTATUSEX PTR [rdi]).ullAvailPhys
xor edx,edx
mov ebx,1024
div ebx
print ustr$(eax)
print " ",13,10

print "Page Fault Count:                  "
lea rdi,procMem
mov eax,dword ptr (PROCESS_MEMORY_COUNTERS PTR [rdi]).PageFaultCount
print ustr$(eax)
print " ",13,10

    ret

main endp

mainCRTStartup proc FRAME
    invoke main
    invoke ExitProcess, eax
mainCRTStartup endp

    END mainCRTStartup


johnsa

In addition the updated assemble/link details at the top allow VS2010 to debug the app perfectly with devenv.exe win64_5.exe /debugexe ...

johnsa

Small bug fix..



;--- Win64 console application with exception handler, uses WinInc v2+
;--- assemble: jwasm -c -win64 -Zp8 Win64_5.asm
;--- link: link /subsystem:console /Libpath:\WinInc\Lib64 Win64_5.obj

;--- UPDATE (Must ensure you have latest WinInc, PellesC, run POLIB as per details to generate Lib64 in WinInc):
;--- assemble: jwasm -c -Zi  -Zd -Zf -win64 -Zp8 Win64_5.asm
;--- link:     link /subsystem:console /debug /pdb:win64_5.pdb /Libpath:"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib\x64" /Libpath:"c:\jwasm\wininc\lib64" /Libpath:"c:\masm32\lib" win64_5.obj

option win64:1
option casemap:none
    option frame:auto
.mmx
.xmm

    .nolist
    .nocref
WIN32_LEAN_AND_MEAN equ 1
    include ..\WinInc\Include\windows.inc
    .list
    .cref

include ..\WinInc\Include\shellapi.inc

includelib msvcrt.lib

externdef printf : near
externdef kbhit  : near
externdef strlen : near


    includelib <kernel32.lib>
    includelib <gdi32.lib>
    includelib <user32.lib>
includelib <shell32.lib>

PROCESS_MEMORY_COUNTERS STRUCT
  dwLength       DWORD ?
  PageFaultCount DWORD ?
  PeakWorkingSetSize dq ?
  WorkingSetSize dq ?
  QuotaPeakPagedPoolUsage dq ?
  QuotaPagedPoolUsage dq ?
  QuotaPeakNonPagedPoolUsage dq ?
  QuotaNonPagedPoolUsage dq ?
  PagefileUsage dq ?
  PeakPagefileUsage dq ?
PROCESS_MEMORY_COUNTERS ENDS

StdOut64 proto lpszText:QWORD

dwtoa proto :DWORD, :QWORD

GetPhysicallyInstalledSystemMemory PROTO :QWORD
K32GetProcessMemoryInfo PROTO :DWORD, :DWORD, :DWORD
GetProcessMemoryInfo EQU <K32GetProcessMemoryInfo>

   


  ; -----------------------------------------------------------
  ; This macro replaces quoted text with a DATA section OFFSET
  ; and returns it in ADDR "name" format. It is used by other
  ; macros that handle optional quoted text as a parameter.
  ; -----------------------------------------------------------
    reparg MACRO arg
      LOCAL nustr
        quot SUBSTR <arg>,1,1
      IFIDN quot,<">            ;; if 1st char = "
        .data
          nustr db arg,0        ;; write arg to .DATA section
        .code
        EXITM <ADDR nustr>      ;; append name to ADDR operator
      ELSE
        EXITM <ADDR arg>             ;; else return arg
      ENDIF
    ENDM

    print MACRO arg1:REQ,varname:VARARG      ;; display zero terminated string
        invoke StdOut64,reparg(arg1)
      IFNB <varname>
        invoke StdOut64,CStr(varname)
      ENDIF
    ENDM

      ustr$ MACRO DDvalue   ;; unsigned integer from string
        LOCAL rvstring
        .data
          rvstring db 20 dup (0)
        align 4
        .code
        invoke dwtoa,DDvalue,ADDR rvstring
;        invoke crt__ultoa,DDvalue,ADDR rvstring,10
        EXITM <OFFSET rvstring>
      ENDM
         
.data?

memStatus MEMORYSTATUSEX <?>
procMem PROCESS_MEMORY_COUNTERS <?>
totalMem dq ?
     
;--- CStr(): macro function to simplify defining a string

CStr macro Text:VARARG
local szText
    .const
szText  db Text,0
    .code
    exitm <offset szText>
endm

  ; ------------------------------------------------
  ; Function return value version of the above macro
  ; ------------------------------------------------
    rv MACRO FuncName:REQ,args:VARARG
      arg equ <invoke FuncName>         ;; construct invoke and function name
      FOR var,<args>                    ;; loop through all arguments
        arg CATSTR arg,<,reparg(var)>   ;; replace quotes and append arg
      ENDM
      arg                               ;; write the invoke macro
      EXITM <eax>                       ;; EAX as the return value
    ENDM
   
    .CODE

align 4

dwtoa proc dwValue:DWORD, lpBuffer:QWORD

    ; -------------------------------------------------------------
    ; convert DWORD to ascii string
    ; dwValue is value to be converted
    ; lpBuffer is the address of the receiving buffer
    ; EXAMPLE:
    ; invoke dwtoa,edx,ADDR buffer
    ;
    ; Uses: eax, ecx, edx.
    ; -------------------------------------------------------------

    push rbx
    push rsi
    push rdi

    mov eax, dwValue
    mov rdi, [lpBuffer]

    or eax,eax
    jnz sign

  zero:
    mov word ptr [rdi],30h
    ret

  sign:
    jns pos
    mov byte ptr [rdi],'-'
    neg eax
    inc rdi

  pos:
    mov ecx, 3435973837
    mov rsi, rdi

    .while (eax > 0)
      mov ebx,eax
      mul ecx
      shr edx, 3
      mov eax,edx
      lea edx,[edx*4+edx]
      add edx,edx
      sub ebx,edx
      add bl,'0'
      mov [rdi],bl
      inc rdi
    .endw

    mov byte ptr [rdi], 0       ; terminate the string

    ; We now have all the digits, but in reverse order.

    .while (rsi < rdi)
      dec rdi
      mov al, [rsi]
      mov ah, [rdi]
      mov [rdi], al
      mov [rsi], ah
      inc rsi
    .endw

    pop rdi
    pop rsi
    pop rbx

    ret

dwtoa endp

StdOut64 proc FRAME lpszText:QWORD

    LOCAL hOutPut  :QWORD
    LOCAL bWritten :DWORD

    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov hOutPut,rax

mov rsi,lpszText

invoke lstrlen,rsi
mov edi,eax
invoke WriteConsole,hOutPut,rsi,edi,ADDR bWritten,NULL

    mov eax, bWritten
    ret

StdOut64 endp

exchdl proc pRecord:ptr, ulframe:qword, pContext:ptr, x4:ptr

    add qword ptr [r8].CONTEXT.Rip_, 1  ;1=size of "in EAX, DX" opcode
    mov eax, 0  ;0=continue execution?
    ret

exchdl endp

VMwareInstalled proc FRAME:exchdl

    mov eax, 0564D5868h
    mov ebx, 08685D465h
    mov ecx, 10
    mov dx, 05658h
    in eax, dx
    cmp ebx, 564D5868h
    setz al
    movzx eax,al
    ret

VMwareInstalled endp

main proc FRAME uses rbx rsi rdi

local dwWritten:DWORD

    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov rbx,rax
    invoke VMwareInstalled
    .if ( eax )
invoke StdOut64,CStr("Running under VMWare")
print " ",13,10
    .else
invoke StdOut64,CStr("Not Running under VMWare")
print " ",13,10   
.endif

invoke GetPhysicallyInstalledSystemMemory, ADDR totalMem
mov ecx,sizeof(MEMORYSTATUSEX)
xor eax,eax
lea rdi,memStatus
rep stosb
lea rdi,memStatus
mov dword ptr (MEMORYSTATUSEX PTR [rdi]).dwLength,sizeof(MEMORYSTATUSEX)
invoke GlobalMemoryStatusEx, ADDR memStatus
invoke GetProcessMemoryInfo,rv(GetCurrentProcess),ADDR procMem,sizeof(PROCESS_MEMORY_COUNTERS)

print "Physically Installed Ram (KB):     "
mov rax,totalMem
print ustr$(eax)
print " ",13,10

print "Memory Load:                       "
lea rdi,memStatus
mov eax,dword ptr (MEMORYSTATUSEX PTR [rdi]).dwMemoryLoad
print ustr$(eax)
print "%",13,10

print "Total OS Visible Ram (KB):         "
lea rdi,memStatus
mov rax,(MEMORYSTATUSEX PTR [rdi]).ullTotalPhys
xor rdx,rdx
mov rbx,1024
div rbx
print ustr$(eax)
print " ",13,10

print "Total Available Physical Ram (KB): "
lea rdi,memStatus
mov rax,(MEMORYSTATUSEX PTR [rdi]).ullAvailPhys
xor rdx,rdx
mov rbx,1024
div rbx
print ustr$(eax)
print " ",13,10

print "Page Fault Count:                  "
lea rdi,procMem
mov eax,dword ptr (PROCESS_MEMORY_COUNTERS PTR [rdi]).PageFaultCount
print ustr$(eax)
print " ",13,10

    ret

main endp

mainCRTStartup proc FRAME
    invoke main
    invoke ExitProcess, eax
mainCRTStartup endp

    END mainCRTStartup