I want to write some inline assembly in a DOS program which is compiled using Turbo C 2.01. When I write
asm {
nop
}
the compiler claims that in-line assembly is not allowed in function .... See:
Any ideas?
See the Turbo C user manual page 430:
Inline assembly not allowed
Your source file contains inline assembly language statements and you are compiling it from within the
Integrated Environment. You must use the TCC command to compile this
source file.
I believe that you need also to pass the -B option to TCC (page 455).
Alternatively you can use __emit__ (page 103) for relatively simple code entered as machine code rather than assembler mnemonics.
It seems an odd restriction to not allow inline assembly in the IDE. You might consider "upgrading" to Turbo C++ 3.0 which I believe does allow it. I would imagine that TC++ will compile C code when presented with a .c file, or that the IDE can be set to compile C explicitly. There's a manual for that too.
Turbo C converts C code directly into machine code without using an assembler phase, and thus cannot include assembly language source within a program. What it can do, however, is use the __emit directive to insert machine code. The cleanest way to use that is probably to use a separate assembler (or perhaps DEBUG) to process the code of interest by itself into a COM file, and then enter the byte values therein into an __emit directive. Parameters are stored in ascending order left to right, starting at either BP+4 (in tiny, small, or compact model) or BP+6 (medium, large, or huge). Local variables are stored at addresses below BP.
When using Turbo Pascal, it's possible to use a handy program called "inline assembler" to convert assembly-language source into a Turbo Pascal literal-code directive. Turbo Pascal's directive is formatted differently from C's (I like Pascal's better) and can accommodate labels in ways Turbo C's cannot. Still, using __emit may have far less impact on build times than trying to use inline assembly code.
Related
I'm learning assembly for 80x86 this semester. A typical asm file I write looks something like
.model tiny
.486
.data
#initializations
.code
.startup
#actual code
.exit
end
I was expecting a similar format when I created a .s file for a simple hello world. But I don't see any of the segments with their proper names and it's all very different. I compile using g++ -S -O0 hello.c
Why is the assembly for c so different than the assembly they make us write in class? Is the assembly I'm learning used by a different programming language? If I want to get the assembly version (that I'm used to) of hello world from some higher-level code, how do I do that?
The code does not match your command line. That is neither C (file name) nor C++ code (command line). That is assembly language.
Assembly language varies by tool (masm, tasm, nasm, gas, etc), and is not expected to be compatible nor standard in any way. Not talking about just intel vs at&t, all of the code, and this applies to all targets not just x86, easily seen with ARM and others.
You should try to use the assembler not a C nor C++ compiler as that creates yet another assembly language even though gcc for example will pass the assembly language on to gas it can pre-process it through the C preprocessor creating yet another programming language that is incompatible with the gnu assembler it is fed to.
x86 is the last if ever assembly language/instruction set you want to learn, if you are going to learn it then starting with the 8086/88 is IMO the preferred way, much more understandable despite the nuances. Since this appears to be a class you are stuck with this ISA and cannot chose a better first instruction set. (first, second, third...)
Very much within the x86 world, but also for any other target, expect that the language is incompatible between tools and if it happens to work or mostly work that is a bonus. Likewise there is no reason to assume that any tool will have a "masm compatible" or other mode, simply stating intel vs at&t is only a fraction of the language problem and is in no way expected to make the code port between tools.
Re-write the code for the assembly language used for the assembler is the bottom line.
Some C compilers emit assembly language and allow snippets of assembly to be placed inline in the source code to be copied verbatim to the output, e.g. https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html
Some compilers for higher-level languages emit C, ranging from Nim which was to some extent designed for that, to Scheme which very definitely was not, and takes heroic effort to compile to efficient code that way.
Do any such compilers, similarly allow snippets of C to be placed inline in the source code, to be copied verbatim to the output?
I'm not sure I understand what you mean by "be copied verbatim to the output," but all C compilers (msvc, gcc, clang, etc...) have preprocessor directives that essentially allow snippets of code to be added to the source files for compilation. For example, the #include directive will pull in the contents the specified file to be included in compilation. An "effect" of this is that you can do weird things such as:
printf("My code: \n%s\n",
#include "/tmp/somefile.c"
);
Alternatively, creating macros with the #define directive allows you to supplant snippets of code by calling a macro name. This all happens at the preprocessor stage before turning into the compile "output."
Other languages, like c# with roslyn, allows runtime compilation of code. Of course, you can also implement the same within c by calling your compiler as via something like system() and then loading the resulting library with dlopen.
Edit:
Now that I come back and think about this question, I should also note that python is one of those C-targeting "compilers" (I guess technically a interpreter on top of the python runtime). Python let's you use native C compiled code with some either some py API code to export functions or directly with some dlopen-like helpers. Take a look at the inlinec module that does what I described above (call the compiler then load the compiled code). I suppose you should have the ability to do similar functionality with any language that can call c compiled code (c#, java, etc...).
I'm writing a proof-of-concept JIT compiler in C, which at the moment is generating strings of assembly code. The inline assembly functionality in C only deals with string literals that are known at compile time, so I can't use it to run my generated-at-runtime code.
I've read about using mmap() to execute generated machine code at runtime, but I'd like to avoid working with machine code if possible.
Does anyone know of any solutions? I've thought of writing it to a file and invoking the assembler & linker on said file, but that'd be messy and slow.
I think ultimately to be "JIT" you need to be time sensitive which means generate machine code. You might try putting in some debug code that generates both machine code to run and assembly code to verify, run the assembler compare the machine code from the assembly language to the machine code you generated directly and use that to debug/validate the machine code (if possible, sometimes assemblers want to do their own thing, not what you wanted them to do).
What I've done is generate C/C++/Fortran code, compile it on the fly, link it into a DLL, and dynamically load the DLL, all of which takes on the order of a few seconds at most.
You could do the same, except generate ASM.
It's a very effective technique when you need speed of the resulting code, plus the flexibility of the code (and run-time libraries) of the language you're generating.
I always read things about how certain functions within the C programming language are optimized by being written in assembly. Let me apologize if that sentence sounds a little misguided.
So, I'll put it clearly: How is it that when you call some functions like strlen on UNIX/C systems, the actual function you're calling is written in assembly? Can you write assembly right into C programs somehow or is it an external call situation? Is it part of the C standard to be able to do this, or is it an operating system specific thing?
The C standard dictates what each library function must do rather than how it is implemented.
Almost all known implementations of C are compiled into machine language. It is up to the implementers of the C compiler/library how they choose to implement functions like strlen. They could choose to implement it in C and compile it to an object, or they could choose to write it in assembly and assemble it to an object. Or they could implement it some other way. It doesn't matter so long as you get the right effect and result when you call strlen.
Now, as it happens, many C toolsets do allow you to write inline assembly, but that is absolutely not part of the standard. Any such facilties have to be included as extensions to the C standard.
At the end of the road compiled programs and programs in assembly are all machine language, so they can call each other. The way this is done is by having the assembly code use the same calling conventions (way to prepare for a call, prepare parameters and such) as the program written in C. An overview of popular calling conventions for x86 processors can be found here.
Many (most?) C compilers do happen to support inline assembly, though it's not part of the standard. That said, there's no strict need for a compiler to support any such thing.
First, recognize that assembly is mostly just human (semi-)readable machine code, and that C ends up as machine code anyway.
"Calling" a C function just generates a set of instructions that prepare registers, the stack, and/or some other machine-dependent mechanism according to some established calling convention, and then jumps to the start of the called function.
A block of assembly code can conform to the appropriate calling convention, and thus generate a blob of machine code that another blob of machine code that was originally written in C is able to call. The reverse is, of course, also possible.
The details of the calling convention, the assembly process, and the linking process (to link the assembly-generated object file with the C-generated object file) may all vary wildly between platforms, compilers, and linkers. A good assembly tutorial for your platform of choice will probably cover such details.
I happen to like the x86-centric PC Assembly Tutorial, which specifically addresses interfacing assembly and C code.
When C code is compiled by gcc, it's first compiled to assembler instructions, which are then again compiled to a binary, machine-executable file. You can see the generated assembler instructions by specifying -S, as in gcc file.c -S.
Assembler code just passes the first stage of C-to-assembler compilation and is then indistinguishable from code compiled from C.
One way to do it is to use inline assembler. That means you can write assembler code directly into your C code. The specific syntax is compiler-specific. For example, see GCC syntax and MS Visual C++ syntax.
You can write inline assembly in your C code. The syntax for this is highly compiler specific but the asm keyword is ususally used. Look into inline assembly for more information.
I've been looking through questions on here and the internet for a while now and I cannot seem to find out whether or not it is possible to do inline assembly with GCC using something other than GAS. I am trying to find if I can avoid using not only GAS's AT&T syntax (though, I know how to use Intel syntax with GAS) but the extended asm format. While this is not for a project or anything other than my own curiosity, I would really appreciate any help I can get (this is actually my first question here because I could not find an answer about it)! Also, if this makes any difference, I'm currently using DevC++ (for C code, not C++) on Windows.
Thanks,
Tom
You can link the output from an assembler (a ".o" or ".obj" file) with your C or C++ program. Put your assembler code in a text file. Your IDE or makefile will assemble it just as it would any c source file. The only tricky bit is learning how to interface between the two different systems.
You cannot use another inline assembly syntax with GCC. inline assembly is implemented by GCC literally including the assembly you write inline with its own (textual) assembly output, which it then sends to gas to be assembled. Since GCC doesn't know how to change the format of its own output to feed to another assembler, you can't change the inline assembly, either.