1
2; rudimentary "hello world" for Xwindows
3; translated from a nasm sample supplied by Frank Kotler.
4; LD is used as linker, since WLINK doesn't know how to use shared objects.
5;
6; 1. assemble:       jwasm -elf -Fo=Linux3.o Linux3.asm
7; 2. link with LD:   ld -s -o Linux3 Linux3.o -I/lib/ld-linux.so.2 -L/usr/X11R6/lib -lX11
8
9    .386
10    .model flat
11
12    public _start
13
14;--- The X functions don't have a underscore prefix.
15;--- Therefore SYSCALL is used in the prototypes.
16;--- If C is to be used instead, the -zcw cmdline parameter is needed.
17
18XOpenDisplay        proto syscall :DWORD
19XDefaultRootWindow  proto syscall :DWORD
20XCreateSimpleWindow proto syscall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
21XSelectInput        proto syscall :DWORD, :DWORD, :DWORD
22XStoreName          proto syscall :DWORD, :DWORD, :DWORD
23XMapRaised          proto syscall :DWORD, :DWORD
24XCreateGC           proto syscall :DWORD, :DWORD, :DWORD, :DWORD
25XSetForeground      proto syscall :DWORD, :DWORD, :DWORD
26XSetBackground      proto syscall :DWORD, :DWORD, :DWORD
27XNextEvent          proto syscall :DWORD, :DWORD
28XFreeGC             proto syscall :DWORD, :DWORD
29XDestroyWindow      proto syscall :DWORD, :DWORD
30XCloseDisplay       proto syscall :DWORD
31XDrawImageString    proto syscall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
32
33KeyPressMask equ 1     ; mask for XSelectInput
34KeyPress     equ 2     ; the "type" of event (offset 0 in "glob of bytes")
35
36ExposeMask   equ 1 shl 15
37ExposeEvent  equ 12
38
39event_size equ 20h    ; ??? max size of several different structs
40
41;------------------------------------------
42    .data
43    StringOpenFailed db "Can't Open X display!", 10
44    caption db 'A Window', 0
45    string db ' Greetings from X, Earthling! '
46
47;-----------------------------------------
48    .data?
49
50Display dd ?
51Window  dd ?
52GC      dd ?
53
54event   dd event_size dup (?)
55
56;-------------------------------------
57
58    .code
59
60_start:    ; let the ritual begin.
61; open a connection to the server.
62; param 0 uses the "DISPLAY" environment variable
63; or defaults to local machine.
64    invoke XOpenDisplay, 0
65    .if (eax == 0)
66        mov eax, 4                      ; __NR_write
67        mov ebx, 2                      ; stderr
68        mov ecx, offset StringOpenFailed; buffer
69        mov edx, sizeof StringOpenFailed; count
70        int 80h
71        jmp Terminate
72    .endif
73    mov [Display], eax
74
75    invoke XDefaultRootWindow, [Display]
76    ; error?
77;--- params: display handle, defaultrootwindow, left, top, width, height
78;---         border width, border colour, background colour
79    invoke XCreateSimpleWindow, [Display], eax, 50, 50, 400, 300, 0, 0, 0
80    .if (eax == 0)
81        invoke XCloseDisplay, [Display]
82        jmp Terminate
83    .endif
84    mov [Window], eax
85; this is one Windows doesn't do. if we don't specify
86; what events (messages) we want to receive, we don't get any.
87; "or" this with other events to recv!
88; don't forget to handle 'em!
89    invoke XSelectInput, [Display], [Window], KeyPressMask or ExposeMask
90    ; error?
91    ; give the baby a name
92    invoke XStoreName, [Display], [Window], offset caption
93    ; error?
94    invoke XMapRaised, [Display], [Window]  ; make our window visible.
95    ; error?
96    invoke XCreateGC, [Display], [Window], 0, 0
97    ; error?
98    mov [GC], eax
99; Mmmm, looks like 16-bit color, 5-6-5, on my machine.
100; Bet we can't count on it!
101; 1111100000000000b = red
102    invoke XSetForeground, [Display], [GC], 1111100000000000b
103    ; error?
104; 0000011111100000b = green
105    invoke XSetBackground, [Display], [GC], 0000011111100000b
106    ; error?
107
108    .while (1)
109        invoke XNextEvent, [Display], offset event
110        ; error?
111        .if (dword ptr [event+0] == ExposeEvent)
112            invoke XDrawImageString, [Display], [Window], [GC], 155, 140, offset string, sizeof string
113        .elseif (dword ptr [event+0] == KeyPress)
114            .break  ; exit gracefully if key pressed
115        .endif
116    .endw
117
118    invoke XFreeGC, [Display], [GC]
119    invoke XDestroyWindow, [Display], [Window]
120    invoke XCloseDisplay, [Display]
121
122Terminate:
123    mov eax, 1     ; function (sys_exit)
124    xor ebx, ebx   ; exit code
125    int 80h        ; make Linux system call
126
127    end _start
128