循环中的C asm linux syscall永远继续

Jas*_*son 1 c assembly inline-assembly

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

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

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

write(res, 1, "Hello\n", 6);
Run Code Online (Sandbox Code Playgroud)

循环使用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;
}
Run Code Online (Sandbox Code Playgroud)

但是有一点...我对此代码也没有问题,但仅在调试模式下....如果我将程序设置为(发布)或优化模式,则此循环将永远执行!就像没有100倍的限制...仅在“发布”模式下发生,这会优化我的代码并使它出错!

是的...在“ debug”中找到了打击源代码,但在“ Release”模式中将其永久写入“ Hello”(无限制)

这是我使用 带有-O3选项的在线检查的汇编代码(GCC x86_64)

.LC0:
  .string "Hello\n"
main:
  movl $100, %ecx
  movl $.LC0, %esi
  movl $1, %edi
  movl $6, %edx
.L2:
  movl %edi, %eax
  syscall
  subl $1, %ecx
  jne .L2
  xorl %eax, %eax
  ret
Run Code Online (Sandbox Code Playgroud)

fuz*_*fuz 5

syscall指令则会覆盖寄存器rcxr11。编译器假定保留其值,从而导致无限循环。将这两个添加到问题列表以解决此问题:

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

  • @fuz:这是一个示例:https://pastebin.com/D4fy0uS3。由于关闭了编译器的所有不必要的加载并在内存中进行存储,因此在优化关闭时,它会按预期运行。然后用-O3尝试。请注意,该字符串已放置在堆栈上。如果查看生成的代码,您会发现优化器从未将字符串写入堆栈,因为它不知道字符串中的数据正在使用中。它只知道指向字符串的指针被用作输入,而不知道指针指向的对象。 (2认同)