许多linux / x86-64系统调用接受指向结构的指针作为参数。
例如,stat(2)
的第二个参数是struct stat*
...
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
这意味着如果你想从纯汇编中调用系统调用,你必须知道每个类型有多大的规则,以及成员之间是否有任何填充用于对齐目的,等等。
C标准是否将此开放定义为(编译器)实现定义,还是可以从标准确定(假设原始类型大小已知)?
如果它保持打开状态,内核或x86-64架构是否仍然定义它?或者仅仅是编译内核的编译器的问题?
(给出了结构的一些成员,我需要计算该成员相对于结构地址的起始偏移量)
答案 0 :(得分:14)
结构的布局未在C标准中定义,但在ABI定义中,在您的情况下是System V AMD64 ABI。也就是说,通常布局是依赖于操作系统的,并且所有针对该操作系统的编译器必须符合ABI(尽管如果您知道自己在做什么,大多数编译器都会选择生成不同的布局)。 ABI还定义了如何将参数传递给函数,如何返回值,哪些寄存器必须在调用之间保留,等等。
您需要的ABI定义应该在http://www.x86-64.org/上提供(似乎已关闭)
答案 1 :(得分:0)
在Linux / x86-64下:
一个字节是8位。大小和内存地址以1个字节为单位。
原始类型的对齐方式与其大小相同:
原始类型大小(和对齐)是:
bool 1
char 1
short 2
int 4
long 8
long long 8
__int128 16
void* 8
float 4
double 8
long double 16
__float128 16
__m64 8
__m128 16
结构(和联合)对齐是任何组件的最大对齐。
每个结构成员都被赋予适当的最低可用偏移量 对准。
结构的大小向上舍入到其最接近的对齐倍数。
结构和联合对象可能需要填充以满足大小和对齐 限制。任何填充的内容都是未定义的。
小于16个字节的数组具有其元素类型的对齐方式。
16字节或更长的数组具有(a)16中较高者的对齐; (b)元素类型的对齐。