News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Examples for Win64 Iczelion tutorial

Started by Mikl__, April 30, 2015, 03:14:46 PM

Previous topic - Next topic

Mikl__

Win x64 Tutorial #38r: Processing of mouse and keyboard messages
bat-file cls
set masm64_path=\masm64\
set filename=%1
del %filename%.exe
%masm64_path%bin\ml64 /Cp /c /I"%masm64_path%Include" %filename%.asm || exit
%masm64_path%bin\link /SUBSYSTEM:CONSOLE /LIBPATH:"%masm64_path%Lib" ^
/entry:WinMain %filename%.obj /LARGEADDRESSAWARE:NO ^
/ALIGN:16 /BASE:0x400000 /STUB:%masm64_path%\bin\stubby.exe || exit
del %filename%.obj
asm-fileinclude win64a.inc

MAXSCREENX = 80
MAXSCREENY = 25
buffersize = 100
.code
WinMain proc
local ConsoleWindow:SMALL_RECT
local cci:CONSOLE_CURSOR_INFO
local BUFF[buffersize]:byte
local result:qword
local fdwSaveOldMode:qword
push rbp
mov ebp,esp
sub esp,(28h+sizeof SMALL_RECT+sizeof CONSOLE_CURSOR_INFO+buffersize+\
2*8+15)and(-16)
xor ebx,ebx
; initialization of the console
call FreeConsole
        call AllocConsole
; to receive input handle
        mov ecx,STD_INPUT_HANDLE
        call GetStdHandle
        mov hIn,eax
; to receive output handle
        mov ecx,STD_OUTPUT_HANDLE
        call GetStdHandle
        mov hOut,eax
        mov ecx,eax ;hOut
call GetLargestConsoleWindowSize
; eax return in 31-16 bits: dwCoord.y
;               15-00 bits: dwCoord.x

        lea r8d,ConsoleWindow ; lpConsoleWindow
mov [r8],ebx
; ConsoleWindow.Left = 0 ConsoleWindow.Top = 0

sub ax, MAXSCREENX
sbb edx, edx
and ax, dx
add ax, MAXSCREENX-1
mov [r8+SMALL_RECT.Right],ax

shr eax, 16
sub eax, MAXSCREENY
sbb edx, edx
and eax, edx
add eax, MAXSCREENY-1
mov [r8+SMALL_RECT.Bottom],ax
mov edx,TRUE ; bAbsolute
mov ecx,hOut ; hConsoleOutput
call SetConsoleWindowInfo

mov edx,MAXSCREENY*10000h+MAXSCREENX;dwCoord
mov ecx,hOut ; hConsoleOutput
call SetConsoleScreenBufferSize ;establish the new size of console window
mov ecx,offset NameConsole
call SetConsoleTitle
;hide cursor----------------------------------------
lea edx,cci ; lpConsoleCursorInfo
mov ecx,hOut ; hConsoleOutput
call GetConsoleCursorInfo
lea edx,cci ; lpConsoleCursorInfo
mov [rdx+CONSOLE_CURSOR_INFO.bVisible],ebx;FALSE
mov ecx,hOut ; hConsoleOutput
call SetConsoleCursorInfo
;------------------------------------------------------
;keep the current mode of input for future restoration at an exit from the program
lea edx,fdwSaveOldMode
mov ecx,hIn
        call GetConsoleMode
;include input events from a mouse and a window
mov edx,ENABLE_WINDOW_INPUT or ENABLE_MOUSE_INPUT
mov ecx,hIn
call SetConsoleMode
;-------------------------------------------------------
mov [rsp+20h],rbx
lea r9d,result ;&result
        mov r8d,sizeof s00
mov edx,offset s00;'For an exit from the program press "cross" in the right top corner'
mov ecx,hOut
        call WriteConsole
; establish the event handler
mov edx,TRUE
mov ecx,offset CtrlHandler
call SetConsoleCtrlHandler
; procedure with an operation cycle of messages
call inputcons
; exit
; disconnect the event handler
        mov edx,FALSE
mov ecx,offset CtrlHandler
call SetConsoleCtrlHandler
; restore the current mode of input
        mov rdx,fdwSaveOldMode
mov ecx,hIn
        call SetConsoleMode
; release descriptors
mov ecx,hOut
call CloseHandle
mov ecx,hIn
call CloseHandle
; switch off the console
        call FreeConsole
xor ecx,ecx
        call ExitProcess
WinMain endp

; handler of critical console events
CtrlHandler proc fdwCtrlType:qword
sub esp,28h
cmp ecx,CTRL_C_EVENT
jz beep
cmp ecx,CTRL_BREAK_EVENT
jz beep
cmp ecx,CTRL_CLOSE_EVENT
jz beep
cmp ecx,CTRL_LOGOFF_EVENT
jz false
cmp ecx,CTRL_SHUTDOWN_EVENT
jz false
; another code
false:  xor eax,eax
jmp bye_bye
beep:   mov edx,1000
mov ecx,1000
        call Beep
mov eax,TRUE
bye_bye:add esp,28h
retn
CtrlHandler endp

inputcons proc
local result:qword
local MOUSE_KEY:INPUT_RECORD
local BUFF[buffersize]:byte

;Cycle of reading and processing of events of input
;Expectation of events
push rbp
mov ebp,esp
sub esp,(28h+buffersize+sizeof INPUT_RECORD+8+15)and(-16)
loo: lea r9d,result;number of the read symbols
mov r8d,1     ;reading buffer size
lea edx,MOUSE_KEY;the buffer in which we read
mov ecx,hIn   ;input buffer descriptor
call ReadConsoleInput
; check correctness of performance of function
or eax,eax
jnz no_err
; error message
        mov [rsp+20h],rbx
lea r9d,result ;&result
        mov r8d,sizeof s01
mov edx,offset s01  ;"Error input!"
mov ecx,hOut
        call WriteConsole
mov ecx,5000
call Sleep
leave
ret

no_err: lea eax,result
mov [rsp+20h],rax;number of the read symbols
mov r9d,1*10000h+0;Y=1 X=0 coordinates of the first symbol - we will begin with
;the first cell of the second line (on the first line the inscription "For an Exit from the
;Program Press "Cross" in the Right Top Corner")
mov r8d,MAXSCREENX*(MAXSCREENY-1);fill area of the screen buffer
;80 ї 24 ёшьтюыют эєы ьш
xor edx,edx ;0 is symbol with which fill
mov ecx,hOut ;descriptor of the screen buffer
call FillConsoleOutputCharacter;before a conclusion of each message we clear the screen
mov edx,10*10000h+0 ;Y=10 X=0
        mov ecx,hOut
        call SetConsoleCursorPosition
;send events to the corresponding handlers
lea eax,MOUSE_KEY
cmp [rax+INPUT_RECORD.EventType],KEY_EVENT;1
;keyboard input
jz KeyEventProc
        cmp [rax+INPUT_RECORD.EventType],MOUSE_EVENT;2
;input from a mouse
jz MouseEventProc
        cmp [rax+INPUT_RECORD.EventType],WINDOW_BUFFER_SIZE_EVENT;4
;change of the size of the screen buffer
jz      ResizeEventProc
cmp [rax+INPUT_RECORD.EventType],FOCUS_EVENT;16
;ignoring of events of focus
jz      loo
cmp [rax+INPUT_RECORD.EventType],MENU_EVENT;8
;ignoring of events of the menu
        jz      loo
        mov [rsp+20h],rbx
lea r9d,result ;&result
        mov r8d,sizeof s15
mov edx,offset s15  ;"unknown event type"
mov ecx,hOut
        call WriteConsole
        jmp     loo
ResizeEventProc:
movzx r9d,MOUSE_KEY.WindowBufferSizeEvent.dwSize.y
        movzx r8d,MOUSE_KEY.WindowBufferSizeEvent.dwSize.x
        mov edx,offset xy2       ;'Size of console: Right=%d, Bottom=%d'
lea ecx,BUFF
call wsprintf
mov [rsp+20h],rbx
lea r9d,result ;&result
        mov r8d,eax
lea edx,BUFF
mov ecx,hOut
        call WriteConsole
mov ecx,5000
call Sleep
        jmp     loo
; check the control keys
KeyEventProc:
ok1:    test [rax+INPUT_RECORD.KeyEvent.dwControlKeyState],CAPSLOCK_ON;80h
jnz dal0
cmp [rax+INPUT_RECORD.KeyEvent.dwControlKeyState],ENHANCED_KEY;100h
jz dal1
test [rax+INPUT_RECORD.KeyEvent.dwControlKeyState],LEFT_ALT_PRESSED or RIGHT_ALT_PRESSED;2 or 1
jnz dal2
test [rax+INPUT_RECORD.KeyEvent.dwControlKeyState],LEFT_CTRL_PRESSED or RIGHT_CTRL_PRESSED;8 or 4
jnz dal4
cmp [rax+INPUT_RECORD.KeyEvent.dwControlKeyState],SHIFT_PRESSED;10h
jz dal6
test [rax+INPUT_RECORD.KeyEvent.dwControlKeyState],NUMLOCK_ON;20h
jnz dal7
cmp [rax+INPUT_RECORD.KeyEvent.dwControlKeyState],SCROLLLOCK_ON;40h
jnz us_key
dal8:; SCROLL LOCK
mov [rsp+20h],rbx;0
        lea r9d,result
mov r8d,sizeof s11
mov edx,offset s11 ;"SCROLLLOCK",10
jmp exit1
MouseEventProc:
cmp MOUSE_KEY.MouseEvent.dwEventFlags,DOUBLE_CLICK
jz dalm0
cmp MOUSE_KEY.MouseEvent.dwEventFlags,MOUSE_MOVED
jz dalm1
        cmp MOUSE_KEY.MouseEvent.dwEventFlags,MOUSE_WHEELED
jz dalm2
cmp MOUSE_KEY.MouseEvent.dwButtonState,FROM_LEFT_1ST_BUTTON_PRESSED
jz dalm3
dalm4:  cmp MOUSE_KEY.MouseEvent.dwButtonState,RIGHTMOST_BUTTON_PRESSED
jnz loo
        mov [rsp+20h],rbx;0
        lea r9d,result             ;&result
mov r8d,sizeof s07
mov edx,offset s07 ;"Right mouse click"
jmp exit2
dalm0:  mov [rsp+20h],rbx;0
        lea r9d,result             ;&result
mov r8d,sizeof s03
mov edx,offset s03      ;"Double click"
jmp exit2
dalm2:; ъюыхёшъю ь√°ш
        mov [rsp+20h],rbx;0
        lea r9d,result             ;&result
        mov r8d,sizeof s02
mov edx,offset s02      ;"Wheel was rolled"
jmp exit2
dalm3:  mov [rsp+20h],rbx;0
        lea r9d,result             ;&result
        mov r8d,sizeof s14
mov edx,offset s14      ;"Left mouse click"
jmp exit2
dalm1: movzx r9d,MOUSE_KEY.MouseEvent.dwMousePosition.y
        movzx r8d,MOUSE_KEY.MouseEvent.dwMousePosition.x
        mov edx,offset xy1       ;'Location of cursor: X=%d, Y=%d'
lea ecx,BUFF
call wsprintf
        jmp exit3
dal0:;CAPSLOCK
mov [rsp+20h],rbx;0
        lea r9d,result             ;&result
        mov r8d,sizeof s09
mov edx,offset s09      ;"CAPSLOCK",10
jmp exit1
dal2:; ыхт√щ ALT
        mov [rsp+20h],rbx;0
        lea r9d,result ;&result
mov r8d,sizeof s05
mov edx,offset s05      ;"ALT"
        jmp exit1
dal4:; ыхт√щ CTRL
mov [rsp+20h],rbx;0
        lea r9d,result ;&result
mov r8d,sizeof s04
mov edx,offset s04       ;"CTRL"
jmp exit1
dal6:; SHIFT
mov [rsp+20h],rbx;0
        lea r9d,result ;&result
mov r8d,sizeof s06
mov edx,offset s06      ;"SHIFT"
jmp exit1
dal7:; NUM LOCK
mov [rsp+20h],rbx;0
        lea r9d,result ;&result
mov r8d,sizeof s10
mov edx,offset s10      ;"NUMLOCK"
exit1: mov ecx,hOut
        call WriteConsole
; usual keys
us_key: movzx eax,MOUSE_KEY.KeyEvent.AsciiChar
cmp al,32
jb bel
; symbol output
mov r8d,eax
mov edx,offset fc      ;"Character '%c'",0
jmp exit4
bel: cmp al,0
jnz upr
;call these keys functional for them ASCII code it is equal to 0
        movzx r8d,MOUSE_KEY.KeyEvent.wVirtualKeyCode
mov edx,offset s13     ;"Function key (virtual code) %d",0
jmp exit4
upr:    mov r8d,eax
mov edx,offset s08     ;"Code %d ",0
jmp exit4
dal1:; enhanced keyboard
movzx r8d,MOUSE_KEY.KeyEvent.wVirtualKeyCode
mov edx,offset s12     ;"Enhanced key (virtual code) %d",0
exit4: lea ecx,BUFF
call wsprintf
exit3:  mov [rsp+20h],rbx;0
lea r9d,result ;&result
mov r8d,eax
lea edx,BUFF
exit2:
mov ecx,hOut
        call WriteConsole
        jmp loo
inputcons endp
;------------------------------------------------------
NameConsole db 'Processing of mouse and keyboard messages',0
s00 db 'For an exit from the program press "cross" in the right top corner'
s01 db "Error input!"
s02 db "Wheel was rolled"
s03 db "Double click"
s04 db "CTRL",10
s05 db "ALT",10
s06 db "SHIFT",10
s07 db "Right mouse click"
s08 db "Code %d ",0
s09 db "CAPSLOCK",10
s10 db "NUMLOCK",10
s11 db "SCROLLLOCK",10
s12 db "Enhanced key (virtual code) %d",0
s13 db "Function key (virtual code) %d",0
s14 db "Left mouse click"
s15 db "Unknown event type"
s16 db "Change of the sizes of the screen buffer"
fc db "Character '%c'",0
xy1 db 'Location of cursor: X=%d, Y=%d',0
xy2 db 'Size of console: Right=%d, Bottom=%d',0
hIn dd ?
hOut dd ?
end

Mikl__

End of the second part of the Win64 tutorial

avcaballero

Hi Mikl__, as a constructive criticism: why don't you put everything into a webpage? Maybe it's a bit hard to follow everything in a forum thread. I have discovered a free hoster that don't seems to be bad. Don't know if anybody knows any other.

Mikl__

¡Hola, Alfonso! Gracias por la ayuda y la crítica constructiva...

Mikl__

#154
Win x64 Tutorial #38p: the values returned by the GetStdHandle function
I have decided to look by means of a value debugger which are returned by the GetStdHandle function. To the surprise I have found these values are constants.

||Windows Seven x64|Windows XP|Windows 98
|hInput|3|3|8
|hOutput=hInput+4|7|7|0Ch
|hError=hOutput+4|0Bh|0Bh|10h
Maybe it is worth using the fixed values, but not to cause every time the GetStdHandle function?
bat-filecls
set masm64_path=\masm64\
set filename=%1
del %filename%.exe
%masm64_path%bin\ml64 /Cp /c /I"%masm64_path%Include" %filename%.asm || exit
%masm64_path%bin\link /SUBSYSTEM:CONSOLE /LIBPATH:"%masm64_path%Lib" ^
/entry:WinMain %filename%.obj /LARGEADDRESSAWARE:NO ^
/ALIGN:16 /BASE:0x400000 /STUB:%masm64_path%\bin\stubby.exe || exit
del %filename%.obj
asm-fileinclude win64a.inc
buffersize = 100
.code
WinMain proc
local hIn:qword
local hOut:qword
local hError:qword
local BUFF[buffersize]:byte
push rbp
mov ebp,esp
sub esp,(28h+buffersize+3*8+15)and(-16)
; to receive input handle
        mov ecx,STD_INPUT_HANDLE
        call GetStdHandle
        mov hIn,rax
; to receive output handle
        mov ecx,STD_OUTPUT_HANDLE
        call GetStdHandle
        mov hOut,rax
; to receive error handle
        mov ecx,STD_ERROR_HANDLE
        call GetStdHandle
        mov hError,rax
;-------------------------------------------------------
mov [rsp+20h],rax
mov r9,hIn
        mov r8,hOut
        mov edx,offset format
lea ecx,BUFF
call wsprintf
xor r9d,r9d
        mov r8d,offset NameConsole
Lea edx,BUFF
xor ecx,ecx
        call MessageBox
; release descriptors
mov rcx,hOut
call CloseHandle
mov rcx,hIn
call CloseHandle
mov rcx,hError
call CloseHandle
; switch off the console
        call FreeConsole
xor ecx,ecx
        call ExitProcess
WinMain endp
;------------------------------------------------------
NameConsole db 'Values of stdinput, stdoutput, stderror',0
format db 'StdOutput=%016Xh',10,'StdInput=%016Xh',10,'StdError=%016Xh',0
end

Mikl__

#155
Win x64: Tiny IDE
I create the masm64 catalog, in this catalog I create the subdirectories bin, include, lib, examples.
Bin catalog contents:

  • asm2.bat
  • cvtres.exe
  • link.exe
  • ml64.exe
  • msobj80.dll
  • mspdb80.dll
  • msvcp80.dll
  • msvcp90.dll
  • msvcr80.dll
  • msvcr90.dll
  • rc.exe
  • rc.GID
  • rc.hlp
  • rcdll.dll
  • stubby.exe
asm2.bat contents:@echo off
cls
if exist errors.txt del errors.txt
if exist %1.exe del %1.exe
if exist %1.obj del %1.obj
\masm64\bin\ml64 /Cp /c /I\masm64\include %1.asm >> errors.txt
if errorlevel 1 goto errasm
\masm64\bin\link /LIBPATH:\masm64\lib /SUBSYSTEM:WINDOWS  ^
/entry:WinMain /LARGEADDRESSAWARE:NO /ALIGN:16 /SECTION:.text,W ^
/BASE:0x400000 /STUB:\masm64\bin\stubby.exe %1.obj >> errors.txt
if errorlevel 1 goto errasm
del %1.obj
del errors.txt
if errorlevel 0 exit
:errasm
\masm64\topgun.exe errors.txt
In the masm64 catalog from the masm32 catalog I copy qeditor.exe and topgun.exe. I create the menus.ini file[&x64]
Compile && Link,\masm64\bin\asm2.bat "{b}"
-
&Run Program,"{b}.exe"
-
&Debbuging,F:\x64_dbg\x64_dbg.exe "{b}.exe"

Alex81524

Hi!  How to get your assembling? With kind regards

Mikl__

#157
Hi, Alex81524!
there are asm-files with bat-files in pages of this topic. On the site http://dsmhelp.narod.ru/environment.htm you can find a set of lib- and inc-files to create 64-bit applications in assembler, as well as a lot of useful macros. Sorry, but the forum rules do not allow me to attach the zip-file size of 4 MB with lib- and inc- files. You can easily find lib- and inc-files  in my attach-files.
ml64.exe can be obtained for free (please read and obey EULA) in the Windows Server 2003 DDK and the Windows Server 2003 R2 Platform SDK.

In the DDK, look in C:\WINDDK\3790.1830\bin\win64\x86\amd64\
In the SDK, look in C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin\win64\x86\AMD64
With kind regards

Mikl__

#158
Tiny MessageBox x64 in FASM
Size of exe-file is 298 bytes
format binary as 'exe'
include 'win64a.inc'

struc dbs [data]
{
  common
  . db data
  .size = $ - .
}

IMAGE_DOS_SIGNATURE equ 5A4Dh
IMAGE_NT_SIGNATURE equ 00004550h
PROCESSOR_AMD_X8664 equ 8664h
IMAGE_SCN_CNT_CODE equ 00000020h
IMAGE_SCN_MEM_WRITE equ 80000000h
IMAGE_SCN_MEM_READ equ 40000000h
IMAGE_SCN_CNT_INITIALIZED_DATA equ 00000040h
IMAGE_SUBSYSTEM_WINDOWS_GUI equ 2
IMAGE_NT_OPTIONAL_HDR64_MAGIC equ 20Bh
IMAGE_FILE_RELOCS_STRIPPED equ 1
IMAGE_FILE_EXECUTABLE_IMAGE equ 2
IMAGE_BASE equ 0x400000
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE equ 8000h
use64
org 0
;--------DOS-stub-------------------------------
Signature dw IMAGE_DOS_SIGNATURE,0
;-------PE-header--------------------------------------------------
ntHeader dd IMAGE_NT_SIGNATURE;'PE'
;image_header----
Machine dw PROCESSOR_AMD_X8664;CPU Type
Count_of_section dw 0;Number of sections
TimeStump dd 0;Information about the time when the PE-file was compiled
Symbol_table_offset dd 0;A pointer to the size of debug information
Symbol_table_count dd 0;A pointer to the COFF symbol table-PE-format
Size_of_optional_header dw begin-optional_header;The size of optional header
Characteristics dw IMAGE_FILE_RELOCS_STRIPPED or \
IMAGE_FILE_EXECUTABLE_IMAGE;file attributes
;-------Standard field NT
optional_header:
Magic_optional_header dw IMAGE_NT_OPTIONAL_HDR64_MAGIC;Status Display File
Linker_version_major_and_minor dw 9;Contain the linker version that created the file.
Size_of_code dd 0;The total size of the code sections
Size_of_init_data dd 0x70;The total size of initialized data
Size_of_uninit_data dd 0;The total size of the uninitialized data
entry_point dd start
base_of_code dd begin
;------Additional fields NT-----------------------------------------------
image_base dq IMAGE_BASE
section_alignment dd 4
file_alignment dd ntHeader
OS_version_major_minor dw 5,2
image_version_major_minor dd 0
subsystem_version_major_minor dw 5,2
Win32_version dd 0
size_of_image dd end_import
size_of_header dd begin
checksum dd 0
subsystem dw IMAGE_SUBSYSTEM_WINDOWS_GUI
DLL_flag dw IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
Stack_allocation dq 0x100000
Stack_commit dq 0x1000
Heap_allocation dq 0x100000
Heap_commit dq 0x1000
loader_flag dd 0
number_of_dirs dd (begin-export_RVA_size)/8
export_RVA_size dq 0
import_RVA_size dd _import,end_import-import
;--------code and data-----------------------------------------
begin:
MsgBoxText dbs 'Win64 Assembly is Great!',0
MsgCaption db "Win64 Iczelion's lesson #2: MessageBox",0
start:
push rbp; <-- not sub rsp,28h
xor ecx,ecx
mov edx,MsgBoxText+IMAGE_BASE
lea r8d,[rdx+MsgBoxText.size]; <-- not mov r8d,offset MsgCaption
xor r9d,r9d; MB_OK
call [MessageBox]
pop rbp
retn
;---------import---------------------------------------
Import_Table:
user32_table:
MessageBox  dq _MessageBox
_import:
dd 0,0,0,user32_dll,user32_table,0
user32_dll db "user32",0,0 ;<-- not "user32.dll"
dw 0
_MessageBox db 0,0,"MessageBoxA"
end_import:

avcaballero


shankle

Thank you very much for these 64-bit tutorials.

Any chance of getting one that uses "FindFirstFile and Win32_Find_date??
I am having a problem with lpFileName.

hutch--

Jack,

This is 32 bit MASM format but it shows the basics of how to use these APIs. The "lpszFileName" is simply the address of the file you want to test. Check in 64 bit if EAX needs to be changed to RAX based on the WIN32_FIND_DATA structure.


exist proc lpszFileName:DWORD

    LOCAL wfd :WIN32_FIND_DATA

    invoke FindFirstFile,lpszFileName,ADDR wfd
    .if eax == INVALID_HANDLE_VALUE
      mov eax, 0                    ; 0 = NOT exist
    .else
      invoke FindClose, eax
      mov eax, 1                    ; 1 = exist
    .endif

    ret

exist endp

shankle

Thanks Hutch for responding.
Windows 7 pro 64-bit, 2 SSD drives.
MASM32 is on the 2nd SSD as E:
I have no idea what the address is or if it is stationary.
I need to read this file not in the normal way.


hutch--

I don't get what you are doing Jack, normally a file has a name if its a disk file. Tell us what you are trying to do and it may make a bit more sense.

shankle

I'm trying to do my own Backup file.
This includes Windows 7 and the boot file on the C: drive.
And Masm32 on the 2nd drive.