Pages

Se afișează postările cu eticheta FASM. Afișați toate postările
Se afișează postările cu eticheta FASM. Afișați toate postările

vineri, 10 aprilie 2026

FASM : mouse crosshair with lines on the window GDI.

For a year now, it keeps hacking me on Windows. And when I am in a bad mood, I turn to complex things. Today, I wanted to see if I could make a functional assembly code with Microsoft's Copilot artificial intelligence and my assembly knowledge with FASM. Here is what resulted.
The program is a Win32 GUI application written in FASM that draws a crosshair (vertical + horizontal line) following the mouse cursor inside a window classic GDI.
1. Window Setup
The app starts by registering a Win32 window class (WNDCLASSEX) and creating a standard overlapped window. Nothing unusual here — just the classic Win32 boilerplate.
2. Message Loop
The program enters the main loop:
  • GetMessage
  • TranslateMessage
  • DispatchMessage
This keeps the window responsive and forwards events to the window procedure.
3. Tracking the Mouse
Whenever the mouse moves inside the window, Windows sends a WM_MOUSEMOVE message. The program extracts the X and Y coordinates from lParam:
  • LOWORD(lParam) → X
  • HIWORD(lParam) → Y
These values are stored and the window is invalidated so it can be repainted.
4. Drawing the Crosshair (GDI)
All drawing happens inside WM_PAINT using classic GDI:
  • MoveToEx
  • LineTo
  • Ellipse
  • TextOut
  • FillRect
The steps are:
  • Clear the client area
  • Get the window’s current size (GetClientRect)
  • Draw a vertical line at the mouse’s X position
  • Draw a horizontal line at the mouse’s Y position
  • Draw a small circle at the intersection
  • Print the coordinates in the corner
Because the client size is read dynamically, the crosshair always stretches across the entire window — no matter how it’s resized.
See the source code
; mouse_crosshair.asm
format PE GUI 4.0
entry start
include "win32a.inc"

WM_MOUSEMOVE = 0x0200

section '.data' data readable writeable

    szClass db "MouseGraph",0
    szTitle db "Mouse Crosshair Demo",0

    mouseX dd 0
    mouseY dd 0

    fmt    db "X=%d  Y=%d",0
    buffer db 64 dup(0)

    rc  RECT
    ps  PAINTSTRUCT
    wc  WNDCLASSEX
    msg MSG

section '.code' code readable executable

start:
    invoke GetModuleHandle,0
    mov [wc.hInstance],eax

    mov [wc.cbSize],sizeof.WNDCLASSEX
    mov [wc.style],CS_HREDRAW or CS_VREDRAW
    mov [wc.lpfnWndProc],WndProc
    mov [wc.cbClsExtra],0
    mov [wc.cbWndExtra],0
    mov [wc.hIcon],0
    mov [wc.hIconSm],0
    mov [wc.lpszMenuName],0
    mov [wc.lpszClassName],szClass
    mov [wc.hbrBackground],COLOR_WINDOW+1

    invoke LoadCursor,0,IDC_ARROW
    mov [wc.hCursor],eax

    invoke RegisterClassEx,wc

    invoke CreateWindowEx,0,szClass,szTitle,\
           WS_VISIBLE+WS_OVERLAPPEDWINDOW,\
           200,200,800,600,0,0,[wc.hInstance],0

msg_loop:
    invoke GetMessage,msg,0,0,0
    test eax,eax
    jz exit
    invoke TranslateMessage,msg
    invoke DispatchMessage,msg
    jmp msg_loop

exit:
    invoke ExitProcess,0

; ---------------------------------------------------------
proc WndProc hWnd,uMsg,wParam,lParam

    cmp [uMsg],WM_MOUSEMOVE
    je .mouse

    cmp [uMsg],WM_PAINT
    je .paint

    cmp [uMsg],WM_DESTROY
    je .destroy

.def:
    invoke DefWindowProc,[hWnd],[uMsg],[wParam],[lParam]
    ret

; ---------------- WM_MOUSEMOVE ----------------
.mouse:
    mov eax,[lParam]
    and eax,0FFFFh
    mov [mouseX],eax

    mov eax,[lParam]
    shr eax,16
    and eax,0FFFFh
    mov [mouseY],eax

    invoke InvalidateRect,[hWnd],0,TRUE
    ret

; ---------------- WM_PAINT ----------------
.paint:
    invoke BeginPaint,[hWnd],ps
    mov esi,eax ; hdc

    ; clean client
    invoke GetClientRect,[hWnd],rc
    invoke FillRect,esi,rc,COLOR_WINDOW+1

    ; pen red
    invoke CreatePen,PS_SOLID,1,0x0000FF
    mov ebx,eax
    invoke SelectObject,esi,ebx

    ; ---------------- linie verticala (cruce) ----------------
    mov eax,[mouseX]        ; X constant
    mov edx,[rc.bottom]     ; Y max (jos)
    invoke MoveToEx,esi,eax,0,0
    invoke LineTo,esi,eax,edx

    ; ---------------- line  ----------------
    mov eax,[mouseY]        ; Y constant
    mov edx,[rc.right]      ; X max (dreapta)
    invoke MoveToEx,esi,0,eax,0
    invoke LineTo,esi,edx,eax

    ; punct în intersec?ie
    mov eax,[mouseX]
    mov edx,[mouseY]
    invoke Ellipse,esi,eax-4,edx-4,eax+4,edx+4

    ; text coordonate
    invoke wsprintf,buffer,fmt,[mouseX],[mouseY]
    invoke lstrlen,buffer
    invoke TextOut,esi,10,10,buffer,eax

    invoke EndPaint,[hWnd],ps
    ret

; ---------------- WM_DESTROY ----------------
.destroy:
    invoke PostQuitMessage,0
    ret

endp

section '.idata' import data readable
library kernel32,"KERNEL32.DLL",\
        user32,"USER32.DLL",\
        gdi32,"GDI32.DLL"

include "api/kernel32.inc"
include "api/user32.inc"
include "api/gdi32.inc"

News : SASM - SimpleASM has support multiple languages.

... multi-languages for this good assembly editor named SASM - SimpleASM.
SASM (SimpleASM) - simple Open Source crossplatform IDE for NASM, MASM, GAS, FASM assembly languages. SASM has syntax highlighting and debugger. The program works out of the box and is great for beginners to learn assembly language. SASM is translated into Russian, English, Turkish (thanks Ali Goren), Chinese (thanks Ahmed Zetao Yang), German (thanks Sebastian Fischer), Italian (thanks Carlo Dapor), Polish (thanks Krzysztof Rossa), Hebrew (thanks Elian Kamal), Spanish (thanks Mariano Cordoba), Portuguese (thanks alglus), French (thanks Franc Serres), Brazilian Portuguese (thanks williampe99), Japanese (thanks ookatuk). Licensed under the GNU GPL v3.0. Based on the Qt.

miercuri, 18 martie 2026

Tools : FASM-Tutorial source code by Mori-TM.

Today, I found this repo with few basic source code for Flat Assembler (FASM).

duminică, 24 noiembrie 2024

News : Try old design with ascii and assembly language.

The old ASCII design can still be captivating. I used FASM in fedora to create such a design.
Read my article how can be done on my fedora blogger.

miercuri, 20 noiembrie 2024

FASM : simple bootloader source code with menu .

This is the source code with a boot menu and can be tested with qemu emulator.
I need to use the Sonet 3.5 artificial inteligence to search infos and make this source code better, but I learn assembly in the past.
The compile commands of the source code:
mythcat@localhost:~/fasm$ ./fasm.x64
flat assembler  version 1.73.32
...
mythcat@localhost:~/fasm$ ./fasm.x64 bootloader.asm bootloader.bin
flat assembler  version 1.73.32  (16384 kilobytes memory, x64)
2 passes, 512 bytes.
The test with qemu tool:
mythcat@localhost:~/fasm$ qemu-system-x86_64 -drive format=raw,file=bootloader.bin
Let's see the source code:
; Simple Bootloader with Menu for QEMU
; Written in FASM

org 0x7C00

format binary

start:
    ; Clear the screen
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ah, 0x0
    int 0x10

    ; Display the menu
    call display_menu

main_loop:
    ; Wait for key press
    call wait_for_input

    ; Check key pressed
    cmp al, '1'
    je handle_option1
    cmp al, '2'
    je handle_option2

    ; Invalid option, restart
    jmp main_loop

handle_option1:
    ; Option 1 selected
    mov si, option1_msg
    call display_message
    call wait_for_input  ; Wait for any key
    jmp start           ; Return to menu

handle_option2:
    ; Option 2 selected
    mov si, option2_msg
    call display_message
    call wait_for_input  ; Wait for any key
    jmp start           ; Return to menu

display_menu:
    ; Display the menu
    mov si, menu
    call print_string
    ret

wait_for_input:
    ; Wait for a key press
    xor ax, ax
    int 0x16
    ret

print_string:
    ; Print string at DS:SI
    mov ah, 0x0E
@@:
    lodsb
    test al, al
    jz @f
    int 0x10
    jmp @b
@@:
    ret

display_message:
    ; Print message at DS:SI
    call print_string
    ret

menu db 'Simple Bootloader Menu', 13, 10
     db '1. Option 1', 13, 10
     db '2. Option 2', 13, 10
     db 'Select an option: ', 0

option1_msg db 13, 10, 'You selected Option 1!', 13, 10
           db 'Press any key to return to menu...', 13, 10, 0

option2_msg db 13, 10, 'You selected Option 2!', 13, 10
           db 'Press any key to return to menu...', 13, 10, 0

rb 510-($-$$)
db 0x55, 0xAA
This is the result:

luni, 12 august 2024

FASM : play a wav file with assembly programming language.

... this source code in FASM will play a hexa file using a window with two buttons, see my comments to deal with 'how to do it' ... :
; sound player example , tested with tada.wav from windows os
; convert wav file with
; tomeko.net/online_tools/file_to_hex.php online tool
; to text from tool , then add 'db ' in the front of Sound.inc text file like this:
; db 0x52, 0x49, 0x46, 0x46,
; this : 0x52, 0x49, 0x46, 0x46, is header for RIFF WAV file format

format PE GUI 4.0
entry start

include 'INCLUDE\win32a.inc'

ID_CAPTION         = 101
ID_MESSAGE         = 102
ID_ICONERROR       = 201
ID_ICONINFORMATION = 202
ID_ICONQUESTION    = 203
ID_ICONWARNING     = 204
ID_TOPMOST         = 301

section '.text' code readable executable

  start:

        invoke  GetModuleHandle,0
        invoke  DialogBoxParam,eax,37,HWND_DESKTOP,DialogProc,0
        invoke ExitProcess,0

proc DialogProc hwnddlg,msg,wparam,lparam
        push    ebx esi edi
        cmp     [msg],WM_INITDIALOG
        je      .wminitdialog
        cmp     [msg],WM_COMMAND
        je      .wmcommand
        cmp     [msg],WM_CLOSE
        je      .wmclose
        xor     eax,eax
        jmp     .finish
  .wminitdialog:

        jmp     .processed
  .wmcommand:
        cmp     [wparam],BN_CLICKED shl 16 + IDCANCEL    ; stop
        je      .player_stop

        cmp     [wparam],BN_CLICKED shl 16 + IDOK
        je      .player_play

        jmp     .processed

  .player_stop:
        invoke play, NULL, NULL, NULL     ; stop
        jmp     .processed

  .player_play:
        invoke play, sndFile, NULL, 0x0004 or 0x0001 ; 0x0004 = SND_MEMORY + ASYNC = 0x0001
        jmp     .processed

  .wmclose:
        invoke  EndDialog,[hwnddlg],0

  .processed:
        mov     eax,1
  .finish:
        pop     edi esi ebx
        ret
endp

section '.bss' readable writeable

  sndFile :
           ;db 'Sound.wav',0
  include 'Sound.inc';
section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL',\
          winmm,'winmm.dll'

  import winmm,\
          play, 'PlaySound'

  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         ExitProcess,'ExitProcess'

  import user,\
         DialogBoxParam,'DialogBoxParamA',\
         EndDialog,'EndDialog'

section '.rsrc' resource data readable

  directory RT_DIALOG,dialogs

  resource dialogs,\
           37,LANG_ENGLISH+SUBLANG_DEFAULT,demonstration

  dialog demonstration,'SoundPlayer / _ (typedef)',70,76,110,30,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME
    dialogitem 'BUTTON','Play',IDOK,10,10,45,15,WS_VISIBLE
    dialogitem 'BUTTON','Stop',IDCANCEL,54,10,45,15,WS_VISIBLE
  enddialog

sâmbătă, 10 august 2024

FASM : take a screenshot with assembly programming language.

From my old assembly projects, this is a source code that take an screenshot of your display.
format PE GUI 4.0

include 'INCLUDE\win32w.inc'

struct GdiplusStartupInput
  GdiplusVersion	   dd ?
  DebugEventCallback	   dd ?
  SuppressBackgroundThread dd ?
  SuppressExternalCodecs   dd ?
ends

struct ImageCodecInfo
  Clsid 	    db 16 dup ?
  FormatID	    db 16 dup ?
  CodecName	    dd ?
  DllName	    dd ?
  FormatDescription dd ?
  FilenameExtension dd ?
  MimeType	    dd ?
  Flags 	    dd ?
  Version	    dd ?
  SigCount	    dd ?
  SizeSize	    dd ?
  SigPattern	    dd ?
  SigMask	    dd ?
ends

section '.text' code readable executable

entry $

	invoke	GdiplusStartup,token,input,NULL
	test	eax,eax
	jnz	exit

	invoke	GdipGetImageEncodersSize,encoders_count,encoders_size
	test	eax,eax
	jnz	gdiplus_shutdown
	invoke	VirtualAlloc,0,[encoders_size],MEM_COMMIT,PAGE_READWRITE
	test	eax,eax
	jz	gdiplus_shutdown
	mov	ebx,eax
	invoke	GdipGetImageEncoders,[encoders_count],[encoders_size],ebx
	test	eax,eax
	jnz	gdiplus_shutdown
    scan_encoders:
	mov	esi,[ebx+ImageCodecInfo.MimeType]
	mov	edi,encoder_mimetype
	mov	ecx,(encoder_clsid-encoder_mimetype) shr 1
	repe	cmpsw
	je	encoder_found
	add	ebx,sizeof.ImageCodecInfo
	dec	[encoders_count]
	jnz	scan_encoders
	; no encoder found
	jmp	gdiplus_shutdown
     encoder_found:
	lea	esi,[ebx+ImageCodecInfo.Clsid]
	mov	edi,encoder_clsid
	mov	ecx,4
	rep	movsd
	invoke	VirtualFree,ebx,0,MEM_RELEASE

	invoke	GetDC,HWND_DESKTOP
	test	eax,eax
	jz	gdiplus_shutdown
	mov	esi,eax
	invoke	GetSystemMetrics,SM_CYSCREEN
	mov	[screen_height],eax
	invoke	GetSystemMetrics,SM_CXSCREEN
	mov	[screen_width],eax
	invoke	CreateCompatibleBitmap,esi,[screen_width],[screen_height]
	test	eax,eax
	jz	release_desktop_dc
	mov	ebx,eax
	invoke	CreateCompatibleDC,esi
	test	eax,eax
	jz	delete_bitmap
	mov	edi,eax
	invoke	SelectObject,edi,ebx
	test	eax,eax
	jz	delete_dc
	invoke	BitBlt,edi,0,0,[screen_width],[screen_height],esi,0,0,SRCCOPY
	test	eax,eax
	jz	delete_dc

	invoke	GdipCreateBitmapFromHBITMAP,ebx,NULL,gdip_bitmap
	test	eax,eax
	jnz	delete_dc

	invoke	GdipSaveImageToFile,[gdip_bitmap],file_name,encoder_clsid,NULL

	invoke	GdipDisposeImage,[gdip_bitmap]
  delete_dc:
	invoke	DeleteObject,edi
  delete_bitmap:
	invoke	DeleteObject,ebx
  release_desktop_dc:
	invoke	ReleaseDC,HWND_DESKTOP,esi
  gdiplus_shutdown:
	invoke	GdiplusShutdown,[token]
  exit:
	invoke	ExitProcess,0


section '.data' data readable writeable

  file_name du 'test.jpg',0

  encoder_mimetype du 'image/jpeg',0
	   .length = $ - encoder_mimetype
  encoder_clsid db 16 dup ?

  input GdiplusStartupInput 1
  token dd ?
  memdc dd ?
  gdip_bitmap dd ?

  encoders_count dd ?
  encoders_size dd ?

  screen_width dd ?
  screen_height dd ?

section '.rdata' data readable

data import

  library kernel32,'KERNEL32.DLL',\
	  user32,'USER32.DLL',\
	  gdi32,'GDI32.DLL',\
	  gdiplus, 'GDIPLUS.DLL'

  include 'INCLUDE\API\kernel32.inc'
  include 'INCLUDE\API\user32.inc'
  include 'INCLUDE\API\gdi32.inc'

  import  gdiplus,\
	  GdiplusStartup,'GdiplusStartup',\
	  GdiplusShutdown,'GdiplusShutdown',\
	  GdipGetImageEncodersSize,'GdipGetImageEncodersSize',\
	  GdipGetImageEncoders,'GdipGetImageEncoders',\
	  GdipSaveImageToFile,'GdipSaveImageToFile',\
	  GdipDisposeImage,'GdipDisposeImage',\
	  GdipCreateBitmapFromHBITMAP,'GdipCreateBitmapFromHBITMAP'

end data

duminică, 4 august 2024

FASM : writing on the screen with assembly programming language.

I haven't worked in assembly language for a long time. My favorite is FASM.
Here is an example of older source code that randomly displays some colored pixels.
If you change this line of source code, you will see that it is written directly on the screen from Windows 10:
invoke FindWindow,NULL,<'Random Pixels Screen'>
this is the result:
... using this you cannot be able to take a screenshot with Windows shortkeys:
invoke FindWindow,NULL,<'Random Pixels ...'>
This is the source code, if you want to test it:
format pe console
entry start

include 'INCLUDE/WIN32AX.INC'

section '.code' code readable writeable executable 

start:   
     invoke GetStdHandle,STD_OUTPUT_HANDLE
     mov [stdout],eax
          
     mov [rect.Left],0
     mov [rect.Top],0
     mov [rect.Right],79
     mov [rect.Bottom],44
     mov [coord.x],8
     mov [coord.y],40
     mov [cinfo.dwSize],25
     mov [cinfo.bVisible],FALSE
     
     cinvoke system,<'cls'>
     cinvoke srand,<cinvoke time,NULL>
     invoke SetConsoleTitle,<'Random Pixels Screen'>
     invoke SetConsoleWindowInfo,[stdout],1,rect
     invoke SetConsoleScreenBufferSize,[stdout],dword[coord]   
     invoke SetConsoleCursorInfo,[stdout],cinfo
     
     invoke FindWindow,NULL,<'Random Pixels ...'>
     mov [hWnd],eax
     invoke GetDC,[hWnd]
     mov [hdc],eax
                                     
@@:   
     cinvoke rand
     shl eax,9
     push eax
     cinvoke rand
     pop ecx
     add eax,ecx
     mov esi,eax
     invoke SetPixel,[hdc],<stdcall rnd,640>,<stdcall rnd,100>,esi
     cinvoke _kbhit
     test eax,eax
     jz @b
     invoke ExitProcess,0

proc rnd max
     cinvoke rand 
     shl eax,17
     mul [max]
     mov eax,edx            
     ret
endp    

section '.data' data readable writeable

struc COORD {
     .x dw ?
     .y dw ?
    } 

struc SMALL_RECT {
     .Left dw ?
     .Top dw ?
     .Right dw ?
     .Bottom dw ?
    } 

struc LPCONSOLE_CURSOR_INFO {
     .dwSize dd ?
     .bVisible db ?
    }      
     
     cinfo LPCONSOLE_CURSOR_INFO
     rect SMALL_RECT
     coord COORD     
          
     stdout dd ?
     hWnd dd ?
     hdc dd ?

     
section '.idata' import data readable writeable

     library kernel32,'kernel32.dll',\
        msvcrt,'msvcrt.dll',\
        user32,'user32.dll',\
        gdi32,'gdi32.dll'
         
     import gdi32,\
        SetPixel,'SetPixel'
                  
     import user32,\
        GetDC,'GetDC',\
        FindWindow,'FindWindowA'
             
     import kernel32,\     
        ExitProcess,'ExitProcess',\
        GetStdHandle,'GetStdHandle',\
        SetConsoleTitle,'SetConsoleTitleA',\
        SetConsoleCursorInfo,'SetConsoleCursorInfo',\
        SetConsoleWindowInfo,'SetConsoleWindowInfo',\
        SetConsoleCursorPosition,'SetConsoleCursorPosition',\
        SetConsoleScreenBufferSize,'SetConsoleScreenBufferSize'   
            
     import msvcrt,\
        _kbhit,'_kbhit',\
        system,'system',\      
        srand,'srand',\
        rand,'rand',\
        time,'time'

luni, 29 ianuarie 2024

News : FASM graphics with DirectX ...

It is not mandatory to use a game engine, access to the graphic resource of the computer can also be done through FASM.
An example of a website from asmgges.chez.com with source code in assembler that you can reuse !