x86汇编语言中的CLD和STD是什么? DF做什么?

时间:2012-03-09 15:33:58

标签: assembly x86

好吧,我知道CLD清除方向标志,STD设置方向标志。 但设置和清除方向标志的重点是什么?

5 个答案:

答案 0 :(得分:31)

方向标志用于影响字符串指令偏移指针寄存器的方向。这些是可以使用with the REP prefix重复操作的相同指令。   (虽然lodsrep}不是很有用。

字符串指令是:MOVS(将mem复制到mem),STOS(存储AL / AX / EAX / RAX),SCAS(扫描字符串),{{1} }(比较字符串)和CMPS(加载字符串)。还有LODS / ins用于在内存和IO端口之间进行复制。这些指令中的每一个都有字节,字,双字和qword操作数大小。

简而言之,当direction标志为0时,指令的工作方式是在每次迭代后将指针递增到数据(直到outs为零或其他条件,具体取决于{{1的味道如果标志为1,则指针递减。

例如,movsd将dword从ECX复制到REP(或64位模式下的rdi),并执行此操作:(请参阅链接中的“操作”部分从英特尔的PDF中提取的ISA参考手册条目

[ds:esi]

使用REP前缀,它执行ECX次,现代x86 CPU优化了“快速字符串”微码,可以使用16字节或32字节内部操作进行复制(或[es:edi]存储)。另见this Q&A about memory bandwidth and the ERMSB feature。 (请注意,只有dword [es:edi] = dword [ds:esi] // 4-byte copy memory to memory if (DF == 0) esi += 4; edi += 4; else // DF == 1 esi -= 4; edi -= 4; fi stos以这种方式进行优化,而不是rep stosrep movs)。

答案 1 :(得分:8)

CLD CLears Direction标志,数据继续。 STD Sends Direction标志,数据倒退。

答案 2 :(得分:3)

如果使用Windows,那么按照STDCALL调用约定 -

  

在STDCALL下,方向标志在进入时是清除的,必须是   回来了。

因此,如果您设置DF,那么在API调用之前,您必须清除它。

答案 3 :(得分:3)

CLD:清除方向标志使字符串指针   每次字符串操作后自动递增

STD: std用于将方向标志设置为1,以便当其中一个字符串指令执行时,SI和/或DI将自动递减以指向下一个字符串元素。如果设置了方向标志,则SI / DI将递减1表示字节字符串,2表示字串。

这个答案对你有帮助。

答案 4 :(得分:1)

CLD: 清除EFLAGS寄存器中的DF标志。当DF标志设置为0时,字符串操作将递增索引寄存器(ESI和/或EDI)。

这是一个简单的示例:

List<double>

(汇编并与section .text global main main: mov ecx, len mov esi, s1 mov edi, s2 cld ; redundant because DF is already guaranteed to be 0 on function entry ; but included for illustration purposes loop_here: lodsb ; AL=[esi], ESI+=1 (because DF=0, otherwise ESI-=1) add al, 02 stosb ; [edi]=AL, EDI+=1 (because DF=0, otherwise EDI-=1) loop loop_here ; like dec ecx / jnz but without setting flags ; ECX=0, EDI and ESI pointing to the end of their buffers mov edx, len-1 ;message length, not including the terminating 0 byte mov ecx,s2 ;message to write mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel mov eax,1 ;system call number (sys_exit) xor ebx,ebx int 0x80 ;call kernel: sys_exit(0) section .data s1: db 'password', 0 ; source buffer len equ $-s1 section .bss s2: resb len ; destination buffer 链接。或者,如果需要,可以将其链接为静态文件nasm -felf32 caesar.asm && gcc -no-pie -m32 caesar.o -o caesar而不是_start的可执行文件。)

(此示例尝试实现Caesar密码。)