I am writing real mode function, which should be normal function with stackframes and so, but it should use %sp instead of %esp. Is there some way to do it?
GCC 5.2.0 (and possible earlier versions) support 16-bit code generation with the -m16 flag. However, the code will almost certainly rely on 32-bit processor features (such as 32-bit wide registers), so you should check the generated assembly carefully.
From the man pages:
The -m16 option is the same as -m32, except for that it outputs the
".code16gcc" assembly directive at the beginning of the assembly output
so that the binary can run in 16-bit mode.
Firstly, gcc could build 16bit code, because the linux kernel is go through realmode to protectmode, so it could even build 16bit c code.
Then, -m16 option is supported by GCC >= 4.9 and clang >= 3.5
gcc will ignore asm(".code16"),you can see it by -S output the assembly code surround by #APP #NO_APP
the linux kernel do the trick to compile 16bit c with a code16gcc.h(only have .code16gcc) pass to gcc compile params directly.
see Build 16-bit code with -m16 where possible, also see the linux kernel build Makefile
if you direct put the asm(".code16gcc"), see Writing 16-bit Code, it's not real 16bit code, call, ret, enter, leave, push, pop, pusha, popa, pushf, and popf instructions default to 32-bit size
GCC does not produce 8086 code. The GNU AS directive .code16gcc can be used to assemble the output of GCC to run in a 16-bit mode, put asm(".code16gcc") at the start of your C source, your program will be limited to 64Kibytes.
On modern GCC versions you can pass the -m16 argument to gcc which will produce code to run in a 16-bit mode. It still requires a 386 or later.
As far as I know, GCC does not support generation of code for 16-bit x86. For legacy bootloaders and similar purposes, you should write a small stub in assembly language to put the cpu in 32-bit mode and pass off execution to 32-bit code. For other purposes you really shouldn't be writing 16-bit code.
Related
I am trying to learn function call grammar in arm architecture and i compiled same code for user mode app and loadable kernel module. in attached picture you can see disassembly result for same function in two different mode. i am curious about reason of this difference.
You have compiled the code with wildly different options. The first is ARM (32bit only) and the 2nd is Thumb2 (mixed 16/32bit); see hex opcodes at the side. Thumb2 used the first 8 registers in a compact way (16bit encodings) so the call interface is different. Ie, fp is r7 versus r12. This is why you are seeing different call sequences for the same code.
Also, the first has profiling enabled (why __gnu_mcount_nc is inserted).
It really has nothing to do with 'kernel' versus 'user' code. It is possible to compile user code with similar option as the kernel uses. There are many gcc command line options which affect the 'call interface' (search AAPCS for more information and the gcc ARM options help).
Related: ARM Link and frame pointer
I know that it's generally recommended to use -march=native (if you're compiling for the machine you're on), so that gcc determines your arch and cputype and generates the most machine-specific code, but how does it do that?
Does it use cpuid (on either arm or x86)? What techniques are used on platforms without a cpuid-like instruction?
Good question.
My intuition was that it would go check /proc/cpuinfo. Actually it depends on the architecture it has been compiled to run on. It seems like host_detect_local_cpu is the function responsible for that. Its job is to replace -march=native by either the good -march=<...> or a set of flags (-mmmx, -mno-avx, etc) that match as closely as possible the current cpu. Examples for i386 and arm. i386 uses cpuid directly to check for each and every possible feature. arm checks in /proc/cpuinfo for the CPU part line and has a table that maps from a CPU part value to a generation of the architecture and use this directly in -march=<...>.
Just for fun I check on other architectures (I am not familiar with them).
solaris on sparc: uses the kstat interface
linux on sparc: uses /proc/cpuinfo
alpha: uses the implver instruction
darwin on rs6000: uses the hw.cpusubtype system call
freebsd on rs6000: uses hardcoded powerpc
linux on rs6000: checks in /proc/self/auxv for the platform value in the elf interpreter of its own process
aix on rs6000: uses _system_configuration (apparently a global structure)
I have next problem:
I have some tests related to xop check with using some Bulldozer (xop) instructions.
And I must run this tests only on Bulldozer processors.
How can I check that my processor supports xop instruction at compile-time?
Language: C, Os: Linux;
You can write a program that checks CPUID and use the output of that program while compiling:
gcc $(cpuid_test) my_prog.c
where cpuid_test returns '-march=bdver1' or -DXOP_SUPPORT=1
You cannot test at compile time, but you can compile for AMD Bulldozer using:
$ gcc -march=bdver1 -mtune=bdver1 ...
See: http://gcc.gnu.org/gcc-4.6/changes.html
If your build machine is your target machine, look into /proc/cpuinfo.
If a source is compiled with -march=bdver1 (which enables XOP support among other things), the preprocessor macro __XOP__ will be defined to 1.
You can test at compile time for XOP with
#ifdef __XOP__
...XOP code path here...
#else
...non XOP code here...
#endif
I have written some code in C and need to convert this to MIPS 64, with and without optimisation. I have been trying to convert this with gcc but this converts it to x86 which is far more complex. Furthermore, I have been trying to find a cross compiler but have not been able to get any compiler to work. Any help and suggestions will tremendously be appreciated.
Kind regards,
After downloading and installing Codesourcery codebench for MIPS, invoke the MIPS gcc cross compiler for the MIPS 64 revision 2 architecture as follows:
C:\Program Files (x86)\CodeSourcery\Sourcery_CodeBench_Lite_for_MIPS_GNU_Linux\bin\mips-linux-gnu-gcc -march=mips64r2 foo.c -S
This generates MIPS assembly source code in foo.s.
The documentation that was installed with codebench will tell you the other possible values for the -march option. Other gcc flags like -S and -O work as normal.
If you use a MIPS cross compiler, instead of a gcc that targets x86, you can complete this "conversion" (compilation). If you need to find a MIPS cross compiler (gcc), you can get one pre-built from codesourcery.com
The wording in your question seems to suggest you don't care as much that the output is MIPS, but rather you want the output to be less complex than x86. If this is the case, you might also examine the ARM output.
I am compiling on a 64 bit architecture with the intel C compiler. The same code built fine on a different 64 bit intel architecture.
Now when I try to build the binaries, I get a message "Skipping incompatible ../../libtime.a" or some such thing, that is indicating the libtime.a that I archived (from some object files I compiled) is not compatible. I googled and it seemed like this was usually the result of a 32->64 bit changeover or something like that, but the intel C compiler doesnt seem to support a -64 or some other memory option at compile time. How do I troubleshoot and fix this error?
You cannot mix 64-bit and 32-bit compiled code. Config instructions for Linux are here.
You need to determine the target processor of both the library and the new code you are building. This can be done in a few ways but the easiest is:
$ objdump -f ../../libtime.a otherfile.o
For libtime this will probably print out bunches of things, but they should all have the same target processor. Make sure that otherfile.o (which you should substitute one of your object files for) also has the same architecture.
gcc has the -m32 and -m64 flags for switching from the default target to a similar processor with the different register and memory width (commonly x86 and x86_64), which the Intel C compiler may also have.
If this has not been helpful then you should include the commands (with all flags) used to compile everything and also information about the systems that each command was being run on.