Напишем простую программу , которая просто заносит число 20 в регистр eax ,
назовем ее first.s и откомрилируем ее командой
cc first.s
.globl main
main:
movl $20, %eax
ret
Следующая программа вычисляет факториал числа, находящегося в регистре eax. Результат вычислений сохраняется в регистре ebx.
.globl main
main:
movl $5, %eax
movl $1, %ebx
L1: cmpl $0, %eax // сравнить содержимое регистра eax с 0
je L2
// переход на L2 если 0==eax (je - jump if equal, перейти если равно)
imull %eax, %ebx // ebx = ebx*eax
decl %eax // decrement eax (уменьшить на 1)
jmp L1 // безусловный переход на L1
L2: ret
Здесь L1 и L2 -- это метки.
Напишем программу , создающую и вызывающую другую подпрограмму .
.globl main
main:
movl $10, %eax
call foo
ret
foo:
addl $5, %eax
ret
Для работы со стеком используются 2 регистра - esp/ebp
Адрес вершины стека хранится в esp . Стек растет от старших адресов к младшим .
Следующий пример показывает работу со стеком :
.globl main
main:
call foo
ret
foo:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $10, -4(%ebp)
movl %ebp, %esp
popl %ebp
ret
Напишем комбинированный пример из 2-х исходников - один main.c и другой sqr.s
и откомпилируем результат командой сс main.c sqr.s
//main.c
main()
{
int i = sqr(11);
printf("%d\n",i);
}
//sqr.s
.globl sqr
sqr:
movl 4(%esp), %eax
imull %eax, %eax
ret
Обратный вариант (вызов C-шной функции из ассемблера):
//print.c
print(int i)
{
printf("%d\n",i);
}
//main.s
.globl main
main:
movl $123, %eax
pushl %eax
call print
addl $4, %esp
ret
Наберем простую программу add.c
void main()
{
add(10,20);
}
int add(int i,int j)
{
int p = i + j;
return p;
}
После команды gcc -S add.c получим asm-вариант:
.file "add.c"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
subl $8, %esp
pushl $20
pushl $10
call add
addl $16, %esp
leave
ret
.size main, .-main
.globl add
.type add, @function
add:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 12(%ebp), %eax
addl 8(%ebp), %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
leave
ret
Если обьявить глобальную переменную , то она будет оттранслирована с префиксом
.globl
Можно дизассемблировать си-шные программы с помощью gdb .
Компилировать нужно с опциями :
cc -o myprogram -g myprogram.c -static
После этого запускаем gdb и говорим :
file myprogram
disassemble myprogram .
|