【问题标题】:gnu inline assembly errorgnu 内联汇编错误
【发布时间】:2024-01-05 03:21:01
【问题描述】:

我正在尝试在 C 文件中编写内联汇编,但出现 2 个错误:

open.c:10: Error: junkptr nombre' 在表达式后`

open.c:10: Error: suffix or operands invalid forles'`

这是我的文件:

int open(char * nombre, unsigned char modo)
{
  int retval;
  int nrllamada = 6;
  asm("mov $8,%%ah \n\t"
      "les %%bx, dword ptr nombre \n\t"
      "int $0x22 \n\t"
      "mov %%eax,%0 \n\t"
      : "=r"(retval)
      : "a"(modo)
  );
  return retval;
}

【问题讨论】:

    标签: c gcc assembly gnu inline-assembly


    【解决方案1】:
    "les %%bx, dword ptr nombre \n\t"
    

    你的字符串中有 ptr 名词。那可能是不正确的。您确定要在函数的参数中引用 char* 名词吗?

    【讨论】:

      【解决方案2】:

      在寄存器 ES 和 BX 中写入名为 nombre 的 32 位指针的正确方法是将 C 变量 nombre 连接到寄存器 ECX,将 ECX 的低 16 位移动到寄存器 BX,将 ECX 寄存器循环 16 位,使低16 位到同一个寄存器的高 16 位,反之亦然,最后将 ECX 的低 16 位移动到 ES。

      int open(char * nombre, unsigned char modo)
      {
        int retval;
        // numero servicio 6
        // nombre del fichero a abrir (ES:BX) y modo (AL) de apertura
        asm("mov $6,%%ah \n\t"
            "mov %%cx,%%bx \n\t"
            "rol $16,%%ecx \n\t"
            "mov %%cx,%%es \n\t"
            "int $0x22 \n\t"
            "mov %%eax,%0 \n\t"
            : "=r"(retval)
            : "a"(modo), "c"(nombre)
        );
        return retval;       
      }
      

      【讨论】:

        【解决方案3】:

        GCC 是 32 位编译器。这也意味着,您应该最有可能尝试摆脱 es:bx 类型指针算法并转移到平面 32 位寻址(其中 cs=ds=es=0 的基数和每个段限制为 0xffffffff)。

        在保护模式的用户空间访问状态寄存器很可能会出现访问冲突异常。

        另外,什么是操作系统,允许 int 22h 以及它期望 es:bx 输入的位置?在 MS-DOS 中不应该调用它,因为它只是用作静态变量来恢复其他中断向量。

        【讨论】:

        • 我正在编写一个名为 OSO 的微型操作系统的小内核,它使用了 fat12 文件系统和 16 位 CPU 架构等旧技术。 int22h 是为我的内核制作的,我已经有一个中断例程。