flat assembler
Message board for the users of flat assembler.

Index > Linux > Xlib Window Example for x86_64 Linux

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
bitshifter



Joined: 04 Dec 2007
Posts: 813
Location: Massachusetts, USA
bitshifter 27 Jul 2026, 09:07
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Xlib Window Example for x86_64 Linux ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

format ELF64 executable 3
entry main

;;;;;;;;;;;;;;;;;;;;
;; import section ;;
;;;;;;;;;;;;;;;;;;;;

include 'import64.inc'

interpreter '/lib64/ld-linux-x86-64.so.2'

needed 'libX11.so.6'

import XOpenDisplay,\
       XDefaultRootWindow,\
       XCreateSimpleWindow,\
       XSelectInput,\
       XStoreName,\
       XMapWindow,\
       XInternAtom,\
       XSetWMProtocols,\
       XNextEvent,\
       XDestroyWindow,\
       XCloseDisplay

;;;;;;;;;;;;;;;;;;;;;
;; equates section ;;
;;;;;;;;;;;;;;;;;;;;;

; Xlib Constants
KeyPressMask  = 1
KeyPress      = 2
ClientMessage = 33

;;;;;;;;;;;;;;;;;;
;; code section ;;
;;;;;;;;;;;;;;;;;;

segment readable executable

main:
    ; note: rsp should be already aligned for 0-stack-arg calls

    ; Open connection to X server
    xor rdi, rdi                ; char *display_name (NULL)
    call [XOpenDisplay]
    test rax, rax
    jz exit_main
    mov [display_handle], rax

    ; Get default root window
    mov rdi, rax                ; Display *display
    call [XDefaultRootWindow]
    mov [root_handle], rax

    ; -------------------------------------------------------------------------

    ; XCreateSimpleWindow (9 parameters)
    ; First 6 parameters go in registers.
    ; Last 3 parameters go on stack. (right to left)

    ; Load registers for params 1-6
    mov rdi, [display_handle]       ; 1st param: Display *display
    mov rsi, [root_handle]          ; 2nd param: Window parent
    mov rdx, 0                      ; 3rd param: int x
    mov rcx, 0                      ; 4th param: int y
    mov r8, 320                     ; 5th param: unsigned int width
    mov r9, 240                     ; 6th param: unsigned int height

    ; Reserve 32 bytes (4 slots) to keep 16-byte alignment
    ; (3 parameters * 8 bytes = 24 bytes, rounded up to 32)
    sub rsp, 32
    mov qword [rsp+16], 0x00FFFFFF  ; 9th param: unsigned long background (color)
    mov qword [rsp+8],  0x00000000  ; 8th param: unsigned long border (color)
    mov qword [rsp],    2           ; 7th param: unsigned int border_width

    ; Create the window
    call [XCreateSimpleWindow]
    mov [window_handle], rax
    add rsp, 32                     ; Restore stack alignment

    ; -------------------------------------------------------------------------

    ; Select input types
    mov rdi, [display_handle]       ; Display *display
    mov rsi, [window_handle]        ; Window w
    mov rdx, KeyPressMask           ; long event_mask
    call [XSelectInput]

    ; Set window name
    mov rdi, [display_handle]       ; Display *display
    mov rsi, [window_handle]        ; Window w
    mov rdx, window_name_str        ; char *window_name
    call [XStoreName]

    ; Map window to screen
    mov rdi, [display_handle]       ; Display *display
    mov rsi, [window_handle]        ; Window w
    call [XMapWindow]

    ; Call Close Button Handler Sub-function 
    call register_wm_close

    ; Enter the event message loop
event_loop:
    mov rdi, [display_handle]       ; Display *display
    mov rsi, event_buffer           ; XEvent *event_return
    call [XNextEvent]

    mov eax, dword [event_buffer]     
    cmp eax, KeyPress           
    je event_loop_end           

;   TODO: handle other generic events here...

    cmp eax, ClientMessage
    jne event_loop

    mov rax, qword [event_buffer + 56]  ; data.l[0]
    cmp rax, [wm_delete_window]
    je event_loop_end           

;   TODO: handle other ClientMessage events here...

    jmp event_loop

event_loop_end:

    mov qword [exit_code], 0        ; exit status (success)

;exit_cleanup:

    ; Destroy Window instance
    mov rdi, [display_handle]       ; Display *display
    mov rsi, [window_handle]        ; Window w
    call [XDestroyWindow]

    ; Close display connection
    mov rdi, [display_handle]       ; Display *display
    call [XCloseDisplay]

exit_main:

    mov rdi, [exit_code]            ; exit status
    mov rax, 60                     ; exit syscall
    syscall

; =============================================================================

register_wm_close:
    sub rsp, 8                  

    ; Create 'WM_PROTOCOLS' Atom
    mov rdi, [display_handle]       ; Display *display
    mov rsi, wm_protocols_str       ; char *atom_name
    xor rdx, rdx                    ; Bool only_if_exists
    call [XInternAtom]
    mov [wm_protocols], rax

    ; Create 'WM_DELETE_WINDOW' Atom
    mov rdi, [display_handle]       ; Display *display
    mov rsi, wm_delete_window_str   ; char *atom_name
    xor rdx, rdx                    ; Bool only_if_exists
    call [XInternAtom]
    mov [wm_delete_window], rax

    ; Register protocols with window manager
    mov rdi, [display_handle]       ; Display *display
    mov rsi, [window_handle]        ; Window w
    lea rdx, [wm_delete_window]     ; Atom *protocols
    mov rcx, 1                      ; int count
    call [XSetWMProtocols]

    add rsp, 8
    ret

; =============================================================================

;;;;;;;;;;;;;;;;;;
;; data section ;;
;;;;;;;;;;;;;;;;;;

segment readable writeable

align 8
exit_code       dq 1    ; assume failure
display_handle  dq 0
root_handle     dq 0
window_handle   dq 0           

; Explicitly align atoms to 8-byte (64-bit) boundaries
align 8
wm_protocols     dq 0
wm_delete_window dq 0

wm_protocols_str     db 'WM_PROTOCOLS', 0
wm_delete_window_str db 'WM_DELETE_WINDOW', 0
window_name_str      db 'Hello Xlib Linux World!', 0

align 8
event_buffer rb 192
    

EDIT: Updated code example:
* Stack Alignment Fix: Replaced manual push instructions (see XCreateSimpleWindow) with a clean (sub rsp, 32) stack reservation.
* ABI Compliance: This ensures strict adherence to the 16-byte System V AMD64 ABI alignment rules before calling functions with more than 6 arguments.
* Safety & Readability: Passing parameters via explicit stack offsets ([rsp+16], [rsp+8], etc...) completely avoids accidental stack corruption during future modifications.

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.


Last edited by bitshifter on 28 Jul 2026, 05:03; edited 1 time in total
Post 27 Jul 2026, 09:07
View user's profile Send private message Reply with quote
sylware



Joined: 23 Oct 2020
Posts: 645
Location: Marseille/France
sylware 27 Jul 2026, 11:43
You should move to wayland. Xwayland is there only for legacy and it does create problems: it seems it is adding too much latency to some fast games.

If I were you...
Post 27 Jul 2026, 11:43
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 21055
Location: In your JS exploiting you and your system
revolution 27 Jul 2026, 11:51
sylware wrote:
You should move to wayland.
Why?
Post 27 Jul 2026, 11:51
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 148
Location: Brazil
Jessé 27 Jul 2026, 22:30
sylware wrote:
You should move to wayland. Xwayland is there only for legacy and it does create problems: it seems it is adding too much latency to some fast games.

If I were you...


No, he shouldn't.
Linux is about freedom of choice, and still exist XLibre which is widely and actively developed, and it is the break-free-of-chains continuation of X, with some improvements, according to them.
Being here doesn't mean someone should go mainstream (like the folks who still think there's only systemd and Wayland, btw).

Anyways, I'm here to see the nice example from bitshifter, done in the old (and pure) static fasm assembly! Looking forward to test the idea, because I never test interfacing directly with X.

_________________
jesse6
Post 27 Jul 2026, 22:30
View user's profile Send private message Visit poster's website Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 813
Location: Massachusetts, USA
bitshifter 28 Jul 2026, 04:26
My linux pc is from 2011, even tho it has modern linux on it, i still dont use Wayland, its better with X11 for me...
Post 28 Jul 2026, 04:26
View user's profile Send private message Reply with quote
sylware



Joined: 23 Oct 2020
Posts: 645
Location: Marseille/France
sylware 28 Jul 2026, 10:13
wayland is much leaner than x11...
Post 28 Jul 2026, 10:13
View user's profile Send private message Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 813
Location: Massachusetts, USA
bitshifter 28 Jul 2026, 11:30
On my old machine, xfce with x11 runs circles around wayland with gnome.
wayland is made for modern hardware and the compositor is mandatory.

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.
Post 28 Jul 2026, 11:30
View user's profile Send private message Reply with quote
Jessé



Joined: 03 May 2025
Posts: 148
Location: Brazil
Jessé 28 Jul 2026, 22:39
I've tested your example above, and, couldn't agree more. Not by copying it, but, by understanding it and make my own version.
Quite impressive to have a graphical thing at only 310KB of memory!
Of course it does nothing by itself, but, from that point on, it depends on who is creating what...
Against 48 MB from SDL3, and 44 MB from GTK4! Both of which I am more familiar with.
A major incentive for me to find out more about direct Xlib programming.

I'm waiting for the Wayland defenders to present their code (instead of hollow taking, and, of course, in assembly), so we have a strong and decisive point against X (and its derivatives, like XLibre).
Post 28 Jul 2026, 22:39
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 148
Location: Brazil
Jessé 29 Jul 2026, 11:57
Seeking for the minimal footprint possible, I also found that XCB is quite usable too.
Did a quick test and already spawn a window easily.
Check it out if you want: https://xcb.freedesktop.org/tutorial/basicwindowsanddrawing/
XCB has a very easy to parse into assembly documentation, and also has C headers that are very easy to understand, to obtain what is needed to interface it from assembly code.
And, the best part: 186 KB of memory footprint and you get a window!
Post 29 Jul 2026, 11:57
View user's profile Send private message Visit poster's website Reply with quote
sylware



Joined: 23 Oct 2020
Posts: 645
Location: Marseille/France
sylware 29 Jul 2026, 12:31
Dude, the xserver deprecation is accelerating (like GL).
Post 29 Jul 2026, 12:31
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2744
Furs 29 Jul 2026, 22:28
Nah Wayland is a joke who can't get some basic things right in the name of "security".
Post 29 Jul 2026, 22:28
View user's profile Send private message Reply with quote
MаtQuasar



Joined: 22 Jun 2026
Posts: 16
MаtQuasar 30 Jul 2026, 01:25
Jessé wrote:
Seeking for the minimal footprint possible, ...


ProMiNick has done also a minimal Xlib window example, with 'Hello World' example in page 2, but I don't know the difference between him and bitshifter's.

https://board.flatassembler.net/topic.php?t=22288
Post 30 Jul 2026, 01:25
View user's profile Send private message Reply with quote
sylware



Joined: 23 Oct 2020
Posts: 645
Location: Marseille/France
sylware 30 Jul 2026, 11:19
Furs wrote:
Nah Wayland is a joke who can't get some basic things right in the name of "security".


Nah, you probably can, but as custom extensions, namely wayland moved out much non-core stuff away (which has been in x11 core).

Core wayland is brutally lean, and give the least amount of information to clients.

If you need something beyond core wayland: wayland is like x11, dynamic, you have to query the availability of the extensions.

A warning though: a wayland compositor is not a small project, but still far from the size and complexity of the xserver. I am head banging my head against _CLEAN_ window management: a bazillions of little things to do everywhere.

(I have coded my own xserver DDX for an old AMDGPU driver of mine, and I am currently coding/designing a binary specification for my own wayland compositor).

And if you keep an eye on what is happening on wayland side, you'll seed that the xserver is running on fumes.
Post 30 Jul 2026, 11:19
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2744
Furs 30 Jul 2026, 23:45
sylware wrote:
Core wayland is brutally lean, and give the least amount of information to clients.
That's exactly the problem, yes.

Let me put it another way: A hello world program is also brutally lean, which is exactly the problem with it, it's not useful for anything.
Post 30 Jul 2026, 23:45
View user's profile Send private message Reply with quote
Jessé



Joined: 03 May 2025
Posts: 148
Location: Brazil
Jessé 31 Jul 2026, 00:47
I did some code demonstrating libxcb (which has nothing to do with libX11, except being an interface to the X server/protocol itself), and that beauty is the proof of what I'm saying. You can chek it here.
Despite not being the purest assembly form, like the example from bitshifter, I'm convinced that one here can figure out easily what's going on with XCB way of spawning windows.
I also demonstrated there one of the advantage points of XCB over libX: the non-blocking approach they implement. And, it worked flawlessly!
186 KB of memory usage, and a perfectly spawned window. The most efficient I've seen so far!
Post 31 Jul 2026, 00:47
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 21055
Location: In your JS exploiting you and your system
revolution 31 Jul 2026, 04:37
Libraries are good for what they do, but they can't match direct communication with the X11 server. For just a simple window, programs can be tiny, just a few kB.

Sending messages to X11 isn't that hard. Just open a socket and talk.
Post 31 Jul 2026, 04:37
View user's profile Send private message Visit poster's website Reply with quote
sylware



Joined: 23 Oct 2020
Posts: 645
Location: Marseille/France
sylware 31 Jul 2026, 09:08
Furs wrote:
sylware wrote:
Core wayland is brutally lean, and give the least amount of information to clients.
That's exactly the problem, yes.

Let me put it another way: A hello world program is also brutally lean, which is exactly the problem with it, it's not useful for anything.


???
Post 31 Jul 2026, 09:08
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2744
Furs 01 Aug 2026, 20:12
sylware wrote:
Furs wrote:
sylware wrote:
Core wayland is brutally lean, and give the least amount of information to clients.
That's exactly the problem, yes.

Let me put it another way: A hello world program is also brutally lean, which is exactly the problem with it, it's not useful for anything.


???
I don't know what wasn't clear? Wayland doesn't even give position information to clients last time I checked, you can't restore your window to a saved position etc.

Just because you want to isolate and sandbox every app from another because you're paranoid doesn't mean it's good for the rest of us who'd like our apps to, you know, have more control.
Post 01 Aug 2026, 20:12
View user's profile Send private message Reply with quote
Ali.Z



Joined: 08 Jan 2018
Posts: 896
Ali.Z 02 Aug 2026, 02:13
somebody used ai to recreate xorg server in nasm assembly.
https://github.com/isene/frame
i wonder how much did they spend on this.

...

perhaps you can test on this xorg implementation too.

_________________
Asm For Wise Humans
Post 02 Aug 2026, 02:13
View user's profile Send private message Reply with quote
sylware



Joined: 23 Oct 2020
Posts: 645
Location: Marseille/France
sylware 02 Aug 2026, 11:35
Furs wrote:
sylware wrote:
Furs wrote:
sylware wrote:
Core wayland is brutally lean, and give the least amount of information to clients.
That's exactly the problem, yes.

Let me put it another way: A hello world program is also brutally lean, which is exactly the problem with it, it's not useful for anything.


???
I don't know what wasn't clear? Wayland doesn't even give position information to clients last time I checked, you can't restore your window to a saved position etc.

Just because you want to isolate and sandbox every app from another because you're paranoid doesn't mean it's good for the rest of us who'd like our apps to, you know, have more control.


Huh? It just means it is the compositor doing that using wl_surface class/instance titles (maybe more infered informations). It was just moved to the compositor/window manager for good.

This is how I do it with my x11 window manager (dwm). The window manager which is part of the compositor in wayland. I pass a 'tag'/'session name' to the application for its instance names of windows to differentiate.

That say, you can have wayland extension protocols if you want, but they would have to be dynamically discovered with proper fallbacks.

I had a quick look at https://github.com/isene/frame

He still does not have DRM atomic modesetting (which xserver devs failed to do...). And I'll keep an eye on its GFX hardware acceleration (still not there). And "correct" evdev input handling is far from being straight forward (I am currently coding exactly that in my wayland compositor), more so to fit it with transactional window management state changes.

(After quick skimming of https://github.com/isene/chasm: I'll keep tabs on https://github.com/isene/bare and https://github.com/isene/glyph)

And guys, x11 is running on fumes, its deprecation is accelerating (like for GL).

Don't forget, the main reason for wayland: it is several orders of magnitude leaner and simpler than x11, and build on top of x11 experience.
Post 02 Aug 2026, 11:35
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2026, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.