Проблема сборки с простой программой
-
29-09-2019 - |
Вопрос
Я пытаюсь выучить сборку с нуля. Я читал довольно много, но даже следующая простая программа, которую я нашел в справочнике, заставила меня оторваться:
section .data
msg db "Hello!", 0xa
len equ $ - msg
section .text
global _start
_start:
move edx, len
move ecx, msg
move ebx, 1
move eax, 4
int 0x80
move ebx, 0
move eax, 1
int 0x80
Теперь, очевидно, это должно печатать «Привет». Но я даже не знаю, что происходит на каких -либо этапах. Первые два этапа помещают длину сообщения и Messgae в две регистры, которые никогда больше не используются. Я не понимаю, почему.
Я не знаю, почему нужны четыре разных регистра.
Решение
int 80
это механизм в некоторых*а Unix-подобные операционные системы для создания системных вызовов.
Для этих вызовов регистры используются для определенных значений. От syscalls
файл:
0 STD NOHIDE { int nosys(void); } syscall nosys_args int
1 STD NOHIDE { void exit(int rval); } exit rexit_args void
2 STD POSIX { int fork(void); }
3 STD POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
4 STD POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
Вы можете увидеть, что номер 4 - это write
Позвоните и нужны три других параметра. Номер 1 есть exit
И нужен только код возврата.
При вызове, eax
Syscall, который вы делаете, пока ebx
, ecx
и edx
три параметра (при условии, что они все необходимы - exit
Например, только нужно только один).
Итак, вы можете прокомментировать код следующим образом:
move edx, len ; length of message (nbyte).
move ecx, msg ; message to print (buf).
move ebx, 1 ; file handle 1, stdout (fd).
move eax, 4 ; write syscall.
int 0x80 ; do it.
move ebx, 0 ; exit code (rval).
move eax, 1 ; exit syscall.
int 0x80 ; do it.
* A: Более поздние версии Linux представили новый интерфейс, который может использовать различные методы, в зависимости от того, что обеспечивает наилучшую скорость. Например, некоторые чипы Intel намного быстрее, если вы используете sysenter
скорее, чем int 80
.
Другие советы
Iirc int 0x80
Инструкция используется для вызова Syscall с помощью вектора прерывания. В вашем примере значений в ebx
и eax
используются, чтобы указать, какой SYSCALL вы собираетесь позвонить (вероятно, операция печати на Stdout).
Syscall знает, что edx
и ecx
должен содержать то, что будет напечатано.
На многих системах, int 80h это системный вызов ворота. Номер Syscall находится в eax
. ebx
, ecx
и edx
содержать дополнительные параметры:
move edx, len
move ecx, msg
move ebx, 1 ; fd 1 is stdout
move eax, 4 ; syscall 4 is write
int 0x80 ; write(1, msg, len)
move ebx, 0
move eax, 1 ; syscall 1 is exit
int 0x80 ; exit(0)
Когда вы называете системный вызов, генерируется «int 'Mnemonic, перерыв системы». Это вроде «прыгает» в системную функцию, которая в этом случае печатает выход (зависит от EAX).
Это прерывание использует все эти регистры, чтобы знать, что делать. Прерывание читает EAX, проверьте, какую функцию вы хотите, и использует другие регистры для этого.
EAX - это номер функции, 4 означает SYS_WRITE, который записывает строку в дескриптор потока / файла.
Теперь он знает, что вы хотите что -то написать в какое -то место, а затем использует другие регистры для этой информации.
Для EAX = 4 и INT 0x80 Это значение для других регистров:
ebx = вывод (1 = stdout)
ecx = адрес строки
EDX = длина строки
Вы можете прочитать это:
http://www.intel.com/assets/ja_jp/pdf/manual/253665.pdf
Раздел 6.4 У него есть некоторые вещи о прерывании и исключениях.
И вы можете начать писать код сборки Intel 80x86, который проще и проще понять, вот некоторые ссылки:
Mnemonics/Code Tables Cheatsheet:http://www.jegerlehner.ch/intel/
Некоторые введенные сайты:http://mysite.du.edu/~Ettle/math/8086.htm.http://www.malware.org/teaching/assembly.htm.