Hello,
I want to share my source code written for ML64.EXE (MASM64) assembler.
Build.bat file content:
@echo off
ml64.exe prog4.asm /link /entry:Main /subsystem:windows /defaultlib:"kernel32.Lib" /defaultlib:"user32.Lib" /defaultlib:"Gdi32.Lib" /defaultlib:"gdiplus.lib" /LARGEADDRESSAWARE:NO
pause
My source code:
;(c) 2018 Dawid_vx7 - http://vx7.pl/
;Assembler MASM64 (ML64.EXE)
;Take screenshot and save to .jpg image file
extrn BitBlt : proc
extrn CreateCompatibleBitmap : proc
extrn CreateCompatibleDC : proc
extrn DeleteDC : proc
extrn ExitProcess : proc
extrn GdipCreateBitmapFromHBITMAP : proc
extrn GdipDisposeImage : proc
extrn GdipSaveImageToFile : proc
extrn GdiplusShutdown : proc
extrn GdiplusStartup : proc
extrn GetDC : proc
extrn GetDeviceCaps : proc
extrn MultiByteToWideChar : proc
extrn SelectObject : proc
GdiplusStartupInput struct
GdiplusVersion dd ?
DebugEventCallback dd ?
SuppressBackgroundThread dd ?
SuppressExternalCodecs dd ?
GdiplusStartupInput ends
ImageEncoderJPEG_GUID struct
Data1 dd 0
Data2 dw 0
Data3 dw 0
Data4 db 8 dup(0)
ImageEncoderJPEG_GUID ends
.const
HORZRES equ 8
VERTRES equ 10
SRCCOPY equ 00CC0020h
GDIP_IMAGE_JPG equ 1
.data
GDIPlusToken dq 0
gdipsi GdiplusStartupInput <1,0,0,0>
hScreenDC dq 0
hMemoryDC dq 0
screenWidth dq 0
screenHeight dq 0
hScreenBitmap dq 0
hScreenOldBitmap dq 0
pPicture dq 0
szTempJPGUnicode dw 255 dup (0)
imageGUID ImageEncoderJPEG_GUID <0557CF401h,01A04h,011D3h,<09Ah,073h,000h,000h,0F8h,01Eh,0F3h,02Eh>>
szTempJPG db "temp.jpg", 0
.code
Main proc
sub rsp, 28h
xor r9, r9
xor r8, r8
mov rdx, offset gdipsi
mov rcx, offset GDIPlusToken
call GdiplusStartup
add rsp, 28h
sub rsp, 28h
xor r9, r9
xor r8, r8
xor rdx, rdx
xor rcx, rcx
call GetDC
add rsp, 28h
mov hScreenDC, rax
sub rsp, 28h
xor r9, r9
xor r8, r8
xor rdx, rdx
mov rcx, hScreenDC
call CreateCompatibleDC
add rsp, 28h
mov hMemoryDC, rax
sub rsp, 28h
xor r9, r9
xor r8, r8
mov rdx, HORZRES
mov rcx, hScreenDC
call GetDeviceCaps
add rsp, 28h
mov screenWidth, rax
sub rsp, 28h
xor r9, r9
xor r8, r8
mov rdx, VERTRES
mov rcx, hScreenDC
call GetDeviceCaps
add rsp, 28h
mov screenHeight, rax
sub rsp, 28h
xor r9, r9
mov r8, screenHeight
mov rdx, screenWidth
mov rcx, hScreenDC
call CreateCompatibleBitmap
add rsp, 28h
mov hScreenBitmap, rax
sub rsp, 28h
xor r9, r9
xor r8, r8
mov rdx, hScreenBitmap
mov rcx, hMemoryDC
call SelectObject
add rsp, 28h
mov hScreenOldBitmap, rax
sub rsp, 48h
mov qword ptr [rsp+40h], SRCCOPY
mov qword ptr [rsp+38h], 0
mov qword ptr [rsp+30h], 0
mov rax, hScreenDC
mov qword ptr [rsp+28h], rax
mov rax, screenHeight
mov qword ptr [rsp+20h], rax
mov r9, screenWidth
xor r8, r8
xor rdx, rdx
mov rcx, hMemoryDC
call BitBlt
add rsp, 48h
sub rsp, 28h
xor r9, r9
xor r8, r8
mov rdx, hScreenOldBitmap
mov rcx, hMemoryDC
call SelectObject
add rsp, 28h
mov hScreenBitmap, rax
sub rsp, 28h
xor r9, r9
xor r8, r8
xor rdx, rdx
mov rcx, hMemoryDC
call DeleteDC
add rsp, 28h
sub rsp, 28h
xor r9, r9
xor r8, r8
xor rdx, rdx
mov rcx, hScreenDC
call DeleteDC
add rsp, 28h
sub rsp, 28h
xor r9, r9
mov r8, offset pPicture
xor rdx, rdx
mov rcx, [hScreenBitmap]
call GdipCreateBitmapFromHBITMAP
add rsp, 28h
sub rsp, 30h
mov qword ptr [rsp+28h], 255
mov rax, offset szTempJPGUnicode
mov qword ptr [rsp+20h], rax
mov r9, -1
mov r8, offset szTempJPG
mov rdx, 0
mov rcx, 0
call MultiByteToWideChar
add rsp, 30h
sub rsp, 28h
xor r9, r9
lea r8d, imageGUID
mov rdx, offset szTempJPGUnicode
mov rcx, pPicture
call GdipSaveImageToFile
add rsp, 28h
sub rsp, 28h
xor r9, r9
xor r8, r8
xor rdx, rdx
mov rcx, pPicture
call GdipDisposeImage
add rsp, 28h
_exit:
sub rsp, 8h
xor rcx, rcx
call ExitProcess
Main endp
end
Hi davef,
Nice work. A small suggestion : you can avoid the multiple sub rsp\add rsp instructions by doing an initial stack allocation taking in account the API MultiByteToWideChar. It has the maximum number of parameters in your code.