JWASM Linux gtk Example (32bit)

Started by jcfuller, October 31, 2009, 06:15:39 PM

Previous topic - Next topic

jcfuller

My first forray with JWASM on Linux was successful so I thought I'd post a very simple gtk example.
James

Edit: wrong link.

;=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
;very simple jwasm gtk example
; 1. assemble:       ~/jwasm/JWASM -elf -Fo=gtk01.o gtk01.asm
; 2. link with LD:   ld -s -o gtk01 gtk01.o -I/lib/ld-linux.so.2 `pkg-config --libs gtk+-2.0`
;=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
    .386
    .model flat

    public _start

gtk_init proto syscall :DWORD, :DWORD
gtk_init_check proto syscall :DWORD, :DWORD
gtk_window_new proto syscall :DWORD
gtk_window_set_title proto syscall :DWORD, :DWORD
gtk_table_new proto syscall :DWORD, :DWORD, :DWORD
gtk_table_attach_defaults proto syscall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
gtk_container_add proto syscall :DWORD, :DWORD
gtk_button_new_from_stock  proto syscall :DWORD
gtk_label_new proto syscall :DWORD
gtk_widget_show_all proto syscall :DWORD
gtk_main proto syscall
gtk_main_quit proto syscall
g_signal_connect_data proto syscall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD

.data
no_int db 'No gtk_init',0
wincap db 'Hello World', 0
labelcap db 'jwasm gtk example', 0
quitbut db 'gtk-quit',0
no_win_err db 'No Window',0
sdel_event db 'delete-event',0
sclicked db 'clicked',0

    .data?
window dd ?
table dd ?
gtklabel dd ?
button dd ?

    .code

_start:    ; let the ritual begin.

;make sure we have gtk
invoke gtk_init_check,0,0
.if (eax == 0)
mov eax, 4                      ; __NR_write
    mov ebx, 2                      ; stderr
    mov ecx, offset no_int; buffer
    mov edx, sizeof no_int; count
    int 80h
    jmp Terminate
.endif
;create window
invoke gtk_window_new, 0
.if (eax == 0)
mov eax, 4                      ; __NR_write
    mov ebx, 2                      ; stderr
    mov ecx, offset no_win_err; buffer
    mov edx, sizeof no_win_err; count
    int 80h
    jmp Terminate
.endif
mov [window], eax

invoke gtk_window_set_title,[window], offset wincap
invoke gtk_table_new,15, 15, 1
mov [table],eax
invoke gtk_container_add,[window],[table]
invoke gtk_label_new,offset labelcap
mov [gtklabel],eax
invoke gtk_table_attach_defaults,[table],[gtklabel],1, 8, 3, 7
invoke gtk_button_new_from_stock,offset quitbut
mov [button],eax
invoke gtk_table_attach_defaults,[table],[button], 10, 14, 12, 14
;Show whole GUI
invoke gtk_widget_show_all,[window]
;attache signals
invoke g_signal_connect_data,[window],offset sdel_event,offset exit_prog,0, 0, 0
invoke g_signal_connect_data,[button],offset sclicked,offset exit_prog,0, 0, 0
;Do it
invoke gtk_main
;------------------------------------------------------------------------------
;Callback for closing window
exit_prog proc
    invoke gtk_main_quit
exit_prog endp
;------------------------------------------------------------------------------
Terminate:
    mov eax, 1     ; function (sys_exit)
    xor ebx, ebx   ; exit code
    int 80h        ; make Linux system call

    end _start



muttonhead

very nice!   :U

Thanks for the sample code for JWASM.  I grabbed the assembler just about an hour ago and assembled and linked your code in a blink on an Ubuntu 32 9.10 box.

I'm going to go play with gtk now and my new assembler.

This JWASM is nice.  Now I can use the MASM code that I have under Linux.   :cheekygreen:

jcfuller

For any of the windows lurkers I did this on an old hp7975  2GHz P4 with 512MB, using  wubi: http://wubi-installer.org/ (9.04)  but it is upgrading to 9.10 as I write.
I am really amazed at the response. One gotcha is it doesn't work with by usb kvm so I have to have a second keyboard to select the linux boot option. After that it finds my keyboard just fine.
James

muttonhead

I never have yet tried wubi.  When I was learning Linux and still needed to access Windows from time to time I decided that I did not want to dual boot, so I went to newegg.com and bought some drive drawers/trays so that I could swap the drives.  This made it a bunch easier.  I ended up buying trays for all my desktop tower cases and after I flushed Windows completely, I have all sorts of drives here that I can use for data storage - and they are a breeze to move from computer to computer if need be.

Going all Linux/BSD is so much fun.

Thanks again for the code.  I'm going to use it as a starting point for some ideas that I'd like to flesh out.  This JWASM is a pretty nifty assembler.


hutch--

Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

japheth


Cool! Is the sample Public Domain? Then I can add it to the JWasm samples dir.


jcfuller

@muttonhead,
  You're welcome.

@hutch
  Thanks for the compliment. It's been a LONG time since I did any asm coding.
  In this instance my fun with BaCon (mentioned in another post somewhere) helped immensely with the gtk code and Linux programming in general.

@japheth
  add away. All my posted code is public domain.

There may be problems with Linux noobs as you do have to install development packages. I use Ubuntu 64 9.10  for my main Linux machine ( and BaCon development), but am using Wubi (32) for jwasm, and FreeBasic right now. It's just too big a pia to find all the needed 32bit libraries for use on Ubu64 and I don't have a spare machine at the moment for Ubu32 ( soon to change as I am having too much fun with jwasm).
Thank you japheth for jwasm.

James

jcfuller

This is basically the same as above but uses dynamic loading of the shared libraries.

Did I miss it or is there no debugging jwasm code on Linux?

James




;=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
;very simple jwasm gtk example
;This one uses dynamic loading of shared libraries
; 1. assemble:       ~/jwasm/JWASM -elf -Fo=gtk02.o gtk02.asm
; 2. link with LD:   ld -s -o gtk02 gtk02.o -I/lib/ld-linux.so.2 -ldl
;=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
    .386
    .model flat

    public _start
;------------------------------------------------------------------------------   
;very handy MACRO   
_invoke MACRO funcname:REQ,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20
local pos

    FOR arg,<p20,p19,p18,p17,p16,p15,p14,p13,p12,p11,p10,p9,p8,p7,p6,p5,p4,p3,p2,p1>

        IFNB <arg>
             pos=@InStr(1,arg,<ADDR>) OR @InStr(1,arg,<addr>) OR @InStr(1,arg,<Addr>)

             IF pos

                IF (OPATTR(@SubStr(arg,%pos+5))) EQ 98
                        lea eax,@SubStr(<arg>,%pos+5)
                        push eax
                ELSE
                        push OFFSET @SubStr(<arg>,%pos+5)
                ENDIF

             ELSE
                        push arg
             ENDIF
        ENDIF
    ENDM
call funcname
ENDM   
;------------------------------------------------------------------------------     
RTLD_LAZY equ 1
dlopen proto syscall :DWORD, :DWORD
dlclose proto syscall :DWORD
dlsym proto syscall :DWORD, :DWORD
;------------------------------------------------------------------------------   
.data
no_init db 'No gtk_init',0
wincap db 'Hello World', 0
labelcap db 'jwasm gtk example', 0
quitbut db 'gtk-quit',0
no_win_err db 'No Window',0
sdel_event db 'delete-event',0
sclicked db 'clicked',0
no_dl db 'No gtk library load',0
no_dl_proc db 'No gtk proc find',0

sz_gtk_lib db 'libgtk-x11-2.0.so',0
sz_gtk_init_check db 'gtk_init_check',0
sz_gtk_window_new db 'gtk_window_new',0
sz_gtk_window_set_title db 'gtk_window_set_title',0
sz_gtk_table_new db 'gtk_table_new',0
sz_gtk_table_attach_defaults db 'gtk_table_attach_defaults',0
sz_gtk_container_add db 'gtk_container_add',0
sz_gtk_button_new_from_stock db 'gtk_button_new_from_stock',0
sz_gtk_label_new db 'gtk_label_new',0
sz_gtk_widget_show_all db 'gtk_widget_show_all',0
sz_gtk_main db 'gtk_main',0
sz_gtk_main_quit db 'gtk_main_quit',0

sz_gobject_lib db 'libgobject-2.0.so',0
sz_g_signal_connect_data db 'g_signal_connect_data',0
   
    .data?
window dd ?
table dd ?
gtklabel dd ?
button dd ?
gtk_lib dd ?
gobject_lib dd ?
gtk_init_check dd ?
gtk_window_new dd ?
gtk_window_set_title dd ?
gtk_table_new dd ?
gtk_table_attach_defaults dd ?
gtk_container_add dd ?
gtk_button_new_from_stock  dd ?
gtk_label_new dd ?
gtk_widget_show_all dd ?
gtk_main dd ?
gtk_main_quit dd ?
g_signal_connect_data dd ?

    .code

_start:   

invoke dlopen,offset sz_gtk_lib,RTLD_LAZY
.if (eax == 0)
mov eax, 4                      ; __NR_write
    mov ebx, 2                      ; stderr
    mov ecx, offset no_dl; buffer
    mov edx, sizeof no_dl; count
    int 80h
    jmp Terminate
.endif
mov gtk_lib,eax

invoke dlopen,offset sz_gobject_lib,RTLD_LAZY
.if (eax == 0)
mov eax, 4                      ; __NR_write
    mov ebx, 2                      ; stderr
    mov ecx, offset no_dl; buffer
    mov edx, sizeof no_dl; count
    int 80h
    jmp Terminate
.endif
mov gobject_lib,eax


invoke dlsym,gtk_lib,offset sz_gtk_init_check
.if (eax == 0)
mov eax, 4                      ; __NR_write
    mov ebx, 2                      ; stderr
    mov ecx, offset no_dl_proc; buffer
    mov edx, sizeof no_dl_proc; count
    int 80h
    jmp Terminate
.endif
mov gtk_init_check,eax
; I'm going to assume the rest are spelled correctly

invoke dlsym,gtk_lib,offset sz_gtk_window_new
mov gtk_window_new,eax

invoke dlsym,gtk_lib,offset sz_gtk_window_set_title
mov gtk_window_set_title,eax

invoke dlsym,gtk_lib,offset sz_gtk_table_new
mov gtk_table_new,eax

invoke dlsym,gtk_lib,offset sz_gtk_table_attach_defaults
mov gtk_table_attach_defaults,eax

invoke dlsym,gtk_lib,offset sz_gtk_container_add
mov gtk_container_add,eax

invoke dlsym,gtk_lib,offset sz_gtk_button_new_from_stock
mov gtk_button_new_from_stock,eax

invoke dlsym,gtk_lib,offset sz_gtk_label_new
mov gtk_label_new,eax

invoke dlsym,gtk_lib,offset sz_gtk_widget_show_all
mov gtk_widget_show_all,eax

invoke dlsym,gtk_lib,offset sz_gtk_main
mov gtk_main,eax

invoke dlsym,gtk_lib,offset sz_gtk_main_quit
mov gtk_main_quit,eax

invoke dlsym,gobject_lib,offset sz_g_signal_connect_data
mov g_signal_connect_data,eax


_invoke gtk_init_check,0,0
.if (eax == 0)
mov eax, 4                      ; __NR_write
    mov ebx, 2                      ; stderr
    mov ecx, offset no_init; buffer
    mov edx, sizeof no_init; count
    int 80h
    jmp Terminate
.endif

_invoke gtk_window_new, 0
.if (eax == 0)
mov eax, 4                      ; __NR_write
    mov ebx, 2                      ; stderr
    mov ecx, offset no_win_err; buffer
    mov edx, sizeof no_win_err; count
    int 80h
    jmp Terminate
.endif
mov window, eax
_invoke gtk_window_set_title,window, offset wincap
_invoke gtk_table_new,15, 15, 1
mov table,eax
_invoke gtk_container_add,window,table

_invoke gtk_label_new,offset labelcap
mov gtklabel,eax
_invoke gtk_table_attach_defaults,table,gtklabel,1, 8, 3, 7
_invoke gtk_button_new_from_stock,offset quitbut
mov button,eax
_invoke gtk_table_attach_defaults,table,button, 10, 14, 12, 14
;Show whole GUI
_invoke gtk_widget_show_all,window
;attache signals
_invoke g_signal_connect_data,window,offset sdel_event,offset exit_prog,0, 0, 0
_invoke g_signal_connect_data,button,offset sclicked,offset exit_prog,0, 0, 0
;Do it
_invoke gtk_main

;unload the libraries
invoke dlclose,gtk_lib
invoke dlclose,gobject_lib

;------------------------------------------------------------------------------
;Callback for closing window
exit_prog proc
    _invoke gtk_main_quit
exit_prog endp


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



    end _start



ecube

Nice work!,I wish linux had a enforced cross distro backend API, it'd be as fun coding on as windows is, but taking advantage of third party is good too :) is there any benefits to dynamically loading the .so files vs direct callin?

jcfuller

Quote from: E^cube on November 03, 2009, 12:39:45 AM
Nice work!,I wish linux had a enforced cross distro backend API, it'd be as fun coding on as windows is, but taking advantage of third party is good too :) is there any benefits to dynamically loading the .so files vs direct callin?

Most of my Linux experience is with BaCon: http://www.basic-converter.org/ (forum link at the bottom of the page)
It's author explained that with 1,267+ distros at last count, you can never be sure what libraries will be available so he uses dynamic loading. With it you can
provide an alternative  say  gui vs text. I know on windows  a program will just not run without any message as to  the problem if a library is missing,
and I assume the same may be true of Linux. It's quite a bit more asm coding but it does give you an alternative.

James

jcfuller

Attached are 3700+  gtk, gdk proto's. Thanks goes out to Peter van Eerten the author of BaCon who made them available for BaCon in a simple format  that was easy to parse for use with jwasm. There are some that had  variable parameters that my parser converted to a finite number that you might  have to adjust.
James

japheth

Quote from: jcfuller on November 03, 2009, 11:28:47 PM
Attached are 3700+  gtk, gdk proto's.

Using SYSCALL for GTK isn't the best idea. I realized this when I tried your sample with the Windows version of GTK+. It's better to use the C calling convention and then, for Linux, use JWasm's -zcw switch.

Here's the sample, adjusted for Win32. It "should" also work in Linux, what's changed are the INT 80h's to CRT calls puts() and exit().

;=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
;very simple jwasm gtk example
; create a Linux binary
; 1. assemble:       jwasm -elf -zcw -Fo=gtk01.o gtk01.asm
; 2. link with LD:   ld -s -o gtk01 gtk01.o -I/lib/ld-linux.so.2 `pkg-config --libs gtk+-2.0`
;
; create a Win32 binary with MinGW
; ( MinGW installed at C:\MinGW, GTK+ installed at C:\GTK )
; 1. assemble:       jwasm -elf gtk01.asm
; 2. link with LD:   ld -s -o gtk01.exe gtk01.obj -Lc:/gtk/lib
;                    -lgtk-win32-2.0.dll -lgobject-2.0.dll -Lc:\mingw/lib -lmsvcrt
;=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
    .386
    .model flat

    public _start

gtk_init proto c :DWORD, :DWORD
gtk_init_check proto c :DWORD, :DWORD
gtk_window_new proto c :DWORD
gtk_window_set_title proto c :DWORD, :DWORD
gtk_table_new proto c :DWORD, :DWORD, :DWORD
gtk_table_attach_defaults proto c :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
gtk_container_add proto c :DWORD, :DWORD
gtk_button_new_from_stock  proto c :DWORD
gtk_label_new proto c :DWORD
gtk_widget_show_all proto c :DWORD
gtk_main proto c
gtk_main_quit proto c
g_signal_connect_data proto c :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD

puts  proto c :DWORD
exit  proto c :DWORD

.data
no_int db 'No gtk_init',0
wincap db 'Hello World', 0
labelcap db 'jwasm gtk example', 0
quitbut db 'gtk-quit',0
no_win_err db 'No Window',0
sdel_event db 'delete-event',0
sclicked db 'clicked',0

    .data?
window dd ?
table dd ?
gtklabel dd ?
button dd ?

    .code

_start:    ; let the ritual begin.

;make sure we have gtk
invoke gtk_init_check,0,0
.if (eax == 0)
;mov eax, 4                      ; __NR_write
    ;mov ebx, 2                      ; stderr
    ;mov ecx, offset no_int; buffer
    ;mov edx, sizeof no_int; count
    ;int 80h
invoke puts, offset no_int
    jmp Terminate
.endif
;create window
invoke gtk_window_new, 0
.if (eax == 0)
;mov eax, 4                      ; __NR_write
    ;mov ebx, 2                      ; stderr
    ;mov ecx, offset no_win_err; buffer
    ;mov edx, sizeof no_win_err; count
    ;int 80h
invoke puts, offset no_win_err
    jmp Terminate
.endif
mov [window], eax

invoke gtk_window_set_title,[window], offset wincap
invoke gtk_table_new,15, 15, 1
mov [table],eax
invoke gtk_container_add,[window],[table]
invoke gtk_label_new,offset labelcap
mov [gtklabel],eax
invoke gtk_table_attach_defaults,[table],[gtklabel],1, 8, 3, 7
invoke gtk_button_new_from_stock,offset quitbut
mov [button],eax
invoke gtk_table_attach_defaults,[table],[button], 10, 14, 12, 14
;Show whole GUI
invoke gtk_widget_show_all,[window]
;attache signals
invoke g_signal_connect_data,[window],offset sdel_event,offset exit_prog,0, 0, 0
invoke g_signal_connect_data,[button],offset sclicked,offset exit_prog,0, 0, 0
;Do it
invoke gtk_main
;------------------------------------------------------------------------------
;Callback for closing window
exit_prog proc
    invoke gtk_main_quit
exit_prog endp
;------------------------------------------------------------------------------
Terminate:
    ;mov eax, 1     ; function (sys_exit)
    ;xor ebx, ebx   ; exit code
    ;int 80h        ; make Linux system call
invoke exit, 0

    end _start


jcfuller

Looks good and works on both platforms for me.
Attached are protos with "c"

James

ecube

you think you guys can provide a simple example that executes a system cmd and maybe lets you see the results. As to do most things on linux that seems to be the method, so for example shelling "ps" and lettin you get the results back? I believe you can do this using System("ps") in c/c++ idk what thats translates to in assembler.

ecube

#14
*update this below example works fine now that I updated ubuntu, that outputs the process list, not gotta figure out how to be able to get that list internally


; 1. assemble:       jwasm -elf -zcw -Fo=test1.o test1.asm
; 2. link with LD:    ld -s -o test1 test1.o -lc


    .386
    .model flat

    public _start

   system proto C :DWORD

.data
ps byte 'ps',0
  .code

_start:    ; let the ritual begin.
invoke system,addr ps

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

    end _start