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