【问题标题】:GAS does not recognise register %ipGAS 无法识别寄存器 %ip
【发布时间】:2012-10-10 23:58:13
【问题描述】:

在我的 16 位程序中,GAS 对指令犹豫不决:

movw %ip, %dx

我觉得这很奇怪,因为移动段寄存器可以正常工作,例如:

movw %ss, %ax

完整的错误信息是:

错误:错误的寄存器名称 `%ip'

我的版本字符串是:

GNU 汇编器 (GNU Binutils) 2.22

【问题讨论】:

    标签: assembly gnu-assembler att


    【解决方案1】:

    不幸的是,并非每个寄存器都可以轻松访问。有一些限制。

    x86 wikibook, GPR section 中所列,x86 中有 8 个通用寄存器 (GPR):AX、CX、DX、BX、SP、BP、SI、DI,可用于许多命令。它们被编码为 3 位;并且指令编码中没有空间来编码特殊寄存器,如 EIP (IP) 或 EFLAGS (FLAGS)。

    如果你向下滚动wikibook,会有一个关于IP的部分:

    指令指针

    如果没有进行分支,EIP 寄存器包含要执行的下一条指令的地址。

    EIP 只能在调用指令后通过堆栈读取。

    所以,用mov读取IP确实是违法的。

    这里有一些用call然后pop %ax序列读取ip的例子:http://www.programmersheaven.com/mb/x86_asm/267963/267963/how-to-access-ip-register/

    更新:关于读取 SS 寄存器:

    mov 指令编码实际上有很多变体,例如在这个table 中,我们看到了分段阅读

     mnemonic   op1 op2 po     o    description, notes 
     MOV    Sreg    r/m16   8E     r        Move
    

    或控制寄存器写入:

     MOV    r32 CRn 0F20   r ...    Move to Control Registers
    

    但仍然没有用于 IP 寄存器的 MOV。

    更新 2:在 x86_64 中,根据https://stackoverflow.com/a/1047968/196561,有一个 EIP 与 LEA 的读取

    【讨论】:

    • 你能解释一下,你在哪里实现调用?
    • 这不是一个真正的调用,而是试图将%ip 保存到%dx(因为我没有在我的小子程序中使用 %dx),jmp 到我的子程序,然后是@987654332 @返回。
    • 为什么不使用默认堆栈和 call/ret 而不是 jmp/jmp *dx?而且我仍然没有看到调用/弹出 dx 的障碍。
    • 这样做的目的是帮助我以十六进制打印 %ss,因为我不知道堆栈从哪里开始;我想使用堆栈“调用”我的convert_nibble_to_hex 子例程
    • call/pop 序列的问题在于您需要一个工作堆栈,而在操作系统启动期间可能不是这种情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 2012-01-28
    • 2012-02-10
    • 2022-09-25
    相关资源
    最近更新 更多