Привет всем.Linux x86_64 программирование гнезд сборки
Итак, я изучаю сборку.
И в соответствии с моими обычными шагами обучения с любым новым языком, который я забираю, я пришел к созданию сетей с сборкой.
Который, к сожалению, не так уж хорошо, поскольку я очень сильно потерпел неудачу на шаге 0, который будет получать сокет, через который может начаться общение.
Код сборки должен быть примерно равен следующему коду C: (. Давайте игнорировать тот факт, что он не закрывает сокет сейчас)
#include <stdio.h>
#include <sys/socket.h>
int main(){
int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);
}
Так вот что я сделал до сих пор :
- Проверен the manual. Что означало бы, что мне нужно сделать
socketcall()
, все это хорошо и хорошо. Проблема начинается с того, что ему понадобитсяint
, который описывает, какой сокет должен делать. Вызовы manpage не помогают много с этим или как он только описывает, что:
Об одном некоторых архитектуры, например, x86-64 и ARM-нет SOCKETCALL() системного вызова; вместо сокета (2), accept (2), bind (2) и , так что действительно реализованы как отдельные системные вызовы.
Но нет таких вызовов в первоначальном списке системных вызовов - и, насколько я знаю,
socket()
,accept()
,bind()
,listen()
и т.д., звонки сlibnet
и не из ядра. Это меня совершенно смутило, поэтому я решил скомпилировать приведенный выше кодC
и проверить его с помощьюstrace
. Это дало следующее:гнездо (PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
Хотя это не заставило меня ближе к знанию, что
socket()
является она объяснить это аргументы. Для ведьмы я, похоже, не нашел правильной документации (снова). Я думал, чтоPF_INET
,SOCK_STREAM
,IPPROTO_IP
будет определен в<sys/socket.h>
, но мойgrep
-для них, похоже, не нашел ничего полезного. Поэтому я решил просто закрыть его, используяgdb
в тандеме сdisass main
, чтобы найти значения.Это дало следующие результаты:свалки ассемблера для функции главного: 0x00000000004004fd < +0>: нажимной RBP 0x00000000004004fe < +->: мы ПОР RSP 0x0000000000400501 < +4>: Sub RSP, 0x10 0x0000000000400505 < +8>: мы EDX, 0x0 0x000000000040050a < +13>: мы еси, 0x1 0x000000000040050f < +18>: MOV EDI, 0x2 0x0000000000400514 < +23>: вызов 0x400400 0x0000000000400519 < +28>: мы DWORD PTR [rbp-0x4], eax 0x000000000040051c < +31>: оставить
0x000000000040051d < +32>: ret
Конец сборщика самосвалов.В моем опыте это означало бы, что
socket()
получает его параметры изEDX
(PF_INET
),ESI
(SOCK_STREAM
) иEDI
(IPPROTO_IP
). Что было бы странно для syscall (поскольку соглашение с системами linux syscalls было бы использоватьEAX
/RAX
для номера вызова и других регистров для параметров в порядке возрастания, напримерRBX
, ,RDX
...). Тот факт, что это beaingCALL
-ed, а неINT 0x80
'd также подразумевает, что это на самом деле не системный вызов, а нечто, вызываемое из общего объекта. Или что-то.Но с другой стороны. Передача аргументов в регистрах очень странная для чего-то, что
CALL
-ed. Обычно, насколько я знаю, аргумент для вызываемых вещей должен бытьPUSH
-ed на стек, поскольку компилятор не может знать, какие регистры они будут пытаться использовать.Такое поведение становится еще более интересно, при проверке полученного двоичного файла с
ldd
:Linux-vdso.so.1 (0x00007fff4a7fc000) libc.so.6 =>/Библиотека/x86_64-Linux-ГНУ/libc.so.6 (0x00007f56b0c61000) /lib64/ld-linux-x86-64.so.2 (0x00007f56b1037000)
Там, как представляется, нет сетевой библиотеки не связаны между собой.
И это тот момент, когда у меня кончились идеи.
Так я прошу следующее:
- документация, которая описывает фактические системные вызовы в
x86-64
Linux Kernel и их связанные с ними номера. (Предпочтительно в качестве файла заголовка дляC
.) - Заголовочные файлы, которые определяют
PF_INET
,SOCK_STREAM
,IPPROTO_IP
, поскольку это действительно меня беспокоит, что я не смог найти их в своей собственной системе. - Возможно, учебник для создания сетей в сборке на
x86-64
linux. (Дляx86-32
это легко найти материал, но по какой-то причине я подошел пустым с 64-битным материалом.)
Спасибо!
Вы не найдете определения в заголовке, который вы включаете в grep, потому что он, в свою очередь, включает менее портативный заголовочный файл, который обеспечивает фактическое значение (возможно, несколько таких слоев). Большинство процессоров с умеренным или большим числом регистров традиционно программируются через ABI, которые используют первые несколько аргументов в указанных регистрах для повышения эффективности, прежде чем прибегать к стеку для остатка. –
'networking with assembly' - вы действительно выбрали это как учебное упражнение? Кто-то держит вас под прицелом? –