5

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: Inline assembly error Turbo C 2.01

Any ideas?

Jester
  • 56,577
  • 4
  • 81
  • 125
mythbu
  • 786
  • 1
  • 7
  • 20
  • 4
    Apart from "don't try to use decades old technology", you mean? :) – Jester Nov 30 '17 at 18:58
  • Have you tried inserting C before and after it in the function? Perhaps it's simply not allowing *only* assembly there? – Brian Knoblauch Nov 30 '17 at 19:01
  • 1
    The Wikipedia page for [Borland Turbo C](https://en.wikipedia.org/wiki/Borland_Turbo_C) says *"Version 2.0 . . . The American release did not have Turbo Assembler or a separate debugger. (These were sold separately as Turbo Assembler.)"* That was thereabout 1987-8. – Weather Vane Nov 30 '17 at 19:06
  • @WeatherVane what a scam. I don't think a company with such attitude will last long... @ **OP**: please, don't. I think there's something like OpenWatcom, being build on foundation of one of most performant C/C++ compilers from DOS era, also supporting 32b protected mode extenders like DOS4GW, etc... if you really want to touch DOS, use that kind of technology. At least the 32b assembly will be somewhat relevant to win32/linux32. – Ped7g Nov 30 '17 at 19:40
  • @Ped7g another 20 years from then? – Weather Vane Nov 30 '17 at 19:44
  • 1
    This brings back memories. You may find that inline assembly isn't supported when compiled from the Turbo-C IDE, however it may be available at the command line. If you invoke TCC from the command line to compile this code. I believe you needed to use the `-B` option for it to parse the inline assembly. – Michael Petch Nov 30 '17 at 19:58
  • And that also assumes you have TASM installed. As someone mentioned above some variants of Turbo-C did't come with TASM bundled with it. Here in Canada we were lucky. You can still install is separately and copy TASM.EXE into the TC `bin` directory. – Michael Petch Nov 30 '17 at 20:18
  • I have browsed through some archives from about 20 years ago, and can't find a single example of inline assembler in a Turbo C file. The nearest is the use of `struct` for input and output registers to a MS-DOS function call. Back in the day, I found the IDE features for tracing, stepping over functions, breakpoints and watches very good. – Weather Vane Nov 30 '17 at 20:32
  • 1
    @WeatherVane I have, I use to write it occasionally although I seem to recall the version that far back it didn't support the `asm {}` and you may have had to put each on individual lines starting with `asm` . Turbo-C professional 2.01 (came with standalone debugger and assembler) definitely supported it from the command line. You had to use TCC.EXE `-B` option to get it to work properly without a bunch of warnings.What I do know is that the TC IDE in 2.01 didn't support it. Had to invoke TCC.EXE directly. – Michael Petch Nov 30 '17 at 20:37

2 Answers2

6

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.

Community
  • 1
  • 1
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • This is in line with what I remember (and what I mentioned in the comments). What the reference doesn't tell you is what is what the typical mechanism for using inline assembly actually was in that release. What I remember from actual usage in that old version is that it didn't support `asm {}` with curly braces. Each line of inline assembly had to be emitted as `asm instruction operands;` – Michael Petch Nov 30 '17 at 20:50
  • I believe the odd restriction is likely due to the fact that unless you bought the professional version of 2.00(2.01) it lacked the TASM.EXE (and even the standalone TD.EXE for debugging). They probably shipped a version of the IDE that catered to the lowest common denominator (non-professional version) where as the command line version would work but it also meant you had to install TASM.EXE separately. – Michael Petch Nov 30 '17 at 20:56
  • @MichaelPetch : So the solution may still not work if the "museum code" lacks the assembler. But most other IDEs support the specification of arbitrary command line switches to allow features not supported in the IDE dialogs. – Clifford Nov 30 '17 at 20:58
  • That is correct. What I do know for absolute certainty is that you need to install the standalone version of TASM to get this working. If you don't, TCC.EXE use to abort out saying TASM.EXE couldn't be found. – Michael Petch Nov 30 '17 at 20:59
  • 1
    I feel so old. I installed Turbo C Professional 2.0(actually on disk is 2.01) then extracted the TASM.EXE from the TASM disks (it is inside TASM.ZIP). Put it in the TC bin directory. After playing around discovered that `asm{}` isn't supported as I mentioned above. I had to put each line of inline assembly in individual `asm` statements. In his case I used `asm nop;` . Compiled his program with `TCC -LC:\TC\LIB\ -B TEST.C` and it did work and emitted the instruction as expected. – Michael Petch Nov 30 '17 at 21:52
  • 2
    Yes, inline assembly syntax not being standardised is his *next* problem. – Clifford Nov 30 '17 at 22:59
1

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.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • 1
    Turbo C (even 2.01) allows for it, but you can't do it from the IDE. You can see my comments under the other answer. Turbo-C supports single instruction `asm` statements (doesn't support curly braces}. From the command line you use the `-B` option with TCC.EXE. This causes TCC to emit the assembly (this isdifferent from the normal operating mode of TC) and then runs that through TASM.EXE. TASM.EXE came as a separate install with TC 2.01 Professional. You can copy the TASM.EXE into the TC directory and it should work. – Michael Petch Nov 30 '17 at 22:17
  • The documentation for TC 2.0 actually has information on the `-B` option and that it is only supported when running the command line TCC.EXE. What the documentation lacks is the actual supported `asm` directive. I only knew it from past experience doing what this OP is trying to achieve. – Michael Petch Nov 30 '17 at 22:18
  • And I got my answer about the asm directive from compuserv decades ago lol – Michael Petch Nov 30 '17 at 22:34
  • @MichaelPetch: Given how convenient the IDE was to use, I avoided doing anything in my code that would require the use of the command-line-based compiler. If one is using modern rather than vintage hardware the extra time to have the C compiler process everything into assembly language and then run the assembler on that may not be an issue, but back in the day making everything compile in a single shot was definitely desirable. Unless one is trying to do something that can't be done with `__emit`, I'd regard `__emit` as preferable. – supercat Nov 30 '17 at 22:47