Встроенный ассемблер для функции-оболочки по какой-то причине не работает

Я пытаюсь написать функцию-оболочку для системного вызова 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;
 }

person JAN    schedule 21.04.2012    source источник


Ответы (2)


он терпит неудачу и переходит в if (-125 <= res && res < 0)

Куда вы ожидали, что он пойдет?

Я ожидаю, что системный вызов чтения завершится ошибкой с -EINVAL, поскольку вы не передаете ему допустимый файловый дескриптор.

Обновлять:

Откуда вы взяли, что SYS_read это 5?

В моей системе SYS_read равно 3 в 32-битном режиме и 0 в 64-битном режиме:

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), потому что первым параметром системного вызова open должно быть имя файла, а 0 (NULL) не является допустимым именем файла.

person Employed Russian    schedule 21.04.2012
comment
@EmployedRussian : Меня все еще беспокоит одна вещь : если файловый дескриптор -- int , то что я здесь делаю не так ? Я прошел это вовнутрь. - person JAN; 21.04.2012
comment
Вам нужен действительный файловый дескриптор, а не какой-нибудь int. Обычно правильный файловый дескриптор можно получить из системного вызова open. Или используйте один из уже существующих: 0 (для stdin). - person Employed Russian; 21.04.2012
comment
@EmployedRussian: я пробовал с 0, используя фиксированный код в моем отредактированном посте, но я все равно сразу перехожу к if (-125 ‹= res && res ‹ 0)… - person JAN; 21.04.2012
comment
Вы не исправили main (по крайней мере, я не вижу исправления). Предполагая, что вы исправили это, запустите свою программу под strace, как предложил @R.., и посмотрите, что она вам скажет. - person Employed Russian; 21.04.2012

Запустите его под strace, чтобы точно увидеть, что происходит, но я думаю, что ваша проблема в том, что вы помещаете все входы в список выходных регистров, а не в список входных регистров...

person R.. GitHub STOP HELPING ICE    schedule 21.04.2012
comment
Как вы можете видеть, что я поместил все входы в список выходных регистров, а не в список входных регистров? Благодарность - person JAN; 21.04.2012
comment
Материал после первого двоеточия выводится. Материал после второго двоеточия является вводом. Прямо сейчас ваш единственный ввод — это номер системного вызова. - person R.. GitHub STOP HELPING ICE; 21.04.2012
comment
Я отредактировал свой пост с вашими замечаниями, это правильно? спасибо, однако что-то по-прежнему не так, и код не переходит в asm volatile . Я пропустил что-то еще? - person JAN; 21.04.2012
comment
Вы по-прежнему передаете недопустимый файловый дескриптор. Если вы не вызовете open, 0 будет единственным файловым дескриптором, который, вероятно, будет допустимым для чтения. - person R.. GitHub STOP HELPING ICE; 21.04.2012
comment
У меня есть, я прошел 0 (отредактировано в моем исходном сообщении), но это не помогло, и вошел в сбой. Может код неверный? - person JAN; 21.04.2012