Linux x86_64汇编套接字编程 [英] Linux x86_64 assembly socket programming
问题描述
大家好。
所以我正在学习汇编语言。
按照我通常学习的任何新语言的学习步骤,我已经达到了与汇编语言联网的地步。
遗憾的是,这不是很顺利,因为我在步骤0几乎失败了,这将是获得一个套接字,通过它可以开始通信。
汇编代码应大致等于以下C代码:
#include <stdio.h>
#include <sys/socket.h>
int main(){
int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);
}
(让我们忽略它目前没有关闭套接字这一事实。)
以下是我到目前为止所做的工作:
- 已选中the manual。这意味着我需要做一个
socketcall()
,这一切都很好。问题开始于它需要一个int
来描述它应该进行哪种类型的socketcall。调用manpage对此也没有太大帮助,因为它只描述:
在某些体系结构(例如x86-64和ARM)上没有 socketcall()系统调用;而不是Socket(2)、Accept(2)、Bind(2)和 因此,On实际上是作为单独的系统调用实现的。
但是在最初的syscall列表中没有这样的调用-据我所知,
socket()
、accept()
、bind()
、listen()
等都是来自libnet
的调用,而不是来自内核的调用。这让我非常困惑,所以我决定编译上面的C
代码,并用strace
检查它。这产生了以下结果:套接字(PF_INET,SOCK_STREAM,IPPROTO_IP)=3
虽然这并没有让我更深入地了解
转储函数main的汇编器代码: 0x00000000004004fd<;+0>:推流RBP 0x00000000004004fe<;+1>:MOV RBP,RSP 0x0000000000400501<;+4>:子RSP,0x10 0x0000000000400505<;+8>:MOV edX,0x0 0x000000000040050a<;+13>:MOV ESI,0x1 0x000000000040050f<;+18>:MOV EDI,0x2 0x0000000000400514<;+23>:呼叫0x400400 0x0000000000400519<;+28>:MOV双字PTR[RBP-0x4],EAX 0x000000000040051c<;+31>:离开socket()
是什么,但它确实解释了它的参数。对于WITCH,我似乎(再一次)找不到合适的文档。我以为PF_INET
、SOCK_STREAM
、IPPROTO_IP
会在<sys/socket.h>
中定义,但是我对它们的grep
似乎没有什么用处。因此,我决定临时使用gdb
和disass main
来查找值。这将产生以下输出:
0x000000000040051d<;+32>:返回
汇编程序转储结束。根据我的经验,这意味着
socket()
从EDX
(PF_INET
)、ESI
(SOCK_STREAM
)和EDI
(IPPROTO_IP
)获取参数。这对于系统调用来说是奇怪的(因为Linux系统调用的惯例是以递增的顺序使用EAX
/RAX
作为呼叫号,使用其他寄存器作为参数,例如。RBX
,RCX
,RDX
.)。这是由CALL
而不是INT 0x80
执行的这一事实也意味着这实际上不是一个系统调用,而是从共享对象调用的某个东西。然后再说一遍。对于
CALL
-ed的东西,在寄存器中传递参数是非常奇怪的。正常情况下,据我所知,调用对象的参数应该PUSH
放到堆栈上,因为编译器不知道它们会尝试使用什么寄存器。当使用
检查生成的二进制文件时,此行为变得更加奇怪ldd
:linux-vdso.so.1(0x00007fff4a7fc000) libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6(0x00007f56b0c61000) /lib64/ld-linux-x86-64.so.2(0x00007f56b1037000)
似乎没有链接的网络库。
这就是我没有主意的地方。
所以我有以下要求:
- 描述
x86-64
Linux内核的实际系统调用及其相关编号的文档。(最好作为C
的头文件。) - 定义
PF_INET
、SOCK_STREAM
、IPPROTO_IP
的头文件,因为在我自己的系统上找不到它们真的很让我头疼。 - 可能是关于
x86-64
Linux上的汇编联网的教程。(对于x86-32
很容易找到材料,但是由于某种原因,我没有找到64位的内容。)
谢谢!
推荐答案
64位调用约定确实使用寄存器在用户空间和系统调用中传递参数。如您所见,用户空间约定是rdi
、rsi
、rdx
、rcx
、r8
、r9
。对于系统调用,使用r10
而不是被syscall指令销毁的rcx
。有关详细信息,请参阅wikipedia或ABI文档。
/usr/include/x86_64-linux-gnu/bits/socket.h
和/usr/include/linux/in.h
。
对于系统调用列表,Google one是微不足道的,比如this。当然,您也可以随时查看内核源代码。
这篇关于Linux x86_64汇编套接字编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!