, Inspirado por la pregunta Difference in initalizing and zeroing an array in c/c++ ?, decidí examinar realmente el ensamblado de, en mi caso, una versión de lanzamiento optimizada para Windows Mobile Professional (procesador ARM, del compilador de optimización de Microsoft). Lo que encontré fue algo sorprendente, y me pregunto si alguien puede arrojar algo de luz sobre mis preguntas al respecto.Montaje extraño de array 0-initialization
Estos dos ejemplos son examinados:
byte a[10] = { 0 };
byte b[10];
memset(b, 0, sizeof(b));
Se utilizan en la misma función, por lo que la pila se ve así:
[ ] // padding byte to reach DWORD boundary
[ ] // padding byte to reach DWORD boundary
[ ] // b[9] (last element of b)
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ] // b[0] = sp + 12 (stack pointer + 12 bytes)
[ ] // padding byte to reach DWORD boundary
[ ] // padding byte to reach DWORD boundary
[ ] // a[9] (last element of a)
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ] // a[0] = sp (stack pointer, at bottom)
El ensamblado generado con mis comentarios:
; byte a[10] = { 0 };
01: mov r3, #0 // r3 = 0
02: mov r2, #9 // 3rd arg to memset: 9 bytes, note that sizeof(a) = 10
03: mov r1, #0 // 2nd arg to memset: 0-initializer
04: add r0, sp, #1 // 1st arg to memset: &a[1] = a + 1, since only 9 bytes will be set
05: strb r3, [sp] // a[0] = r3 = 0, sets the first element of a
06: bl memset // continue in memset
; byte b[10];
; memset(b, 0, sizeof(b));
07: mov r2, #0xA // 3rd arg to memset: 10 bytes, sizeof(b)
08: mov r1, #0 // 2nd arg to memset: 0-initializer
09: add r0, sp, #0xC // 1st arg to memset: sp + 12 bytes (the 10 elements
// of a + 2 padding bytes for alignment) = &b[0]
10: bl memset // continue in memset
Ahora, hay dos cosas que me confunden:
- ¿Qué sentido tienen las líneas 02 y 05? ¿Por qué no simplemente dar & a [0] y 10 bytes a memset?
- ¿Por qué los bytes de relleno de 0 no se inicializan? ¿Eso es solo para rellenar las estructuras?
Edit: era demasiado curioso para no probar el caso struct:
struct Padded
{
DWORD x;
byte y;
};
El ensamblador para 0-inicializarlo:
; Padded p1 = { 0 };
01: mov r3, #0
02: str r3, [sp]
03: mov r3, #0
04: str r3, [sp, #4]
; Padded p2;
; memset(&p2, 0, sizeof(p2));
05: mov r3, #0
06: str r3, [sp]
07: andcs r4, r0, #0xFF
08: str r3, [sp, #4]
Aquí vemos en la línea 04 que un acolchado de hecho ocurre, ya que se usa str
(a diferencia de strb
). ¿Derecha?
Ni idea, pero gran pregunta –
Bueno, después de leer los comentarios a continuación, parece que msvc simplemente no es muy consistente acerca de la reducción a cero de la memoria. –