相关疑难解决方法(0)

如何从用户空间访问系统调用?

我读了LKD 1中的一些段落, 我无法理解下面的内容:

从用户空间访问系统调用

通常,C库提供对系统调用的支持.用户应用程序可以从标准头中提取函数原型并与C库链接以使用您的系统调用(或者库例程,而该库例程又使用您的系统调用).但是,如果您刚刚编写了系统调用,那么glibc已经支持它是值得怀疑的!

值得庆幸的是,Linux提供了一组用于包装系统调用访问的宏.它设置寄存器内容并发出陷阱指令.这些宏被命名,其中介于0和6之间.该数字对应于传递给系统调用的参数数量,因为宏需要知道预期的参数数量,从而推入寄存器.例如,考虑系统调用,定义为_syscalln()nopen()

long open(const char *filename, int flags, int mode)
Run Code Online (Sandbox Code Playgroud)

在没有显式库支持的情况下使用此系统调用的syscall宏将是

#define __NR_open 5
_syscall3(long, open, const char *, filename, int, flags, int, mode)
Run Code Online (Sandbox Code Playgroud)

然后,应用程序可以简单地调用open().

对于每个宏,有2 + 2×n个参数.第一个参数对应于系统调用的返回类型.第二个是系统调用的名称.接下来是系统调用顺序的每个参数的类型和名称.的__NR_open定义是在<asm/unistd.h>; 它是系统呼叫号码.的_syscall3宏扩展到与联汇编C函数; 程序集执行上一节中讨论的步骤,将系统调用号和参数推送到正确的寄存器中,并发出软件中断以陷入内核.将此宏放在应用程序中是使用open()系统调用所需的全部内容.

让我们编写宏来使用我们精彩的新foo()系统调用,然后编写一些测试代码来展示我们的努力.

#define __NR_foo 283
__syscall0(long, foo)

int main ()
{
        long stack_size;

        stack_size = foo ();
        printf ("The kernel stack size is %ld\n", stack_size);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

是什么 …

linux system-calls

17
推荐指数
2
解决办法
2万
查看次数

x86_64汇编Linux系统调用混淆

我目前正在学习Linux上的汇编语言.我一直在使用"从头开始编程"一书,所有的例子都是32位的.我的操作系统是64位,我一直在尝试以64位的方式完成所有示例.我遇到了麻烦:

.section .data

.section .text
.global _start
_start:
movq $60, %rax
movq $2, %rbx
int $0x80
Run Code Online (Sandbox Code Playgroud)

这只是调用Linux退出系统调用或它应该.相反,它会导致SEG FAULT,而当我改为执行此操作时

.section .data

.section .text
.global _start
_start:
movq $1, %rax
movq $2, %rbx
int $0x80
Run Code Online (Sandbox Code Playgroud)

有用.显然,问题是我转向%rax的价值.我在第二个例子中使用的$ 1值是"从头开始编程"所说的,但互联网上有多个来源说64位系统呼叫号码是60美元.参考 我做错了什么?还应该注意哪些其他问题以及我应该使用什么作为参考?万一你需要知道,我在第5章"从头开始编程".

64-bit assembly 32-bit gnu-assembler system-calls

16
推荐指数
4
解决办法
2万
查看次数

如何在没有printf的汇编级编程中从c库中打印整数?

任何人都可以告诉我纯粹的汇编代码以十进制格式显示寄存器中的值吗?请不要建议使用printf hack,然后使用gcc进行编译.

描述:

好吧,我做了一些研究和NASM的一些实验,并认为我可以使用c库中的printf函数来打印整数.我是通过使用GCC编译器编译目标文件来完成的,所有工作都很公平.

但是,我想要实现的是以十进制形式打印存储在任何寄存器中的值.

我做了一些研究,发现DOS命令行的中断向量021h可以显示字符串和字符,而2或9位于ah寄存器中,数据在dx中.

结论:

我找到的所有示例都没有显示如何在不使用C库的printf的情况下以十进制形式显示寄存器的内容值.有没有人知道如何在装配中这样做?

x86 assembly nasm cpu-registers

16
推荐指数
3
解决办法
3万
查看次数

在64位Linux和64位处理器上运行32位汇编代码:解释异常

我遇到了一个有趣的问题.我忘了我正在使用64位机器和操作系统并写了一个32位汇编代码.我不知道如何编写64位代码.

这是Linux上Gnu Assembler(AT&T语法)的x86 32位汇编代码.

//hello.S
#include <asm/unistd.h>
#include <syscall.h>
#define STDOUT 1

.data
hellostr:
    .ascii "hello wolrd\n";
helloend:

.text
.globl _start

_start:
    movl $(SYS_write) , %eax  //ssize_t write(int fd, const void *buf, size_t count);
    movl $(STDOUT) , %ebx
    movl $hellostr , %ecx
    movl $(helloend-hellostr) , %edx
    int $0x80

    movl $(SYS_exit), %eax //void _exit(int status);
    xorl %ebx, %ebx
    int $0x80

    ret
Run Code Online (Sandbox Code Playgroud)

现在,这个代码应该在32位处理器和32位操作系统上正常运行吗?我们知道64位处理器向后兼容32位处理器.所以,这也不是问题.问题出现是因为64位操作系统和32位操作系统中的系统调用和调用机制不同.我不知道为什么但是他们改变了32位linux和64位linux之间的系统调用号码.

asm/unistd_32.h定义:

#define __NR_write        4
#define __NR_exit         1
Run Code Online (Sandbox Code Playgroud)

asm/unistd_64.h定义:

#define __NR_write              1
#define __NR_exit               60
Run Code Online (Sandbox Code Playgroud)

无论如何使用宏而不是直接数字都可以获得回报.它确保正确的系统呼叫号码.

当我组装和链接并运行程序时.

$cpp hello.S hello.s …
Run Code Online (Sandbox Code Playgroud)

linux x86 assembly gdb x86-64

14
推荐指数
2
解决办法
1万
查看次数

x86程序集:在Linux上进行系统调用之前是否应该保存所有寄存器?

我有以下代码打开文件,将其读入缓冲区然后关闭文件.

关闭文件系统调用要求文件描述符号在ebx寄存器中.ebx寄存器在读取系统调用之前获取文件描述符编号.我的问题是,在我进行读取系统调用之前,我应该将ebx寄存器保存在堆栈中还是某个地方(可以将80h垃圾邮件放入ebx寄存器吗?).然后恢复ebx寄存器以进行关闭系统调用?或者我的代码是否正确且安全?

我运行了下面的代码并且它可以工作,我只是不确定它是否通常被认为是良好的汇编实践,因为我没有在int 80h读取调用之前保存ebx寄存器.

;; open up the input file 
mov eax,5        ; open file system call number
mov ebx,[esp+8]  ; null terminated string file name, first command line parameter
mov ecx,0o       ; access type: O_RDONLY
int 80h          ; file handle or negative error number put in eax
test eax,eax
js Error         ; test sign flag (SF) for negative number which signals error

;; read in the full input file
mov ebx,eax            ; assign input file descripter
mov eax,3              ; …
Run Code Online (Sandbox Code Playgroud)

linux x86 assembly system-calls

11
推荐指数
1
解决办法
6197
查看次数

Linux系统调用表或汇编语言的cheetsheet

有谁知道在汇编语言中为Linux系统调用找到汇总表或备忘单的位置?我通过int 0x80指令调用Linux系统调用,我需要不时地引用哪个寄存器包含什么值.

谢谢.

c linux assembly

11
推荐指数
1
解决办法
1万
查看次数

syscall是x86_64上的指令吗?

我想检查在glibc中执行系统调用的代码.我发现了这样的事情.

ENTRY (syscall)
    movq %rdi, %rax     /* Syscall number -> rax.  */
    movq %rsi, %rdi     /* shift arg1 - arg5.  */
    movq %rdx, %rsi
    movq %rcx, %rdx
    movq %r8, %r10
    movq %r9, %r8
    movq 8(%rsp),%r9    /* arg6 is on the stack.  */
    syscall         /* Do the system call.  */
    cmpq $-4095, %rax   /* Check %rax for error.  */
    jae SYSCALL_ERROR_LABEL /* Jump to error handler if error.  */
L(pseudo_end):
    ret         /* Return to caller.  */
Run Code Online (Sandbox Code Playgroud)

现在我的问题是系统调用(在cmpq指令之前)是否是指令?其次,如果它是一个指令,ENTRY(系统调用)的含义是什么?ENTRY的同名(我不知道ENTRY是什么)和指令?其次,L(pseudo_end)是什么?

c linux gcc x86-64 machine-instruction

11
推荐指数
2
解决办法
8114
查看次数

如果我要在程序集中编写程序,那么这个HelloWorld汇编代码的哪些部分是必不可少的?

我有这个简短的你好世界计划:

#include <stdio.h>

static const char* msg = "Hello world";

int main(){
    printf("%s\n", msg);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我用gcc将它编译成以下汇编代码:

    .file   "hello_world.c"
    .section    .rodata
.LC0:
    .string "Hello world"
    .data
    .align 4
    .type   msg, @object
    .size   msg, 4
msg:
    .long   .LC0
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    movl    msg, %eax
    movl    %eax, (%esp)
    call    puts
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa …
Run Code Online (Sandbox Code Playgroud)

c linux x86 assembly

10
推荐指数
1
解决办法
1149
查看次数

什么是参数推送顺序

我正在学习汇编语言.什么是参数推送顺序?我理解它如何被推入堆栈但左右部分是什么意思?什么左?或右?或者这只是与语义编写命令的方式有关,即:

mov ebp,esp; esp从右到左移动到ebp.

这是正确的还是有人可以启发我?

非常感谢!

assembly arguments push

9
推荐指数
2
解决办法
1万
查看次数

用于汇编程序员的Linux/x86-64系统调用中的结构布局?

许多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 */ …
Run Code Online (Sandbox Code Playgroud)

c linux x86 x86-64 linux-kernel

9
推荐指数
1
解决办法
1112
查看次数