¿Para qué sirven CLD y STD en lenguaje ensamblador x86? ¿Qué hace DF?

bueno, sé que CLD borra la bandera de dirección y STD establece la bandera de dirección. pero, ¿de qué sirve establecer y borrar la bandera de dirección?

preguntado el 09 de marzo de 12 a las 15:03

Uf, la cantidad de errores que causó ese bit. Mi código Turbo Pascal estaba salpicado de ensamblaje en línea para restablecerlo. -

5 Respuestas

La bandera de dirección se utiliza para influir en la dirección en la que las instrucciones de cadena desplazan los registros del puntero. Estas son las mismas instrucciones que se pueden utilizar con REP prefijo para repetir la operación. (A pesar de que lods no es muy útil con rep).

Las instrucciones de la cadena son: MOVS (copiar mem a mem), STOS (almacenar AL / AX / EAX / RAX), SCAS (cadena de escaneo), CMPS (comparar cadena), y LODS (cadena de carga). También hay ins/outs para copiar entre la memoria y un puerto IO. Cada una de estas instrucciones está disponible en tamaños de operando byte, word, dword y qword.

En pocas palabras, cuando la bandera de dirección es 0, las instrucciones funcionan incrementando el puntero a los datos después de cada iteración (hasta ECX es cero o alguna otra condición, dependiendo del sabor de la REP prefijo), mientras que si la bandera es 1, el puntero disminuye.

Por ejemplo, movsd copia una dword de [ds:esi] a [es:edi] (o rdi en modo de 64 bits), y hace esto: (Consulte la sección "Operación" en la entrada del manual de referencia ISA vinculada extraída de los PDF de Intel)

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

Con un prefijo REP, hace esto ECX veces, y las CPU x86 modernas tienen un microcódigo optimizado de "cadenas rápidas" que realiza la copia (o stos almacenamiento) con operaciones internas de 16 o 32 bytes. Ver también esta pregunta y respuesta sobre el ancho de banda de la memoria y la función ERMSB. (Tenga en cuenta que solo rep stos y rep movs están optimizados de esta manera, no repne/repe scas or cmps).

Respondido el 03 de diciembre de 17 a las 20:12

CLD CLaca la bandera de dirección, los datos avanzan. STD establece la bandera de dirección, los datos van hacia atrás.

Respondido el 22 de enero de 13 a las 13:01

Si usa Windows, según la convención de llamadas STDCALL:

Bajo STDCALL, la bandera de dirección está despejada al entrar y debe devolverse despejada.

Entonces, si configura DF, entonces, antes de una llamada a la API, debe borrarlo.

respondido 10 mar '12, 22:03

Depende del sistema operativo. - amanuel2

Esto es común a la mayoría de las convenciones de llamadas de 32 bits / 64 bits, incluidos i386 System V y x86-64 System V. Le permite a usted (o al compilador) de manera eficiente en línea rep movsd / rep stosd sin instrucciones CLD. (En x86 moderno, a menudo solo aumentan rápidamente, con DF = 0) - pedro cordes

CLD: marca de dirección clara para que los punteros de cadena se incrementen automáticamente después de cada operación de cadena

STD: std se utiliza para establecer el indicador de dirección en 1, de modo que SI y / o DI se reducirán automáticamente para apuntar al siguiente elemento de cadena cuando se ejecute una de las instrucciones de cadena. Si el indicador de dirección está establecido, SI / DI será decrementado en 1 para cadenas de bytes y 2 para cadenas de palabras.

Esta respuesta puede resultarle útil.

Respondido el 03 de diciembre de 17 a las 16:12

CLD: Borra la bandera DF en el registro EFLAGS. Cuando la bandera DF se establece en 0, las operaciones de cadena incrementan los registros de índice (ESI y / o EDI).

aquí hay un ejemplo simple:

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

(ensamblar y vincular con nasm -felf32 caesar.asm && gcc -no-pie -m32 caesar.o -o caesar. O vincularlo a un ejecutable estático con esto como _start en lugar de main Si te gusta.)

(este ejemplo intentó implementar el cifrado César).

Respondido 14 ago 18, 06:08

La convención de llamadas i386 System V ya garantiza DF = 0 al ingresar a una función, por lo que su programa funciona de manera confiable incluso si usa lodsb/stosb antes de correr cld. los rep movsb se ejecuta con ECX = 0 (desde loop), por lo que copia cero bytes después del final de s1/s2y no importa qué DF esté configurado en ese punto. - pedro cordes

Por cierto, loop es lento, no lo use a menos que esté optimizando el tamaño del código por encima de la velocidad. Además, probablemente desee ajustar las dos últimas letras del alfabeto a las dos primeras. Por lo tanto, tiene sentido cargar y operar en un byte en un registro, pero solo si va a implementar una verificación de ajuste. De lo contrario, podría modificar una cadena en su lugar con add byte [esi], 2 / inc esi. O haz 4 bytes a la vez con add dword [esi], 0x02020202, si no lleva ... - pedro cordes

gracias. Intento solucionar los problemas que mencionaste en mi código :) - NS

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.