为了获得描述文件的
struct stat
,我们可以调用 *stat 系列函数,这些函数将用结构值填充传递的指针所指向的内存。
在C中我们可以调用POSIX.1-2008offsetof宏,但它是一个宏,在汇编中不可用。
如何从程序集中确定结构体的大小以及如何确定字段的偏移量,以便可以提取必要的字段,例如
st_size
,st_mode
等?
平台的 ABI 决定了 C 结构体填充的规则。例如,x86-64 Linux 使用 x86-64 System V ABI。
困难的方法:阅读 ABI 并自己解决。 x86 标签 wiki 中的链接。 (实际上并不那么难,结构内的对齐/填充规则对于 x86-64 System V ABI 来说非常简单:每个成员都按声明顺序排列,并且自然对齐。这可能需要填充。Windows x64 有自己的结构布局规则并不总是产生相同的布局。)
简单的方法:让编译器通过编写一个存储到结构体中的函数来计算偏移量,然后查看 asm.h 文件。例如
#include <sys/stat.h>
void foo(struct stat *st) {
st->st_size = 1;
st->st_mode = 2; // different numbers so you know which field is which in the output
}
mov QWORD PTR [rdi+48], 1
mov DWORD PTR [rdi+24], 2
ret
(来自 Godbolt 编译器浏览器)
查看其他一些问答,其中的答案旨在自动化生成定义的过程,例如
#define
或 .equ
,或 NASM equ
:
在这种情况下,使用 templated 内联汇编器部分并以
offsetof(...)
作为输入参数来编写 C 模块可能会更容易:
#include <stddef.h>
#include <sys/stat.h>
int my_function(int arg0, void *arg1) {
int result;
__asm__(
"some_command %[a0], %[a1], %[mode_offset]"
: [result] "=r"(result)
: [a0] "r"(arg0), [a1] "r"(arg1),
[mode_offset] "ri"(offsetof(struct stat, st_mode))
: "cc");
return result;
}