Автор: lonesome TSH/Digital Daemons
Дата: 17.04.2003
Раздел: Низкоуровневое программирование в Linux
#Файл sample1.s
.globl _start #Метка _start - глобальная
#Она необходима компоновщику для определения точки входа
.code32 #Директива определяющая разрядность
.text #Сегмент кода
_start: #Точка входа
movl $4, %eax
movl $1, %ebx
movl $message, %ecx
movl $mlen, %edx
int $0x80 #write (4, 1, message, mlen)
movl $1, %eax
xorl %ebx, %ebx
int $0x80 #exit(0)
.data #Сегмент данных
message: .asciz "Hello Linux\n" #asciz - последовательность байт,
# заканчивающаяся нулем
# (C-строка)
mlen = .-message#Констнта mlen
Компиляция: as sample0.s -o sample0.oДействительно, зачем создавать функцию _start самому, когда она уже есть в GLIBC?
.globl main #Основная функция программы с точки зрения GLIBC - main
.text
main: #На нее GLIBC и передаст управление
movl $11, %eax #11 - номер системного вызова execve
movl $program, %ebx
movl $null, %ecx
movl $null, %edx
int $0x80 #execve (program, null, null)
#execve не возвращается в случае успешного вызова
#весь код программы будет переписан кодом вызванной программы
.data
program: .asciz "/bin/date" #Запускаемая программа
null:.long 0 #Указатель на NULL
Обратите внимание на отличие компиляции если мы используем GLIBC:
gcc sample1.s -o sample1 - как видите, всю черную работу по подключению необходимых библиотек мы оставили GCCДействительно, зачем генерировать прерывание системного вызова самому, когда это можно предоставить GLIBC?
.globl main
.globl printf
.text
main:
pushl $message3
pushl $message2
pushl $message1
pushl $message
call printf #printf(message, message1, message2, message3)
addl $16, %esp #А стек по конвенции C необходимо восстановить
#Мы ведь клали в него 4 аргумента по 4 байта каждый
ret
.data
message:.asciz "It is not so easy %s %s %s"
message1:.asciz "to write"
message2:.asciz "printf in assembly."
message3:.asciz "Better use glibc's printf\n"