From: Frank Kotler on
SoLo2 wrote:
> Hello!
>
> I have tried how simple it is to use
> system calls in Linux from assembler.
> Setting parameters in the registers
> eax/edx and then "int 0x80".
>
> I would like to know it there
> is a similar, easy way of calling
> other libraries (specially X windows).

I don't know how "similar" you'd call it, or "easy"... but yes, we
certainly can do that. At some point, there isn't much "advantage" to
using asm...

Might be better to start with a simpler "just call printf" example, but
since you ask about X, I'll append a simple "hello X".

> It should be as simple as giving
> the function name in ASCII ! :)

Well... it won't work in Egyptian hieroglyphics (unless you've got an
Egyptian assembler)... I have seen stuff like:

button db "button", 0

.... mostly in "helper" libraries, not in Xlib itself. I don't know when
or why we have to do that. Mostly it's just "extern XFoo"...

This example links directly with ld. It strikes me that it might be
"dangerous" to be using C library code, without linking in the C startup
code. It "seems to work". I haven't had any trouble with it... (we *do*
need to tell ld which interpreter/dynamic linker to use - ld gets it
wrong by default! gcc knows...) Replace "_start" with "main", if you
want to do it that way...

I have other examples... including accessing Xwindows *without*
libraries - just using the int 80h interface - and even examples that
avoid using ld - creating a "ready to run" executable using Nasm's "-f
bin" mode. How "raw" would you like to get? :)

I'm replying from comp.lang.asm.x86 - I doubt if these other groups are
interested in doing it in assembly language (or are they???). Should
probably trim followups, at some point. There is also interest in this
subject on the news:alt.lang.asm newsgroup...

Best,
Frank


; rudimentary "hello world" for Xwindows

; nasm -f elf -O999 x1.asm
; add the "-g" switch for debugging info - good luck!
;
; sorry 'bout this one...
; ld -o x1 x1.o -I/lib/ld-linux.so.2 -L/usr/X11R6/lib -lX11
;
; if you want it small:
; strip -R .comment x1
;
; after all that, we still have to tell ld where the fun begins:

global _start

; inform Nasm that ld knows where to find this stuff (we hope!)

extern XOpenDisplay
extern XDefaultRootWindow
extern XCreateSimpleWindow
extern XNextEvent
extern XDestroyWindow
extern XCloseDisplay
extern XMapRaised
extern XSelectInput
extern XStoreName
extern XCreateGC
extern XFreeGC
extern XDrawImageString
extern XSetForeground
extern XSetBackground


; we'll be needing lots more of these...

KeyPressMask equ 1 ; mask for XSelectInput
KeyPress equ 2 ; the "type" of event (offset 0 in "glob of bytes")

ExposeMask equ 1 << 15
ExposeEvent equ 12


event_size equ 20h ; ??? max size of several different structs


;------------------------------------------
section .data
StringOpenFailed db "Can't Open X display!", 10
StringOpenFailed_len equ $ - StringOpenFailed

caption db 'A Window', 0

string db ' Greetings from X, Earthling! '
string_len equ $ - string
;-----------------------------------------

;-----------------------------------------
section .bss

Display resd 1
Window resd 1
GC resd 1

event resd event_size
;-------------------------------------

;-------------------------------------
section .text

_start: ; let the ritual begin.

; nop ; parking place for gdb

; open a connection to the server.
; pushing 0 uses the "DISPLAY" environment variable
; or defaults to local machine.

push 0
call XOpenDisplay
add esp, 4

or eax, eax
je OpenFailed

mov dword [Display], eax

push dword [Display]
call XDefaultRootWindow
add esp, 4
; error?

push 0 ; background colour
push 0 ; border colour
push 0 ; border width
push 300 ; height
push 400 ; width
push 50 ; top co-ord
push 50 ; left co-ord
push eax ; XDefaultRootWindow, from above
push dword [Display] ; display handle
call XCreateSimpleWindow
add esp, 36 ; C clean-up parameters stuff

or eax, eax
je CreateFailed

mov dword [Window], eax

; this is one Windows doesn't do. if we don't specify
; what events (messages) we want to receive, we don't get any.

push KeyPressMask | ExposeMask
; "or" this with other events to recv!
; don't forget to handle 'em!
push dword [Window]
push dword [Display]
call XSelectInput
add esp, 12
; error?

; give the baby a name

push caption
push dword [Window]
push dword [Display]
call XStoreName
add esp, 12
; error?


; make our window visible.

push dword [Window]
push dword [Display]
call XMapRaised
add esp, 8
; error?


push 0 ; values?
push 0 ; valuemask?
push dword [Window]
push dword [Display]
call XCreateGC
add esp, 16
;error?
mov dword [GC], eax

; Mmmm, looks like 16-bit color, 5-6-5, on my machine.
; Bet we can't count on it!

; push 65535 ; white
push 1111100000000000b ; red
push dword [GC]
push dword [Display]
call XSetForeground
add esp, 12
; error?

; push 0 ; black
push 0000011111100000b ; green
push dword [GC]
push dword [Display]
call XSetBackground
add esp, 12
; error?

Eventloop:
push event
push dword [Display]
call XNextEvent
add esp, 8
; error?

cmp dword [event], ExposeEvent
jnz not_expose
call drawscreen
jmp Eventloop
not_expose:

cmp dword [event], KeyPress
jne Eventloop

; exit gracefully if key pressed

push dword [GC]
push dword [Display]
call XFreeGC
add esp, 8

push dword [Window]
push dword [Display]
call XDestroyWindow
add esp, 8

CreateFailed:
push dword [Display]
call XCloseDisplay
add esp, 4
jmp Terminate

OpenFailed:
mov eax, 4 ; __NR_write
mov ebx, 2 ; stderr
mov ecx, StringOpenFailed ; buffer
mov edx, StringOpenFailed_len ; count
int 80h

Terminate:
mov eax, 1 ; function (sys_exit)
xor ebx, ebx ; exit code
int 80h ; make Linux system call
;-------------------------------------------

;-------------------------------------------
drawscreen:
push string_len
push string
push 140 ; y pos
push 155 ; x pos
push dword [GC]
push dword [Window]
push dword [Display]
call XDrawImageString
add esp, 28
; error?
ret
;---------------------------------------------

From: SoLo2 on
On Apr 19, 8:29 am, Frank Kotler <spamt...(a)crayne.org> wrote:
> SoLo2 wrote:
> > Hello!
>
> > I have tried how simple it is to use
> > system calls in Linux from assembler.
> > Setting parameters in the registers
> > eax/edx and then "int 0x80".
>
> > I would like to know it there
> > is a similar, easy way of calling
> > other libraries (specially X windows).
>
> I don't know how "similar" you'd call it, or "easy"... but yes, we
> certainly can do that. At some point, there isn't much "advantage" to
> using asm...
>
> Might be better to start with a simpler "just call printf" example, but
> since you ask about X, I'll append a simple "hello X".
>
> > It should be as simple as giving
> > the function name in ASCII ! :)
>
> Well... it won't work in Egyptian hieroglyphics (unless you've got an
> Egyptian assembler)... I have seen stuff like:
>
> button db "button", 0
>
> ... mostly in "helper" libraries, not in Xlib itself. I don't know when
> or why we have to do that. Mostly it's just "extern XFoo"...
>
> This example links directly with ld. It strikes me that it might be
> "dangerous" to be using C library code, without linking in the C startup
> code. It "seems to work". I haven't had any trouble with it... (we *do*
> need to tell ld which interpreter/dynamic linker to use - ld gets it
> wrong by default! gcc knows...) Replace "_start" with "main", if you
> want to do it that way...
>
> I have other examples... including accessing Xwindows *without*
> libraries - just using the int 80h interface - and even examples that
> avoid using ld - creating a "ready to run" executable using Nasm's "-f
> bin" mode. How "raw" would you like to get? :)
>
> I'm replying from comp.lang.asm.x86 - I doubt if these other groups are
> interested in doing it in assembly language (or are they???). Should
> probably trim followups, at some point. There is also interest in this
> subject on the news:alt.lang.asm newsgroup...
>
> Best,
> Frank
>
> ; rudimentary "hello world" for Xwindows
>
> ; nasm -f elf -O999 x1.asm
> ; add the "-g" switch for debugging info - good luck!
> ;
> ; sorry 'bout this one...
> ; ld -o x1 x1.o -I/lib/ld-linux.so.2 -L/usr/X11R6/lib -lX11
> ;
> ; if you want it small:
> ; strip -R .comment x1
> ;
> ; after all that, we still have to tell ld where the fun begins:
>
> global _start
>
> ; inform Nasm that ld knows where to find this stuff (we hope!)
>
> extern XOpenDisplay
> extern XDefaultRootWindow
> extern XCreateSimpleWindow
> extern XNextEvent
> extern XDestroyWindow
> extern XCloseDisplay
> extern XMapRaised
> extern XSelectInput
> extern XStoreName
> extern XCreateGC
> extern XFreeGC
> extern XDrawImageString
> extern XSetForeground
> extern XSetBackground
>
> ; we'll be needing lots more of these...
>
> KeyPressMask equ 1 ; mask for XSelectInput
> KeyPress equ 2 ; the "type" of event (offset 0 in "glob of bytes")
>
> ExposeMask equ 1 << 15
> ExposeEvent equ 12
>
> event_size equ 20h ; ??? max size of several different structs
>
> ;------------------------------------------
> section .data
> StringOpenFailed db "Can't Open X display!", 10
> StringOpenFailed_len equ $ - StringOpenFailed
>
> caption db 'A Window', 0
>
> string db ' Greetings from X, Earthling! '
> string_len equ $ - string
> ;-----------------------------------------
>
> ;-----------------------------------------
> section .bss
>
> Display resd 1
> Window resd 1
> GC resd 1
>
> event resd event_size
> ;-------------------------------------
>
> ;-------------------------------------
> section .text
>
> _start: ; let the ritual begin.
>
> ; nop ; parking place for gdb
>
> ; open a connection to the server.
> ; pushing 0 uses the "DISPLAY" environment variable
> ; or defaults to local machine.
>
> push 0
> call XOpenDisplay
> add esp, 4
>
> or eax, eax
> je OpenFailed
>
> mov dword [Display], eax
>
> push dword [Display]
> call XDefaultRootWindow
> add esp, 4
> ; error?
>
> push 0 ; background colour
> push 0 ; border colour
> push 0 ; border width
> push 300 ; height
> push 400 ; width
> push 50 ; top co-ord
> push 50 ; left co-ord
> push eax ; XDefaultRootWindow, from above
> push dword [Display] ; display handle
> call XCreateSimpleWindow
> add esp, 36 ; C clean-up parameters stuff
>
> or eax, eax
> je CreateFailed
>
> mov dword [Window], eax
>
> ; this is one Windows doesn't do. if we don't specify
> ; what events (messages) we want to receive, we don't get any.
>
> push KeyPressMask | ExposeMask
> ; "or" this with other events to recv!
> ; don't forget to handle 'em!
> push dword [Window]
> push dword [Display]
> call XSelectInput
> add esp, 12
> ; error?
>
> ; give the baby a name
>
> push caption
> push dword [Window]
> push dword [Display]
> call XStoreName
> add esp, 12
> ; error?
>
> ; make our window visible.
>
> push dword [Window]
> push dword [Display]
> call XMapRaised
> add esp, 8
> ; error?
>
> push 0 ; values?
> push 0 ; valuemask?
> push dword [Window]
> push dword [Display]
> call XCreateGC
> add esp, 16
> ;error?
> mov dword [GC], eax
>
> ; Mmmm, looks like 16-bit color, 5-6-5, on my machine.
> ; Bet we can't count on it!
>
> ; push 65535 ; white
> push 1111100000000000b ; red
> push dword [GC]
> push dword [Display]
> call XSetForeground
> add esp, 12
> ; error?
>
> ; push 0 ; black
> push 0000011111100000b ; green
> push dword [GC]
> push dword [Display]
> call XSetBackground
> add esp, 12
> ; error?
>
> Eventloop:
> push event
> push dword [Display]
> call XNextEvent
> add esp, 8
> ; error?
>
> cmp dword [event], ExposeEvent
> jnz not_expose
> call drawscreen
> jmp Eventloop
> not_expose:
>
> cmp dword [event], KeyPress
> jne Eventloop
>
> ; exit gracefully if key pressed
>
> push dword [GC]
> push dword [Display]
> call XFreeGC
> add esp, 8
>
> push dword [Window]
> push dword [Display]
> call XDestroyWindow
> add esp, 8
>
> CreateFailed:
> push dword [Display]
> call XCloseDisplay
> add esp, 4
> jmp Terminate
>
> OpenFailed:
> mov eax, 4 ; __NR_write
> mov ebx, 2 ; stderr
> mov ecx, StringOpenFailed ; buffer
> mov edx, StringOpenFailed_len ; count
> int 80h
>
> Terminate:
> mov eax, 1 ; function (sys_exit)
> xor ebx, ebx ; exit code
> int 80h ; make Linux system call
> ;-------------------------------------------
>
> ;-------------------------------------------
> drawscreen:
> push string_len
> push string
> push 140 ; y pos
> push 155 ; x pos
> push dword [GC]
> push dword [Window]
> push dword [Display]
> call XDrawImageString
> add esp, 28
> ; error?
> ret
> ;---------------------------------------------


Hello!

Thanks to Frank Kotler for his
excellent example of assembler
i86 and X.
[ Also Kleebauer's with the
Motorola 68millions version. ]

I would like to see that the dynamic
libraries are not very dynamic,
if the higher abstraction of using an
ASCII function name is not used.
This is the case as the compilation
of the program requires naming and
linking some "dynamic" libraries.

The program system or programmer
could use an "INT 80" with the ASCII
library name and then the interrupt
delivers the actual method pointer that
is faster to use for further calls.

Wasn't this already for Linux?
Where is this beautifull idea gone?
Java? :-)

Someone points out that there is
doubt a compiler would reach such
clean code for an X program as this
shown by Mr. Kotler.

Greetings,
H.Samso

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
http://bits.atari.org
http://biis.tripod.com
http://so_o2.tripod.com
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

From: Terence on
An interesting point in Frank Kotler's posting, is who gets to clean
up the stack.
Here Frank is doing it in the main program (obviously because the
called rountines don't do this for him).
But I was "brought up" on the Microsoft standard of the CALLED
subprogram doing a RET N operation to clear the stack. All my hand-
wriiten subroutine include this, beuase my main program is a Microsoft
Fortran program which folows my description of the stack
responsibility.

So I assume Miscroft chnaged it's mind at some point in time, because
obvious again, the referred called services aboove are Microsoft-
written Windows service.

From: Frank Kotler on
Terence wrote:
> An interesting point in Frank Kotler's posting, is who gets to clean
> up the stack.
> Here Frank is doing it in the main program (obviously because the
> called rountines don't do this for him).
> But I was "brought up" on the Microsoft standard of the CALLED
> subprogram doing a RET N operation to clear the stack. All my hand-
> wriiten subroutine include this, beuase my main program is a Microsoft
> Fortran program which folows my description of the stack
> responsibility.
>
> So I assume Miscroft chnaged it's mind at some point in time, because
> obvious again, the referred called services aboove are Microsoft-
> written Windows service.

???

You'll have to point out the Microsoft written services to me. I missed
'em. Is this what the lawsuit's about??? :)

Best,
Frank

From: santosh on
Terence wrote:

> An interesting point in Frank Kotler's posting, is who gets to clean
> up the stack.
> Here Frank is doing it in the main program (obviously because the
> called rountines don't do this for him).
> But I was "brought up" on the Microsoft standard of the CALLED
> subprogram doing a RET N operation to clear the stack. All my hand-
> wriiten subroutine include this, beuase my main program is a Microsoft
> Fortran program which folows my description of the stack
> responsibility.
>
> So I assume Miscroft chnaged it's mind at some point in time, because
> obvious again, the referred called services aboove are Microsoft-
> written Windows service.

No, the program is for X Windows, whose interface uses the so called "C
calling convention", where it's the caller's job to clean-up the stack.