Я изучаю asm на Linux (noobuntu 10.04), я получил следующий код от: http://asm.sourceforge.net/intro/hello.html
section .text
global _start ;must be declared for linker (ld)
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
Это - простое привет мир. Работает на Linux +, называет ядро непосредственно (по-видимому). Кто-либо может объяснить, что действительно продолжается здесь? Я думаю, что это читает целые числа в eax и ebx регистрах процессора и ecx, edx данные, и это определяет системный вызов, когда ядро называют. Если так, различные комбинации целых чисел определяют различные системные вызовы, когда интервал 0x80 называют?
Я не хорош со страницами справочника, но считал каждую связанную, которую я могу найти, какая-либо страница справочника говорит мне, что комбинации определяют что syscalls?
ЛЮБАЯ справка ценится. Линию за линией объяснение было бы удивительно... - Заранее спасибо Jeremy
Когда вы вызываете int 0x80
, ядро смотрит на значение регистра eax
, чтобы определить функцию, которую вы хотите вызвать (это «номер системного вызова»). В зависимости от этого числа остальные регистры интерпретируются как означающие определенные вещи. Вызов sys_write
ожидает, что регистры будут настроены следующим образом:
eax
содержит 4 ebx
содержит дескриптор файла ecx
содержит адрес данные для записи edx
содержат количество байтов Для получения дополнительной информации см. Системные вызовы Linux .
Существует слишком много системных вызовов, чтобы для каждого из них была своя инструкция на языке ассемблера.
Вместо этого вы вызываете инструкцию TRAP. Значение eax определяет, какой системный вызов будет вызван. Остальные регистры являются аргументами системного вызова.
Системные вызовы перечислены внутри ядра.
section .text
global _start ;must be declared for linker (ld)
Это просто заголовочный материал, "текстовый" раздел программы на ассемблере - это только машинные инструкции (в отличие от разделов данных, данных только для чтения и BSS). Строка global
сродни тому, что функция _start
является "публичной".
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
Из комментариев мы знаем, что перед нами функция sys_write
, поэтому мы можем man 2 write
узнать подробности. Прототип на языке C дает следующие параметры: fd
, *buf
и count
. Начиная с %ebx, мы видим, что они совпадают (%ebx = fd, %ecx = записываемая строка и %edx = длина строки). Затем, поскольку мы являемся пользовательским процессом, мы должны попросить ядро выполнить вывод. Это делается через интерфейс SYSCALL, и функции write()
(по-видимому) присваивается номер 4. INT 0x80
- это программное прерывание, которое вызывает процедуру SYSCALL ядра Linux.
Вы можете найти фактические номера всех syscalls в заголовочных файлах Linux (при условии, что они у вас установлены). В моей системе я проверил /usr/include/sys/syscall.h
, ведущий к /usr/include/asm/unistd.h
и затем к /usr/include/asm-i386/unistd.h
. Где (я вижу), #define __NR_write 4
.
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
Как и последние две строки предыдущего сегмента, здесь просто загружается идентификатор системного вызова и выполняется программное прерывание для выхода из программы (удаление отображения памяти и очистка).
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
Это раздел данных, здесь просто описываются переменные, которые мы использовали в нашей программе.