Having this simple c:
#include <stdio.h>
struct foo{
int a;
char c;
};
static struct foo save_foo;
int main(){
struct foo foo = { 97, 'c', };
save_foo = foo;
printf("%c\n",save_foo.c);
}
Here the save_foo
variable is in bss segmet, and in the main
function, I am trying to "copy" from stack-made variable foo
to uninitialized save_foo
. So I would expect both elements foo.a
and foo.c
to be copied into save_foo.a
and save_foo.c
.
However, the generated assembly:
.text
.local save_foo
.comm save_foo,8,8
.section .rodata
.LC0:
.string "%c\n"
.text
.globl main
.type main, @function
main:
endbr64
pushq %rbp #
movq %rsp, %rbp #,
subq $16, %rsp #,
# a.c:11: struct foo foo = { 97, 'c', };
movl $97, -8(%rbp) #, foo.a
movb $99, -4(%rbp) #, foo.c
# a.c:12: save_foo = foo;
movq -8(%rbp), %rax # foo, tmp86
##################################################################
#MISSING to copy foo.c to save_foo.c yet able to use that value
#movq -4(%rbp), %rcx
#movq %rcx, 4+save_foo(%rip)
##################################################################
movq %rax, save_foo(%rip) # tmp86, save_foo
# a.c:14: printf("%c\n",save_foo.c);
movzbl 4+save_foo(%rip), %eax # save_foo.c, _1
# a.c:14: printf("%c\n",save_foo.c);
movsbl %al, %eax # _1, _2
movl %eax, %esi # _2,
leaq .LC0(%rip), %rdi #,
movl $0, %eax #,
call printf@PLT #
movl $0, %eax #, _9
# a.c:15: }
leave
ret
.size main, .-main
.ident "GCC: (Ubuntu 10.2.0-13ubuntu1) 10.2.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:
There is only one element (foo.a
) copied. But the foo.c
is not. How is possible for movzbl 4+save_foo(%rip), %eax
to get the right value (99
, which is in ASCII 'c'
), when that value was not copied? (there is no movl
from -4(%rbp)
where the value is to 4+save_foo(%rbp)
symbol on the bss segment). Shouldn't be the value at 4+save_foo(%rbp)
zeroed (when it is uninitialized)?