We have this simple c modified code from stack overflow called funcptrtest.c:
include <stdio.h> /* C code for program funcptrtest.c => https://pastebin.com/rUtXfgSG */ const int b = 23; // A normal function with an int parameter and void return type void fun(int a) { if (a < b) printf("Value of a (%d) is lesser then value of b (%d)\n", a, b); else if (a == b) printf("Value of a (%d) is equal value of b (%d)\n", a, b); else if (a > b) printf("Value of a (%d) is greater than value of b (%d)\n", a, b); } // main => NO KNR style int main(argc, argv) int argc; char **argv int main(int argc, char **argv) { int i = 0; /* fun_ptr is a pointer to function fun() void (*fun_ptr)(int) = &fun; is equivalent of following two void (*fun_ptr)(int); fun_ptr = &fun; */ void (*fun_ptr)(int) = &fun; // call once with static int (*fun_ptr)(b); // iterate through for loop for (i = 1; i < 101; i+=11) { // Invoking fun() using fun_ptr (*fun_ptr)(i); } return 0; }
We compile it now with gnu c compiler with gcc option -S and generate an assembler file:
gcc -S funcptrtest.c -o funcptrtest.asm
Result will be something like this:
.file "funcptrtest.c" .text .globl b .section .rodata .align 4 .type b, @object .size b, 4 b: .long 23 .align 8 .LC0: .string "Value of a (%d) is lesser then value of b (%d)\n" .align 8 .LC1: .string "Value of a (%d) is equal value of b (%d)\n" .align 8 .LC2: .string "Value of a (%d) is greater than value of b (%d)\n" .text .globl fun .type fun, @function fun: .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 movl %edi, -4(%rbp) movl $23, %eax cmpl %eax, -4(%rbp) jge .L2.L2: movl $23, %eax cmpl %eax, -4(%rbp) jne .L4 movl $23, %edx movl -4(%rbp), %eax movl %eax, %esi leaq .LC1(%rip), %rax movq %rax, %rdi movl $0, %eax call printf@PLT jmp .L5 .L2: movl $23, %eax cmpl %eax, -4(%rbp) jne .L4 movl $23, %edx movl -4(%rbp), %eax movl %eax, %esi leaq .LC1(%rip), %rax movq %rax, %rdi movl $0, %eax call printf@PLT .L2: movl $23, %eax cmpl %eax, -4(%rbp) jne .L4 movl $23, %edx movl -4(%rbp), %eax movl %eax, %esi leaq .LC1(%rip), %rax movq %rax, %rdi movl $0, %eax call printf@PLT jmp .L5 .L4: movl $23, %eax cmpl %eax, -4(%rbp) jle .L5 movl $23, %edx movl -4(%rbp), %eax movl %eax, %esi leaq .LC2(%rip), %rax movq %rax, %rdi movl $0, %eax call printf@PLT .L5: nop leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size fun, .-fun .globl main .type main, @function main: .LFB1: .cfi_startproc endbr64 pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $32, %rsp movl %edi, -20(%rbp) movq %rsi, -32(%rbp) movl $0, -12(%rbp) leaq fun(%rip), %rax movq %rax, -8(%rbp) movl $23, %edx movq -8(%rbp), %rax movl %edx, %edi call *%rax movl $1, -12(%rbp) jmp .L7 .L8: movl -12(%rbp), %eax movq -8(%rbp), %rdx movl %eax, %edi call *%rdx addl $11, -12(%rbp) .L7: cmpl $100, -12(%rbp) jle .L8 movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1: .size main, .-main .ident "GCC: (Ubuntu 11.3.0-1ubuntu1~22.04) 11.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:
Lets look, if a simple loop is faster than a function pointer delegate call:
/* program looptest.c */ include <stdio.h> const int b = 23; // main int main(int argc, char **argv) { int i = 0; int a = 23; /* if (a < b) printf("Value of a (%d) is lesser then value of b (%d)\n", a, b); else if (a == b) printf("Value of a (%d) is equal value of b (%d)\n", a, b); else if (a > b) printf("Value of a (%d) is greater than value of b (%d)\n", a, b); */ // iterate through for loop for (i = 1; i < 4194304; i+=11) { a = i; if (a < b) printf("Value of a (%d) is lesser then value of b (%d)\n", a, b); else if (a == b) printf("Value of a (%d) is equal value of b (%d)\n", a, b); else if (a > b) printf("Value of a (%d) is greater than value of b (%d)\n", a, b); } return 0; }
/* program funcptrtest.c */ include <stdio.h> const int b = 23; // A normal function with an int parameter and void return type void fun(int a) { if (a < b) printf("Value of a (%d) is lesser then value of b (%d)\n", a, b); else if (a == b) printf("Value of a (%d) is equal value of b (%d)\n", a, b); else if (a > b) printf("Value of a (%d) is greater than value of b (%d)\n", a, b); } // main int main(int argc, char **argv) { int i = 0; /* fun_ptr is a pointer to function fun() void (*fun_ptr)(int) = &fun; is equivalent of following two void (*fun_ptr)(int); fun_ptr = &fun; */ void (*fun_ptr)(int) = &fun; // call once with static int // (*fun_ptr)(b); // iterate through for loop for (i = 1; i < 4194304; i+=11) { // Invoking fun() using fun_ptr (*fun_ptr)(i); } return 0; }
Well, that's not so deterministic, of course our simple looptest.asm has a shorter assembler.
But execution time is not so huge difference, we have to simulate, that in many scenarios.
[To be continued ...]
Keine Kommentare:
Kommentar veröffentlichen