用嵌入汇编的形式使用open系统调用

用嵌入汇编的形式使用open系统调用

用嵌入汇编的形式使用open系统调用 #

在下面这段代码中,我们直接使用机器指令调用了 open 系统调用函数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <unistd.h>
#include <fcntl.h>
int main(void) {
  const char str[] = "Enter some characters:\n";
  write(STDOUT_FILENO, str, sizeof(str));
  const char* fileName = "./temp.txt";
  // Call to `open` starts:
  // const int fd = open("./temp.txt", O_RDWR | O_CREAT);
  volatile int fd;
  asm("mov $2, %%rax\n\t"                                      (asm)
      "mov %0, %%rdi\n\t"
      "mov $66, %rsi\n\t"  // 2 | 64 -> 66;
      "syscall\n\t"
      "mov %rax, %1\n\t"                                       (write_to_fd)
       : "=m" (fileName)
       : "m" (fd));
  // Call ended.
  if (fd > 0) {
    char ch;
    while (read(STDIN_FILENO, &ch, 1)) {
      if (ch == 'z') break;
      write(fd, &ch, sizeof(ch));
    }
  } else {
    const char errMsg[] = "File open failed.";
    write(STDERR_FILENO, errMsg, sizeof(errMsg));
  }
  close(fd);
  return 0;
}

asm,我们以内联汇编的形式,在程序的执行流中插入了 5 条机器指令。第 1 条指令,我们将系统调用 open 对应的整型 ID 值 2 放入到了寄存器 rax 中;第 2 条指令,我们将存放有目标文件名称的字节数组 fileName 的首地址放到了寄存器 rdi 中,该参数也对应着低级 IO 接口 open 的第一个参数。接下来的一条指令,我们将配置参数对应表达式 O_RDWR | O_CREAT 的计算结果值 66 放入到了寄存器 rsi 中。最后,通过指令 syscall,我们得以调用对应的系统调用函数。而当系统调用执行完毕后,其对应的返回值将会被放置在寄存器 rax 中。在 write_to_fd,我们将该寄存器中的值传送到了变量 fd 在栈内存中的位置。

Viewpoint #

From #

11|标准库:深入理解标准 IO