C asm linux 循环中的系统调用永远继续

C asm linux syscall in loop continue for ever

我想使用 C 语言中的扩展 asm 来处理系统调用(写入)。 一切都很好,我正在使用

#define write(RESULT, FD, BUFF, SIZE)   \
    asm volatile ("syscall" :           \
        "=a" (RESULT) :                 \
        "D" (FD), "S" (BUFF), "d" (SIZE), "a" (1))

这没有任何问题...例如

#define write(RESULT, FD, BUFF, SIZE)   \
    asm volatile ("syscall" :           \
        "=a" (RESULT) :                 \
        "D" (FD), "S" (BUFF), "d" (SIZE), "a" (1))

int
main() {

    int res;
    write(res, 1, "Hello\n", 6);

    return 0;
}

我对这段代码没有问题,但我的问题是当我拨打这个电话时

write(res, 1, "Hello\n", 6);

循环使用100次

#define write(RESULT, FD, BUFF, SIZE)   \
    asm volatile ("syscall" :           \
        "=a" (RESULT) :                 \
        "D" (FD), "S" (BUFF), "d" (SIZE), "a" (1))

int
main() {

    int res;
    for (int i = 0; i < 100; i++) {
        write(res, 1, "Hello\n", 6);
    }    

    return 0;
}

但有一点......我对这段代码也没有问题,但只是在调试模式下......如果我将程序设置为(发布)或优化模式,这个循环将永远执行!!!!!好像没有 100 次限制...这只发生在 "Release" 优化我的代码并使其出错的模式下!!

是的......打击源代码在"debug"中找到但它在"Release"模式

中永远写入"Hello"(无限制)

这是我使用的汇编代码online check 使用 -O3 选项 (GCC x86_64)

.LC0:
  .string "Hello\n"
main:
  movl 0, %ecx
  movl $.LC0, %esi
  movl , %edi
  movl , %edx
.L2:
  movl %edi, %eax
  syscall
  subl , %ecx
  jne .L2
  xorl %eax, %eax
  ret

syscall 指令破坏了寄存器 rcxr11。编译器假定它们的值被保留,从而导致无限循环。将这两个添加到 clobber 列表以解决问题:

#define write(RESULT, FD, BUFF, SIZE)               \
    asm volatile ("syscall" :                       \
        "=a" (RESULT) :                             \
        "D" (FD), "S" (BUFF), "d" (SIZE), "a" (1) : \
        "rcx", "r11", "memory")