Showing posts with label Compiler - Linker - Loader. Show all posts
Showing posts with label Compiler - Linker - Loader. Show all posts

Monday, May 3, 2021

Embedded C Interview questions

MORE IMPORTANT QUESTIONShttp://pandyaelectronics.blogspot.com/2021/06/an-ultimate-guide-for-embeddedfirmware.html


 https://sites.google.com/site/embedsystem1/home/interview-questions

https://www.codeproject.com/Articles/6154/Writing-Efficient-C-and-C-Code-Optimization

  • Count-down loops is always better than count-up loops (primarily because, != is faster than <= operation)
  • Loop Unrolling: Small loops can be unrolled for higher performance, with the disadvantage of increased code size.
  • Referring to address of local variable results in unoptimized code: Reason - Compiler will try to optimize by using it's registers for the variables; but when you refer the address, it cannot allocate a register and rather use memory (and there-by resulting in memory operation)
  • Reduce global variables: For the same reason that it has to use memory.
  • char, short, int - which is better?: Use int as much as possible because for 'char' and 'short' CPU has to do some shift operations before giving the value to the user
  • How to reduce the function call overhead?

  • Avoid using ++ and -- etc. within loop expressions. E.g.: while(n--){}, as this can sometimes be harder to optimize.
  • Minimize the use of global variables.
  • Declare anything within a file (external to functions) as static, unless it is intended to be global.
  • Use word-size variables if you can, as the machine can work with these better (instead of charshortdouble, bit fields etc.).
  • Don't use recursion. Recursion can be very elegant and neat, but creates many more function calls which can become a large overhead.
  • Avoid the sqrt() square root function in loops - calculating square roots is very CPU intensive.
  • Single dimension arrays are faster than multi-dimension arrays.
  • Compilers can often optimize a whole file - avoid splitting off closely related functions into separate files, the compiler will do better if it can see both of them together (it might be able to inline the code, for example).
  • Single precision math may be faster than double precision - there is often a compiler switch for this.
  • Floating point multiplication is often faster than division - use val * 0.5 instead of val / 2.0.
  • Addition is quicker than multiplication - use val + val + val instead of val * 3puts() is quicker than printf(), although less flexible.
  • Use #defined macros instead of commonly used tiny functions - sometimes the bulk of CPU usage can be tracked down to a small external function being called thousands of times in a tight loop. Replacing it with a macro to perform the same job will remove the overhead of all those function calls, and allow the compiler to be more aggressive in its optimization..
  • Binary/unformatted file access is faster than formatted access, as the machine does not have to convert between human-readable ASCII and machine-readable binary. If you don't actually need to read the data in a file yourself, consider making it a binary file.
  • If your library supports the mallopt() function (for controlling malloc), use it. The MAXFAST setting can make significant improvements to code that does a lot of malloc work. If a particular structure is created/destroyed many times a second, try setting the mallopt options to work best with that size.

Last, but definitely not least - turn compiler optimization on! Seems obvious, but is often forgotten in that last minute rush to get the product out on time. The compiler will be able to optimize at a much lower level than can be done in the source code, and perform optimizations specific to the target processor.

Sunday, October 6, 2019

How to Print in Makefile

Source: https://stackoverflow.com/questions/11775733/how-can-i-print-message-in-makefile/11776179


 15 # for TRACEGEN
 16 include $(MAKEDIR)/Tools.make
 17
 18 ifeq ($(CONFIG_SOMETHING),y)
 19 EXTRA_CFLAGS += -fsanitize=kernel-address
 20 $(info ************  TEST VERSION ************)
 21 else
 22 $(info ************  ELSE VERSION ************)
 23 endif

$(info your_text) : Information. This doesn't stop the execution.
$(warning your_text) : Warning. This shows the text as a warning.
$(error your_text) : Fatal Error. This will stop the execution.

To print a variable in Makefile:

 18 $(info $$CONFIG_VAR1 is [${CONFIG_VAR1}])
 19 $(info $$CONFIG_VAR2 is [${CONFIG_VAR2}])


Monday, July 2, 2012

32/64 bit shared library with 32/64 applications

mylib.c
========
#include <stdio.h>

int print_hello()
{
printf("Hello.\n");
return 0;
}

int print_world()
{
printf("World.\n");
return 0;
}

char *get_str()
{
return "Hello World";
}

$> xlc -c mylib.c -o mylib.o [-q64]
$> xlc -qmkshrobj -qexpfile=mylib.exp mylib.o [-q64]
$> cat mylib.exp [You can create this export file manually as well. By default all functions will be exported]
print_hello
print_world
get_str
$> xlc -qmkshrobj mylib.o [-q64]==> This will generate shr.o (mylib.o + mylib.exp)
$> [export OBJECT_MODE=64] ==> Though u compiled the code in 64 bit, ar (nm and strip etc) command does still work in 32 bit mode.
Hence, set the object mode to 64 bit, before calling the "ar" command.
$> ar -rv libfoo.a shr.o
This will generate the shared library (static linking) in AIX.

pgm.c
======
#include <stdio.h>

/* Note these are important to inform linker */
extern int print_hello();
extern int print_world();
extern char* get_str();

int main()
{
print_hello();
print_world();
printf("String from library: %s.\n", get_str());
}

$> xlc -o pgm pgm.c -L/home/harish/temp/ -lfoo [-q32|-q64]
$> ./pgm
Hello.
World.
String from library: Hello World.

NOTE: If you have compiled the application (pgm.c) with -q32 (as 32 bit),
then you would get error :
$> xlc -o pgm pgm.c -L/home/harish/temp/ -lfoo -q32
ld: 0711-317 ERROR: Undefined symbol: .print_hello
ld: 0711-317 ERROR: Undefined symbol: .print_world
ld: 0711-317 ERROR: Undefined symbol: .get_str
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.

[Use "-bnoquiet" option to find that ELF (XCOFF) format maintained by library
is different from what 32 bit application expects.]

$> xlc -o test test.c -L/perffs/ptx/harishse/sandbox/temp -lfoo -q32 -bnoquiet
(ld): halt 4
(ld): setfflag 4
(ld): savename test
(ld): filelist 6 1
(ld): i /lib/crt0.o
(ld): i test.o
(ld): lib /perffs/ptx/harishse/sandbox/temp/libfoo.a
(ld): lib /usr/vac/lib/libxlopt.a
(ld): lib /usr/vac/lib/libxl.a
(ld): lib /usr/lib/libc.a
LIBRARY: Shared object libc.a[shr.o]: 2874 symbols imported.
LIBRARY: Shared object libc.a[meth.o]: 2 symbols imported.
LIBRARY: Shared object libc.a[posix_aio.o]: 20 symbols imported.
LIBRARY: Shared object libc.a[aio.o]: 18 symbols imported.
LIBRARY: Shared object libc.a[pse.o]: 5 symbols imported.
LIBRARY: Shared object libc.a[dl.o]: 4 symbols imported.
LIBRARY: Shared object libc.a[pty.o]: 1 symbols imported.
FILELIST: Number of previously inserted files processed: 6
(ld): resolve
RESOLVE: 36 of 6085 symbols were kept.
(ld): addgl /usr/lib/glink.o
ADDGL: Glink code added for 6 symbols.
(ld): er full
ld: 0711-318 ERROR: Undefined symbols were found.
        The following symbols are in error:
 Symbol                    Inpndx  TY CL Source-File(Object-File) OR Import-File{Shared-object}
                              RLD: Address  Section  Rld-type Referencing Symbol
 ----------------------------------------------------------------------------------------------
 .print_hello              [26]    ER PR test.c(test.o)
                                   00000028 .text    R_RBR    [12]    .main
 .print_world              [28]    ER PR test.c(test.o)
                                   00000030 .text    R_RBR    [12]    .main
 .get_str                  [30]    ER PR test.c(test.o)
                                   00000038 .text    R_RBR    [12]    .main
ER: The return code is 8.

Thursday, June 4, 2009

How the EXE is loaded into main memory for execution - The system Program Loader

Once BIOS hands control over to the OS, you may then request execution of a program.

NOTE: The program can be either .COM or .EXE. A .COM program is useful as a small utility program or as a resident program (one that is installed in memory and is available while other programs run). In real mode, an .EXE program consists of separate code, data and stack segments and is the method used for more serious programs.

When you double click on an .EXE program (when you request the system to load an .EXE program from disk into memory for execution), the System Program Loader performs following steps
  1. Accesses the .EXE program from disk
  2. Constructs a 256-byte (100H) Program Segment Prefix (PSP) on a paragraph boundary in available internal memory (NOTE: PSP is a data structure used in DOS systems to store the state of a program)
  3. Stores the program in memory immediately following PSP
  4. Loads the address of PSP in DS and ES registers
  5. Loads the address of code segment in CS register and sets the IP register to the offset of the first instruction (usually zero) in the code segment
  6. Loads the address of the stack in SS register and sets the SP register to the size of the stack
  7. Transfers control to the program for execution, beginning usually with the first instruction in the code segment