Taking the following C code
#include <stdio.h>
void test(unsigned char buffer[], int size) {
for (int i = 0; i < size; i++) {
unsigned char data = buffer[i];
printf("%c", data);
}
}
void main() {
unsigned char buffer[5] = "Hello";
test(buffer, 5);
return;
}
and compiling it the flags -fno-stack-protector -fno-asynchronous-unwind-tables -fno-unroll-loops
for clarity produces the following assembly for the test()
function:
test:
testl %esi, %esi
jle .L6
pushq %rbp
leal -1(%rsi), %eax
pushq %rbx
leaq 1(%rdi,%rax), %rbp
movq %rdi, %rbx
subq $8, %rsp
.p2align 4,,10
.p2align 3
.L3:
movzbl (%rbx), %edi
addq $1, %rbx
call putchar@PLT
cmpq %rbp, %rbx
jne .L3
addq $8, %rsp
popq %rbx
popq %rbp
ret
.p2align 4,,10
.p2align 3
.L6:
ret
.size test, .-test
.section .text.startup,"ax",@progbits
.p2align 4
It seems to me like the L3
label here is completely useless since it is never jumped to or entered. (Except by jne .L3
, but that instruction is inside of the L3 label already).
Can anyone explain how and why this assembly still produces the expected effect?