We have here a "C style main". So the "_start" label is in the "startup" code. At that point, we have:
??? actual strings of args and env?
dword 0 ; end of envp
??? ; pointers to 0-terminated strings for
; environment variables.
dword 0 ; end of argv
??? ; pointers to 0-terminated strings for
; command line parameters - at least 1!
pointer to name of this program
dword argc
Now, "behind our back", C calculates envp and argv, and pushes them...
envp
argv
argc
Then, C calls main:
return address for main's caller
That's where we get control. Now, in "our" code, we push ebp.
old ebp
So... "ebp + 8" is argc and "ebp + 12" is argv. Looks right to me. Did you miss the return address of main's caller?
Best,
Frank
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I don't know much about gcc - I try to avoid it. Strictly speaking, it's ld that does the linking, gcc just passes the command line to ld. In this case, since there's nothing to compile, that's all it does. By default, it links in some "startup" code - crt0.o or so - which does some preliminary housekeeping and calls main. You can override this with "--nostartfiles" (maybe only one "-").
I don't know what command line(s) you used to build your other asm program, but if argc was the first thing on the stack, it wasn't called. The "call" instruction puts a return address on the stack. The only thing C really has to do with it is that it "hides" a call instruction...
Another thing gcc knows to pass on the command line to ld, if you're using shared libraries (which is what GTK+ is... and libc), is the correct name for the dynamic linker. By default, ld looks for /lib/ld-linux.so.1. This doesn't exist, on my system. If I've got a file like:
extern puts
global _start
_start:
push msg
call puts
...
Assemble it with "nasm -f elf myfile.asm", as usual, and link with "ld -o myprog myprog.o -lc", attempting to run it results in "no such file or directory", even though the file is plainly there. Most confusing!!! Gotta tell ld "-I/lib/ld-linux.so.2" (or "--dynamic-linker ... - "-I" - interpreter - is shorter :)
Lessee - C expects functions to preserve ebx, esi, and edi (as well as the more obvious ebp and esp). If you're writing something to be called from C, you have to take care of this. If you're calling a C function... the other registers may be altered by the function - save 'em if you need 'em!
Lessee - printf expects "floats" to be double precision...
sub esp, 8
fst qword [esp]
push format_string
call printf
I guess that's all I know right now...
Best,
Frank
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
don't using Linux I've no glue your [esp+12] really is the argv vector, but generally this argv will be a pointer to a pointer - as defined with **argv. So, you have to de-reference your pointer twice! For doing that, take the mov version of your code
mov eax, [esp+12] ;bits32 asumed
mov eax, [eax] ;2nd de-reference
call ...
That should work!
martin
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
hey that's really cool, it's a pointer to an array of pointers. so i get the argument i pass to my prog this way:
mov eax, [ebp+12]
mov eax, [eax+4]
call WriteStr
thanks
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
;=================================================
; gtk-test.asm by Yeoh HS
; 26 January 2004
; A very simple GTK+ program. :-)
; My first GTK program built using NASM
;
; Credits To: numit_or for his gnometest example
;
;================================================
;# Makefile --------------------------------------
;GTK_LIBS = `pkg-config --libs gtk+-2.0`
;
;gtk-test: gtk-test.o
; gcc $(GTK_LIBS) -Wall -s -o gtk-test gtk-test.o
;
;gtk-test.o: gtk-test.asm
; nasm -f elf -l gtk-test.lst gtk-test.asm
;
;clean:
; rm *.o gtk-test
;# ----------------------------------- End Makefile
GLOBAL main
GTK_WINDOW_TOPLEVEL equ 0
EXTERN gtk_init
EXTERN gtk_window_new
EXTERN gtk_main
EXTERN gtk_widget_show
EXTERN exit
;------------------------- Data Section ---
SECTION .data USE32
;------------------------- Code Section ---
SECTION .text USE32
main:
push ebp
mov ebp, esp
sub esp, 8
lea eax,[ebp+8]
lea ebx,[ebp+12]
push ebx
push eax
call gtk_init
add esp, 8
push GTK_WINDOW_TOPLEVEL
call gtk_window_new
add esp, 4
mov [appPtr],eax
push dword [appPtr]
call gtk_widget_show
add esp, 4
call gtk_main
push dword 0
call exit
; end of main
;--------------- Uninitialized Data Section ---
SECTION .bss
appPtr: resd 1
; end of file
To see more Linux nasm examples, go to this group:
http://groups.yahoo.com/group/linux-nasm-users
Best Regards,
Yeoh
--
New code:
gtk-hello.asm uploaded to linux-nasm-users group.
Uploaded gtk-hello2.zip to the group:
http://groups.yahoo.com/group/linux-nasm-users
This version connects a button to a callback function. When button is clicked the program quits.
Best Regards,
Yeoh
--
I think you can use one 'USE32' at the beginning of the file, but not 'USE32' after every SECTION.
"-f elf" defaults to 32-bits anyway, so it really isn't neccessary at all...
Best,
Frank
It would be good for beginners if you commented on each line of code.
good job
Please could you comment your code?
my makefile, copied from your source:
1 # Makefile --------------------------------------
2 GTK_LIBS = `pkg-config --libs gtk+-2.0`
3
4 gtk-test: gtk-test.o
5 gcc $(GTK_LIBS) -Wall -s -o gtk-test gtk-test.o
6
7 gtk-test.o: gtk-test.asm
8 nasm -f elf -l gtk-test.lst gtk-test.asm
9
10 clean:
11 rm *.o gtk-test
12 # ----------------------------------- End Makefile
execution:
# make
Makefile:5: *** missing separator. Stop.
AC
i don't understand the beginning
push ebp
mov ebp, esp
sub esp, 8
lea eax,[ebp+8]
lea ebx,[ebp+12]
i think the stack is as follows
^ 0
| argv (=pointer to "gtk-test")
| argc (=1)
there is only one push, then ebp is assigned the adress of esp, that is, 4 bytes below argc
[ebp+8] should be argv and [ebp+12] should be 0 !?
Sheee... lemme see...
We have here a "C style main". So the "_start" label is in the "startup" code. At that point, we have:
??? actual strings of args and env?
dword 0 ; end of envp
??? ; pointers to 0-terminated strings for
; environment variables.
dword 0 ; end of argv
??? ; pointers to 0-terminated strings for
; command line parameters - at least 1!
pointer to name of this program
dword argc
Now, "behind our back", C calculates envp and argv, and pushes them...
envp
argv
argc
Then, C calls main:
return address for main's caller
That's where we get control. Now, in "our" code, we push ebp.
old ebp
So... "ebp + 8" is argc and "ebp + 12" is argv. Looks right to me. Did you miss the return address of main's caller?
Best,
Frank
yeah, i missed that
i didn't understand because there is no "return adress" in my other asm prog :
_main:
pop eax ; argc !
so, this gtk-test is linked with gcc, and that implies "C-style functions" ?
any other things like this to know when using gcc ?
I don't know much about gcc - I try to avoid it. Strictly speaking, it's ld that does the linking, gcc just passes the command line to ld. In this case, since there's nothing to compile, that's all it does. By default, it links in some "startup" code - crt0.o or so - which does some preliminary housekeeping and calls main. You can override this with "--nostartfiles" (maybe only one "-").
I don't know what command line(s) you used to build your other asm program, but if argc was the first thing on the stack, it wasn't called. The "call" instruction puts a return address on the stack. The only thing C really has to do with it is that it "hides" a call instruction...
Another thing gcc knows to pass on the command line to ld, if you're using shared libraries (which is what GTK+ is... and libc), is the correct name for the dynamic linker. By default, ld looks for /lib/ld-linux.so.1. This doesn't exist, on my system. If I've got a file like:
extern puts
global _start
_start:
push msg
call puts
...
Assemble it with "nasm -f elf myfile.asm", as usual, and link with "ld -o myprog myprog.o -lc", attempting to run it results in "no such file or directory", even though the file is plainly there. Most confusing!!! Gotta tell ld "-I/lib/ld-linux.so.2" (or "--dynamic-linker ... - "-I" - interpreter - is shorter :)
Lessee - C expects functions to preserve ebx, esi, and edi (as well as the more obvious ebp and esp). If you're writing something to be called from C, you have to take care of this. If you're calling a C function... the other registers may be altered by the function - save 'em if you need 'em!
Lessee - printf expects "floats" to be double precision...
sub esp, 8
fst qword [esp]
push format_string
call printf
I guess that's all I know right now...
Best,
Frank
my asm prog wasn't called, it's a simple asm code linked with ld:
nasm -f els prog.asm
ld -s -o prog prog.o
now, i'm trying to print the arg with the "C-like" code, and i can't
with prog.asm, very simple:
_start:
mov esi, [esp+4]
call WriteString
with this "C-like" asm code:
main:
push ebp
mov ebp, esp
mov esi, [ebp+12]
call WriteString ; doesn't work :-(
note, i tried using both lea and mov (can't find out the difference)
Hi,
don't using Linux I've no glue your [esp+12] really is the argv vector, but generally this argv will be a pointer to a pointer - as defined with **argv. So, you have to de-reference your pointer twice! For doing that, take the mov version of your code
mov eax, [esp+12] ;bits32 asumed
mov eax, [eax] ;2nd de-reference
call ...
That should work!
martin
gives a segfault :(
ahh, no ! it works ^^ thank you
hey that's really cool, it's a pointer to an array of pointers. so i get the argument i pass to my prog this way:
mov eax, [ebp+12]
mov eax, [eax+4]
call WriteStr
thanks