MOVING FROM ASSEMBLER TO "C": Part 1
By Jeff Robinson

If you're a TPF programmer who's been waiting for a chance to get exposure to "C" programming, now is your chance. Over the next few issues, we'll explore a fast-track method of learning "C" programming tailored specifically for TPF Assembler language programmers. In this article, we'll show you how to start thinking more like a "C" programmer and less like a TPF programmer; in Part 2, we'll take a more in-depth look at "C" and how its features replace those in TPF Assembler. Finally, in Part 3, we'll take an existing Assembler program and translate it into a "C" TPF program using all of our accumulate knowledge.

Each of these lessons will contain a "quiz" at the end and program exercises for further practice. Answers to the program exercises will be posted to my website at "http://www.robisoft.com"; answers to each quiz will also be posted there and in the next successive issue of this newsletter. Of course, both the quiz and the program exercise are optional but will definitely prove helpful in your learning to use "C" language in a TPF environment. Now, let's get started.

Prerequisites:
This course assumes that you have a basic knowledge of the use and application of TPF Assembler language programming. That's it! That's all you have to know before you begin.

Environment:
This course addresses the use of "C" in the newer ISO-C TPF environment -- not the older Target(TPF) one.

THINGS TO FORGET ABOUT
At this point in your TPF career, writing a new TPF program is probably a breeze: from allocating a new segment and determining its name (Can I name it ABXY or XYAB?) to finding which ECB levels are available and which registers to use. All these things and more like them are considered common-place tasks for a TPF applications programmer.

Now, as you delve into the world of "C" programming for TPF (hereafter we'll just use the term "C/TPF" when referring to "C" programming for TPF), you'll in for a definite culture shock. Since "C" is a high-level programming language (or HLL), C/TPF programmers let the compiler and/or the operating system worry about many of the things they used to have to take care of themselves. (A compiler is a product on your development system that converts a high-level languages like "C" into either its equivalent Assembler language or machine language format.)

Here is a list of things you can forget about using before and during the development of C/TPF programs:

  1. Basing Registers and determining their availability
  2. All RR, RX and RS instruction types (you'll still find use for the equivalent features "C" provides for SS and SI instruction types).
  3. Data DSECTS and Assembler Macros
  4. Getting and Manipulating Core Blocks
  5. If you'll be using a database management system such as TPFDF or Persistent Collections, ECB level availability will be an unimportant item also.
  6. In fact, most times you won't be concerned about the ECB at all. However, there still may be instances in which you'll need to retrieve or store information in ECB-related fields.
  7. Most of the traditional TPF macros like ENTRC, BACKC, RELCC, GETFC, EXITC, and FLIPC will be of little use to you in the C/TPF world.

Once you began programming in "C", you'll realize that there is an implied trust between the programmer, the compiler and the operating system that goes something like this: "Let me (the programmer) worry about writing the meat of the application and I'll trust you (the OS and the compiler) with taking care of the low-level concerns such as registers, core blocks and the ECB."

THE BASIC "C" BUILDING BLOCK
When you learned to write TPF Assembler programs, you learned that every program should have the following basic structure:

...

BEGIN NAME=ABCD,VERSION=A0

*

*The program body would follow these comments

*

*

LTORG ,

FINIS ABCD

END ,

...

The above code segment contains all of the basic building components required to assemble the program cleanly in a TPF environment. For, C/TPF, the basic building block is called a 'function'. A Function in C/TPF will contain the necessary code to carry out a specific action or actions that the programmer wishes to have done. A basic C/TPF function would look like this:

....

#include <stdio.h>

#include <tpfapi.h>

void abcd()

{

/* The Body of the C function would follow

these comments. */

return;

}

...

If the above lines of "C" code looks like "gobbledy-gook" to you, then don't feel concerned. "C" has often been described as an "ugly" programming language which takes some time to get used to. Meanwhile, an explanation of each part of the above function follows.

  1. The first two lines ( #include <stdio.h>,#include <tpfapi.h>) are compiler instructions equivalent to macro calls in an Assembly language program. The directive, "#include", instructs the compiler to go to the default library system and look for files named "stdio.h" and "tpfapi.h", respectively, and then to "pre-process" those files BEFORE the actual compilation begins.
  2. (Details of the "pre-processor" step are beyond the scope of this course; for now you simply need to know that the pre-processor step is critical for the compiler because the files that are processed help it to resolve the use of external functions and other references your function might use.)

  3. Line 3 -- void abcd() -- is equivalent to the BEGIN macro of an Assembler program. Every function must begin with a statement similar to this one. Not only does it declare the name of the function (abcd in this case), but it also indicates what value (if any) the function will return to the process that invoked it. In this example, the "void" keyword is used to indicate that this function will NOT return any value to the process that called it. (A keyword is a word in "C" that has special meaning and cannot be used by the programmer except for its pre-set purpose. We'll look at other "C' keywords in later articles).
  4. Although not shown in this example, the process that called function abcd() could have also "passed" or handed values (called parameters) to the abcd() function for it to use. Parameters specify the types, sizes and names of values passed to a function. If abcd() had had any parameters passed to it, this would have been shown between the parentheses of the abcd() function. Example: void abcd(int value1, int value2)

  5. Line 4 of the function contains a left curly brace; in "C" this is called a token and it is used in this instance to indicate the start of the body of the function abcd(). The left brace is required on every function to indicate the start of that function's body.
  6. After the left brace follows a standard "C" comment. Comments in "C" begin with the forward slash followed by an asterisk (/*). The end of a comment in "C" is indicated by an asterisk followed by another forward slask (*/). The comment and anything occuring between the comment's begin and end are IGNORED. You can place a comment on a line by itself as done in our example or it can follow or precede instructions on the same line in a function.
  7. Following the comment is the "C" statement "return;". This statement is equivalent to a BACKC statement in a TPF Assembler program. It terminates execution of a function and gives control back to the calling process. Note the semicolon on the return statement. Semicolons are very important in "C" because they must be used to indicate the physical end of statements. If the semicolon is left off, the compiler doesn't know where you want the return statement to end and you'll get a compiler error.

    As you'll see in later lessons, the return statement can also be used to give back results to the calling process. To do this, one would simply include the name holding the value to be returned after the return keyword and before the semicolon. Example: return value1;

    When thinking of "passing" values and "returning" them, think of the game of basketball. One player (a function) "passes" the ball (our value) to a second player. When the second player finishes with the ball, he may give it back (return) to the first player or "pass" it to another. This is how passing and returning parameter values work in "C" programs.
  8. Finally, the last line in the function is the right curly brace: }. This token is a required part of every function and is used to indicate the physical end of that function. Without this ending brace, the compiler would have given you an error because it would not know where you wanted the function to end. (Note that the return statement is not required in the abcd function; it is used here as a visual indication to show where the function gives up control If it had been omitted, the right brace would have accomplished the same task.)

QUIZ
That's it for Part 1 of this article series. Now, let's test what you've learned with a brief quiz:

  1. Even for C/TPF application programmers, knowing which registers to use are of prime importance. True or False?
  2. The ECB work areas are never regularly accessed in C/TPF programs to store and retrieve temporary work values. True or False?
  3. A function is one of the many basic building blocks of a "C" program. True or False?
  4. Which parenthesis is used in "C" to indicate the end of a function?
  5. Which keyword discussed in this article has special meaning to the "C" compiler and cannot be used by the programmer except for its intended use?
  6. If you want to pass information to a function, you do so using what mechanism?
  7. The ___________ statements are compiler instructions equivalent to macro calls in a TPF assembler language program. Fill in the blank.
  8. The ___________ is required to indicate the start of a function body. Fill in the blank.
  9. Which of the following items were stated as being required in the "C" program used in this article? A.) The void keyword
  10. B.) The left and right curly brace

    C.) The return statement

    D.) The include statements

    E.) All of the above

    F.) None of the above

  11. The semicolon is a required token used to indicate the end of statements in "C" programs. True or False?

PROGRAM EXERCISES
A. Determine which statements in the following TPF Assembler language program would NOT be required if you had to convert the program to its C/TPF equivalent.

BEGIN NAME=XYZ1,VERSION=A0

**********************************************************************

*THE PURPOSE OF THIS PROGRAM IS TO CHECK THE CHARACTER IN THE 7TH *POSITION OF THE INPUT MESSAGE. IF ITS A 'Y' FOR YES, THEN WIPE OUT *THE PASSENGER NAME CURRENTLY BEING WORKED UPON. OTHERWISE, *JUST EXIT AND RETURN.

**********************************************************************

MI0MI REG=R1

PN0NR REG=R3

*

L R1,CE1CR0 BASE THE INPUT BLOCK

L R3,CE1CR2 BASE THE PASSENGER NAME BLOCK

CLI MI0ACC+7,C'Y' ZERO OUT THE CURRENT PASSENGER NAME ?

BNE EXITHERE IF NOT 'Y', THEN GO TO EXIT

XC PN0NM,PN0NM ZERO OUT THE CURRENT NAME RECORD

*

EXITHERE DS 0H

BACKC ,

*

LTORG ,

FINIS XYZ1

END ,

B. Convert the Assembler program above to a "C" function using the information given in this lesson. For lines you can't convert, make those lines comments and indicate where the "C" equivalent statements might go.

C. Using the information in this article, write a C/TPF function that receives two parameters passed to it of "int" type and returns the first value passed.