Hello GTK+ in Linux Assembly Language
学着书里的例子,写一个 GTK+ 程序:
# Hello GTK+ in Assembly
#
# as -g asm-gtk.s -o asm-gtk.s.o
# gcc asm-gtk.s.o `pkg-config --libs gtk+-2.0` -g -o test
# ./test
#
# Author: Pengu1n , Date: 20090508
#
.section .data
# Strings
APP_TITLE:
.ascii "GTK+ in ASM\0"
HELLO_ASM:
.ascii "Hello ........ ASM!\0"
BUTTON_CLICKED_INFO:
.ascii "Hello button clicked!\n\0"
.equ BUTTON_CLICKED_INFO_LEN, . - BUTTON_CLICKED_INFO # '.' means current address
# Constants
.equ GTK_WINDOW_TOPLEVEL, 0
.equ NULL, 0
# GTK+ Signal name
signal_button_clicked:
.ascii "clicked\0"
signal_delete_event:
.ascii "delete_event\0"
.section .bss
.equ WORD_SIZE, 4
.lcomm main_window, WORD_SIZE
.lcomm hello_button, WORD_SIZE
.section .text
.global main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp # args is here, but howto get &argc ?
# TODO: pass &argc, &argv to gtk_init
pushl $NULL
pushl $NULL
call gtk_init
addl $8, %esp
pushl $GTK_WINDOW_TOPLEVEL
call gtk_window_new
addl $4, %esp
movl %eax, main_window
pushl $APP_TITLE
pushl main_window
call gtk_window_set_title
addl $8, %esp
# Setup destory singal handler
pushl $NULL
pushl $NULL
pushl $NULL
pushl $destroy_handler
pushl $signal_delete_event
pushl main_window
call g_signal_connect_data # g_signal_connect is just a macro,
# so we must call g_signal_connect_data directly
addl $24, %esp
pushl $HELLO_ASM
call gtk_button_new_with_label
addl $4, %esp
movl %eax, hello_button
# Setup destory singal handler
pushl $NULL
pushl $NULL
pushl $NULL
pushl $button_clicked_cb
pushl $signal_button_clicked
pushl hello_button
call g_signal_connect_data
addl $24, %esp
pushl hello_button
pushl main_window
call gtk_container_add
addl $8, %esp
pushl main_window
call gtk_widget_show_all
addl $4, %esp
call gtk_main
movl $1, %eax
movl $0, %ebx
int $0x80
.type destroy_handler, @function
destroy_handler:
pushl %ebp
movl %esp, %ebp
call gtk_main_quit
movl $0, %eax
leave
ret
.type button_clicked_cb, @function
button_clicked_cb:
pushl %ebp
movl %esp, %ebp
movl $4, %eax # syscall __NR_write
movl $1, %ebx # stdout
movl $BUTTON_CLICKED_INFO, %ecx
movl $BUTTON_CLICKED_INFO_LEN, %edx
int $0x80
movl $0, %eax
leave
ret
#
# as -g asm-gtk.s -o asm-gtk.s.o
# gcc asm-gtk.s.o `pkg-config --libs gtk+-2.0` -g -o test
# ./test
#
# Author: Pengu1n , Date: 20090508
#
.section .data
# Strings
APP_TITLE:
.ascii "GTK+ in ASM\0"
HELLO_ASM:
.ascii "Hello ........ ASM!\0"
BUTTON_CLICKED_INFO:
.ascii "Hello button clicked!\n\0"
.equ BUTTON_CLICKED_INFO_LEN, . - BUTTON_CLICKED_INFO # '.' means current address
# Constants
.equ GTK_WINDOW_TOPLEVEL, 0
.equ NULL, 0
# GTK+ Signal name
signal_button_clicked:
.ascii "clicked\0"
signal_delete_event:
.ascii "delete_event\0"
.section .bss
.equ WORD_SIZE, 4
.lcomm main_window, WORD_SIZE
.lcomm hello_button, WORD_SIZE
.section .text
.global main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp # args is here, but howto get &argc ?
# TODO: pass &argc, &argv to gtk_init
pushl $NULL
pushl $NULL
call gtk_init
addl $8, %esp
pushl $GTK_WINDOW_TOPLEVEL
call gtk_window_new
addl $4, %esp
movl %eax, main_window
pushl $APP_TITLE
pushl main_window
call gtk_window_set_title
addl $8, %esp
# Setup destory singal handler
pushl $NULL
pushl $NULL
pushl $NULL
pushl $destroy_handler
pushl $signal_delete_event
pushl main_window
call g_signal_connect_data # g_signal_connect is just a macro,
# so we must call g_signal_connect_data directly
addl $24, %esp
pushl $HELLO_ASM
call gtk_button_new_with_label
addl $4, %esp
movl %eax, hello_button
# Setup destory singal handler
pushl $NULL
pushl $NULL
pushl $NULL
pushl $button_clicked_cb
pushl $signal_button_clicked
pushl hello_button
call g_signal_connect_data
addl $24, %esp
pushl hello_button
pushl main_window
call gtk_container_add
addl $8, %esp
pushl main_window
call gtk_widget_show_all
addl $4, %esp
call gtk_main
movl $1, %eax
movl $0, %ebx
int $0x80
.type destroy_handler, @function
destroy_handler:
pushl %ebp
movl %esp, %ebp
call gtk_main_quit
movl $0, %eax
leave
ret
.type button_clicked_cb, @function
button_clicked_cb:
pushl %ebp
movl %esp, %ebp
movl $4, %eax # syscall __NR_write
movl $1, %ebx # stdout
movl $BUTTON_CLICKED_INFO, %ecx
movl $BUTTON_CLICKED_INFO_LEN, %edx
int $0x80
movl $0, %eax
leave
ret
遗留问题:还没有找到如何传 argc, argv 给 gtk_init。
2009年9月23日 20:20
程序启动后,堆栈指针esp指向的就是参数个数,后面是第一个参数的指针,依次向下。参数指针后有一个0x00000000空位,然后是环境变量。
所以,取个数,就是(%esp),取参数依次加4,要取环境变量,则跳过
(1+参数个数+1)*4的偏移即可。
.section .data
output:
.asciz "There are %d params\n"
output2:
.asciz "%s\n"
.section .text
.globl _start
_start:
nop
movl (%esp), %ecx
pushl %ecx
pushl $output
call printf
addl $4, %esp
popl %ecx
movl %esp, %ebp
addl $4, %ebp
para_loop:
pushl %ecx
pushl (%ebp)
pushl $output2
call printf
addl $8, %esp
popl %ecx
addl $4, %ebp
loop para_loop
pushl $0
call exit
2011年12月15日 00:43
谢谢你这段代码。它已在过去的一个很大的帮助,我也有理由期待它有助于在未来。我使用谷歌翻译,所以我道歉,我的话引起任何误解。
在翻译的情况下是不合适的,这里是我的母语我的话:
Thank you for this code. It has been a great help in the past, and I have reason to expect it being helpful in the future. I am using Google translate, so I apologize for any misunderstanding caused by my words.
In case the translation is unsuitable, here are my words in my native language: