I reproduced it, using gcc 9.3.0 (Linux Mint 20.2), on x86-64 system (Intel
Result of hexdump -C
:
Note the byte sequence is the same.
So I use gcc -S -c
:
.file "teststr.c"
.text
.section .rodata
.LC0:
.string "%s"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movl $1668178254, -14(%rbp) # NOTE THIS PART HERE
movw $121, -10(%rbp) # AND HERE
leaq -14(%rbp), %rax
movq %rax, %rsi
leaq .LC0(%rip), %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
movq -8(%rbp), %rdx
xorq %fs:40, %rdx
je .L3
call __stack_chk_fail@PLT
.L3:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
The highlighted value 1668178254
is hex 636E614E
or "cnaN" (which, due to the endian reversal as x86 is a little-endian system, becomes "Nanc") in ASCII encoding, and 121
is hex 79
, or "y".
So it uses two move instructions instead of a loop copy from a byte string section of the file given it's a short string, and the intervening "garbage" is (I believe) the following movw
instruction. Likely a way to optimize the initialization, versus looping byte-by-byte through memory, even though no optimization flag was "officially" given to the compiler - that's the thing, the compiler can do what it wants to do in this regard. Microsoft's compiler, then, seems to be more "pedantic" in how it compiles because it does, in fact, apparently forgo that optimization in favor of putting the string together contiguously.
char temp[6]
is outside a function, so that it gets allocated statically instead of stack allocation. Similarly if you make itstatic char temp[6]
inside a function, though that could be subject to compiler optimizations. – Graveyardprintf
is an intrinsic and the compiler optimizes it in a special fashion, it's not literally a call of a function calledprintf
, even though such a function exists from the programmer's perspective. – Meristicconst char *temp = "Nancy";
would also (typically, aggressive optimizations can do funny things) store the verbatim"Nancy"
(includingNUL
delimiter) in the constant data section. I was about to add that it might do so forconst char temp[6] = "Nancy";
too, even withoutstatic
, but on considering it, I'm not sure that's allowed (I think it would be under as-if rules, but I'm not 100%). – Fiedling.data
has to get copied from flash ROM by code included in the "executable" image, but I don't think it happens there either. (So you have to do it manually in cases where it'd help) – Starveling