用于包装器功能的内联汇编器由于某种原因不起作用

时间:2012-04-21 15:11:47

标签: c assembly volatile system-calls

我正在尝试为read()系统调用编写一个包装函数 asm volatile,但它不起作用,因为res不会改变它的值。

以下是代码:

ssize_t my_read(int fd, void *buf, size_t count)

{

      ssize_t res;

      __asm__ volatile(
        "int $0x80"        /* make the request to the OS */
        : "=a" (res),       /* return result in eax ("a") */
          "+b" (fd),     /* pass arg1 in ebx ("b") */
          "+c" (buf),     /* pass arg2 in ecx ("c") */
          "+d" (count)      /* pass arg3 in edx ("d") */
        : "a"  (5)          /* passing the system call for read to %eax , with call number 5  */
        : "memory", "cc"); /* announce to the compiler that the memory and condition codes have been modified */

      /* The operating system will return a negative value on error;
       * wrappers return -1 on error and set the errno global variable */

      if (-125 <= res && res < 0)
      {
        errno = -res;
        res   = -1;
      }

      return res;

}

这里是int main ()

 int main() {
     int fd = 432423;
     char buf[128];
     size_t count = 128;
     my_read(fd, buf, count);

     return 0;
 }

我做错了吗?也许是因为volatile

我试图调试代码,当Eclipse进入my_read(fd, buf, count);和 到达__asm__ volatile(中的my_read行,它失败并进入if (-125 <= res && res < 0) ......

编辑:

ssize_t my_read(int fd, void *buf, size_t count)

{

      ssize_t res;

      __asm__ volatile(
        "int $0x80"        /* make the request to the OS */
        : "=a" (res)       /* return result in eax ("a") */

        : "a"  (5) ,      /* passing the system call for read to %eax , with call number 5  */
          "b" (fd),     /* pass arg1 in ebx ("b") */
          "c" (buf),     /* pass arg2 in ecx ("c") */
          "d" (count)      /* pass arg3 in edx ("d") */

        : "memory", "cc"); /* announce to the compiler that the memory and condition codes have been modified */

      /* The operating system will return a negative value on error;
       * wrappers return -1 on error and set the errno global variable */

      if (-125 <= res && res < 0)
      {
        errno = -res;
        res   = -1;
      }

      return res;

}

和主要:

 int main() {
     int fd = 0;
     char buf[128];
     size_t count = 128;
     my_read(fd, buf, count);

     return 0;
 }

2 个答案:

答案 0 :(得分:5)

  

它失败并进入if (-125 <= res && res < 0)

你期望它去哪里?

我希望读取系统调用失败并显示-EINVAL,因为您没有在其中使用有效的文件描述符。

更新

您在哪里知道SYS_read5

在我的系统上,SYS_read在32位模式下为3,在64位模式下为0

echo "#include <syscall.h>" | gcc -xc - -dD -E | grep ' __NR_read '
#define __NR_read 0

echo "#include <syscall.h>" | gcc -xc - -dD -E -m32 | grep ' __NR_read '
#define __NR_read 3

假设您使用的是32位系统,则调用SYS_open,但-EFAULT(-14)失败,因为打开系统调用的第一个参数应该是文件名, 0NULL)不是有效的文件名。

答案 1 :(得分:2)

strace下运行它以确定发生了什么,但我认为您的问题是您将所有输入放在输出寄存器列表而不是输入寄存器列表中......