- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
在 x86 Linux 中如何直接使用 sysenter/syscall 实现系统调用?有人可以提供帮助吗?如果能把amd64平台的代码也展示一下就更好了。
我知道在 x86 中,我们可以使用
__asm__(
" movl $1, %eax \n"
" movl $0, %ebx \n"
" call *%gs:0x10 \n"
);
最佳答案
首先,你不能安全地使用 GNU C Basic asm("");
此语法 (没有输入/输出/clobber 约束)。您需要扩展 asm 来告诉编译器您修改的寄存器。见 inline asm in the GNU C manual和 inline-assembly tag wiki有关其他指南的链接,以了解有关诸如 "D"(1)
之类的内容的详细信息意味着作为 asm()
的一部分陈述。
我将向您展示如何通过编写一个程序来执行系统调用,该程序写 Hello World!
使用 write()
到标准输出系统调用。这是没有实现实际系统调用的程序源代码:
#include <sys/types.h>
ssize_t my_write(int fd, const void *buf, size_t size);
int main(void)
{
const char hello[] = "Hello world!\n";
my_write(1, hello, sizeof(hello));
return 0;
}
my_write
为了避免名称与“正常”发生冲突
write
, 由 libc 提供。此答案的其余部分包含
my_write
的来源对于 i386 和 amd64。
int 0x80
在您的汇编代码中,当然事先相应地设置了参数。可以通过
SYSENTER
做同样的事情,但实际执行这条指令是通过 VDSO 虚拟映射到每个正在运行的进程来实现的。自
SYSENTER
从未打算直接替代
int 0x80
API,它永远不会由用户级应用程序直接执行 - 相反,当应用程序需要访问某些内核代码时,它会调用 VDSO 中的虚拟映射例程(这就是代码中的
call *%gs:0x10
的用途),其中包含所有代码支持
SYSENTER
操作说明。由于指令的实际运作方式,有相当多的内容。
getpid
和
clock_gettime
非常简单,内核可以导出在用户空间中运行的代码 + 数据,因此 VDSO 永远不需要进入内核,甚至比
sysenter
快得多。可能。
int $0x80
更容易调用 32 位 ABI。
// i386 Linux
#include <asm/unistd.h> // compile with -m32 for 32 bit call numbers
//#define __NR_write 4
ssize_t my_write(int fd, const void *buf, size_t size)
{
ssize_t ret;
asm volatile
(
"int $0x80"
: "=a" (ret)
: "0"(__NR_write), "b"(fd), "c"(buf), "d"(size)
: "memory" // the kernel dereferences pointer args
);
return ret;
}
int 0x80
API比较简单。系统调用的编号转到
eax
注册,而系统调用所需的所有参数分别进入
ebx
,
ecx
,
edx
,
esi
,
edi
, 和
ebp
.系统调用号可以通过读取文件
/usr/include/asm/unistd_32.h
获得.
write(2)
.
memory
参数,这意味着指令列表中列出的指令引用内存(通过
buf
参数)。 (内联 asm 的指针输入并不意味着指向的内存也是输入。参见
How can I indicate that the memory *pointed* to by an inline ASM argument may be used?)
SYSCALL
的新指令。 .和原来的很不一样
SYSENTER
指令,并且从用户态应用程序中使用肯定要容易得多 - 它真的很像一个普通的
CALL
,实际上,并适应旧的
int 0x80
到新
SYSCALL
非常简单。 (除了它使用 RCX 和 R11 而不是内核堆栈来保存用户空间 RIP 和 RFLAGS 以便内核知道从哪里返回)。
rax
中。 ,但用于保存参数的寄存器现在几乎符合函数调用约定:
rdi
,
rsi
,
rdx
,
r10
,
r8
和
r9
以该顺序。 (
syscall
本身会破坏
rcx
so r10
is used instead of rcx
,让 libc 包装函数只使用
mov r10, rcx
/
syscall
。)
// x86-64 Linux
#include <asm/unistd.h> // compile without -m32 for 64 bit call numbers
// #define __NR_write 1
ssize_t my_write(int fd, const void *buf, size_t size)
{
ssize_t ret;
asm volatile
(
"syscall"
: "=a" (ret)
// EDI RSI RDX
: "0"(__NR_write), "D"(fd), "S"(buf), "d"(size)
: "rcx", "r11", "memory"
);
return ret;
}
"0"(callnum)
匹配约束可以写成
"a"
因为操作数 0(
"=a"(ret)
输出)只有一个寄存器可供选择;我们知道它会选择 EAX。使用你觉得更清楚的那个。
关于linux - 如何在内联汇编中通过 syscall 或 sysenter 调用系统调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9506353/
我有这个代码: System.err.print("number of terms = "); System.out.println(allTerms.size()); System.err
我有以下问题:在操作系统是 Linux 的情况下和在操作系统是 MacOs 的情况下,我必须执行不同的操作。 所以我创建了以下 Ant 脚本目标: /u
我正在调用 system("bash ../tools/bashScript\"This is an argument!\"&"),然后我正在调用 close(socketFD) 直接在 system
使用最初生成的随机元素来约束随机数组的连续元素是否有效。 例如:我想生成一组 10 个 addr、size 对来模拟典型的内存分配例程并具有如下类: class abc; rand bit[5:0
我正在创建一个必须使用system(const char*)函数来完成一些“繁重工作”的应用程序,并且我需要能够为用户提供粗略的进度百分比。例如,如果操作系统正在为您移动文件,它会为您提供一个进度条,
我即将编写一些项目经理、开发人员和业务分析师会使用的标准/指南和模板。目标是更好地理解正在开发或已经开发的解决方案。 其中一部分是提供有关记录解决方案的标准/指南。例如。记录解决/满足业务案例/用户需
在开发使用压缩磁盘索引或磁盘文件的应用程序时,其中部分索引或文件被重复访问(为了论证,让我们说一些类似于 Zipfian 分布的东西),我想知道什么时候足够/更好地依赖操作系统级缓存(例如,Debia
我们编写了一个 powershell 脚本,用于处理来自内部系统的图像并将其发送到另一个系统。现在,业务的另一部分希望加入其中,对数据进行自己的处理,并将其推送到另一个系统。打听了一下,公司周围有几个
我正在尝试朗姆酒我的应用程序,但我收到以下错误:System.Web.HttpUnhandledException:引发了“System.Web.HttpUnhandledException”类型的异
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
所以我在其他程序中没有收到此错误,但我在这个程序中收到了它。 这个程序是一个我没有收到错误的示例。 #include int main() { system("pause"); } // en
我在 c# System.URI.FormatExption 中遇到问题 为了清楚起见,我使用的是 Segseuil 的 Matlab 方法,并且它返回一个图片路径 result。我想为其他用户保存此
我正在尝试像这样设置文本框的背景色: txtCompanyName.BackColor = Drawing.Color.WhiteSmoke; 它不喜欢它,因为它要我在前面添加系统,例如: txtCo
请帮助我解决 System.StackOverflowException我想用 .aspx 将记录写入数据库我使用 4 层架构来实现这一切都正常但是当我编译页面然后它显示要插入数据的字段时,当我将数据
我使用了一些通常由系统调用的API。 因此,我将 android:sharedUserId="android.uid.system" 添加到 manifest.xml, 并使用来自 GIT 的 And
我正在尝试创建一个小型应用程序,它需要对/system 文件夹进行读/写访问(它正在尝试删除一个文件,并创建一个新文件来代替它)。我可以使用 adb 毫无问题地重新挂载该文件夹,如果我这样做,我的应用
我想从没有 su 的系统 priv-app 将/system 重新挂载为 RW。如何以编程方式执行此操作?只会用 Runtime.getruntime().exec() 执行一个 shell 命令吗
我正在尝试制作一个带有登录系统的程序我对此很陌生,但我已经连续工作 8 个小时试图解决这个问题。这是我得到的错误代码 + ServerVersion 'con.ServerVersion' threw
当我“构建并运行”Code::Blocks 中的程序时,它运行得非常好!但是当我从“/bin”文件夹手动运行它时,当它试图用 system() 调用“temp.bat”时,它会重置。这是为什么?它没有
我想使用 system/pipe 命令来执行具有特殊字符的命令。下面是示例代码。通过系统/管道执行命令后,它通过改变特殊字符来改变命令。我很惊讶地看到系统命令正在更改作为命令传递的文本。 run(ch
我是一名优秀的程序员,十分优秀!