如何让GCC知道EFLAGS寄存器中的方向标志DF在内联asm中已更改?

dojqjjoe  于 2023-02-04  发布在  其他
关注(0)|答案(1)|浏览(123)

例如,以下代码:

void ppp(void);

void kkk()
{
    __asm__ volatile("std":::"cc");
    ppp();
}

在调用 * ppp()* 之前,由于x86 API,需要执行cld,引用Default state of Direction Flag (DF) during x86 program execution
然而,装配出来了:

.globl  kkk
        .type   kkk, @function
kkk:
#APP
# 5 "test.c" 1
        std
# 0 "" 2
#NO_APP
        jmp     ppp@PLT
        .size   kkk, .-kkk

根据GCC文档(https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html),"cc"表示x86_64中的EFLAGS寄存器。为什么GCC不执行cld

6pp0gazn

6pp0gazn1#

如您所知,i386 ABI (and AMD64 System V ABI)要求清除方向标志(DF),以便为依赖该标志的指令(即字符串指令)启用正向。
x86/x86 - 64上的FLAGS/EFLAGS/RFLAGS寄存器包含许多条件标志,但也包含系统标志(如方向标志)。x87 FPU状态字中也有条件标志。
虽然内联汇编有一个cc clobber,但目前并不是所有的目标CPU都使用它。GCC编译器上针对x86/x86 - 64处理器的所有asm语句都有一个implied cc clobber,该clobber没有效果
GCC文档中关于x86/x86 - 64目标的条件标志的定义有些模糊。我相信可以从x86/x86 - 64目标的 * 6.47.2.4标志输出操作数 * 部分中的这条语句中推断出其意图,该语句为:
x86系列的标志输出约束的格式为'=@cccond',其中cond是ISA手册中为jcc或setcc**定义的 * 标准条件之一。
特别是引用JccSETcc所支持的条件标志的最后一句话,为我们提供了一个线索,即哪些标志被假定为不会被x86/x86 - 64上的内联汇编所保留:进位标志(CF)、溢出标志(OF)、奇偶校验标志(PF)、符号标志(SF)和零标志(ZF)。
备注:FLAGS寄存器中GCC根本不关心的一个标志是辅助标志(AF),它可以在处理某些指令(如AAA)时使用。
要真正回答方向标志(DF)的问题,GCC并不认为FLAGS/EFLAGS/RFLAGS寄存器中的大多数标志是条件标志。像方向标志、陷阱标志、中断标志这样的标志实际上并不适用。方向标志是一个奇怪的标志,因为它是ABI中定义的一个标志状态。必须清除它才能进行正向。
使用STD指令或其它方法设置方向标志(向后处理)而不将其还原将是未定义的行为。如果更改内嵌程序集asm语句中的Direction标志,则应负责在同一asm语句中还原它。必须在控制从内联程序集中返回之前恢复它。

相关问题