Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Advanced C 1992

.pdf
Скачиваний:
96
Добавлен:
17.08.2013
Размер:
4.28 Mб
Скачать

Part III • Working with Others

and get every ounce of performance out of it. (Remember, though, that it is easy to create assembly functions that are not as efficient as a function written in C and compiled with the compiler’s optimization turned on.)

Your project is on a tight schedule, so you must purchase a library of functions to save development time.

When you purchasea library of functions, be sureit includes thesourcecode. You cannot depend on the supplier of the code to respond to your needs, and without source code you are on your own. I have never used code written by someone else without making at least one change. As well, if the supplier goes out of business, you can keep your product running if you have source code.

Peter’s rule: When you buy a library of functions, get the source code. If it is unavailable, look for a different product.

Other Languages

This chapter considers four languages other than C: assembly, BASIC, FORTRAN, and Pascal. All have been around for many years and are standardized. If your program must interface with a language not mentioned in this chapter, do not despair. Check whether the language you are using calls functions in a manner similar to one of the languages described here.

Table 11.1 shows the types of routines for each language. The major difference is that in FORTRAN a function returns a value, but a subroutine does not have a return value. When a function executes, a dummy variable with the same name as the function is created to hold the return value. (An example of this is shown in Listing 11.7, later in this chapter.)

436

C and Other Languages

C C C

 

11C

 

C C C

 

C C

Table 11.1. Routine types for different languages.

Language

Returns a value

Has no return

value

 

 

assembly

Procedure

Procedure

BASIC

FUNCTION

Subprogram

C

function

(void) function

FORTRAN

FUNCTION

SUBROUTINE

Pascal

Function

Procedure

 

 

 

Do not ignore your C compiler’s power. Almost all C compilers produce a mixed (or perhaps a pure) assembly listing of the functions being compiled. Typical assemblylisting options that you can use are shown in Table 11.2.

Table 11.2. C compiler assembly-listing options.

Option

Description

Compiler

/Fa

Produces an assembly

Microsoft

 

output file

 

/Fc

Produces a mixed object

Microsoft

 

and source listing file

 

/Fl

Produces an object

Microsoft

 

listing file

 

/S

Produces a mixed

Borland C++

 

assembly/source listing

 

 

file

 

WDISASM

Produces (with options)

Watcom

(a stand-alone

assembly/object listing

 

program)

files

 

 

 

 

437

Part III • Working with Others

If you use the options listed for Microsoft compilers, you must use the full compiler, not QuickC or QuickC for Windows. Neither of the QuickC compilers produces an assembly or object listing.

Watcom’s utility (WDISASM) has a number of options documented in the manual. It can disassemble .OBJ files produced by any Microsoft compatible compiler (one that produces compatible .OBJ files). You must check that the disassembly is correct, however, because not all .OBJ files disassemble correctly. Sometimes, disassembly by hand (a long and tedious process) is the only way to find out what the compiler did for a given block of code.

Do not overlook using the DOS DEBUG command to look at .EXE and .OBJ files. It has a crude disassembler, and it can help you see what is happening. Most debuggers can provide a disassembly listing as well.

Some compilers (such as Watcom’s C/386) do not provide an assembly listing, but do come with a utility program to produce assembly. In Watcom, for example, the WDISASM utility disassembles an .OBJ file.

You can save hours of programming if you use the compiler’s assembly listing option to produce an assembly program that is compatible with C programs. You can save time also if you already know the arguments that are passed to the function. Create a dummy function with as much of the necessary functionality as possible, then use the output of the compiler’s assembly listing as the starting point for your assembly routine.

Assembly

Assembly is not a language. Rather, it is a method to use the CPU’s native machine language. You must specify everything when writing in assembly: where data objects come from, where they will go, the basic operations, and so on. To use assembly language, you must be very familiar with how the CPU works.

Listing 11.1, CALLASM, is a simple example of how assembly works. It is written in assembly, and can be linked with the C libraries.

438

C and Other Languages

C C C

 

11C

 

C C C

 

C C

Listing 11.1. CALLASM.ASM.

;

;CALLASM.ASM: This program calls the C printf() function

;

and prints a string on the terminal.

 

;

 

 

 

 

 

NAME

CALLASM

 

 

 

EXTRN

_printf:BYTE

; Prototype for

printf()

 

 

 

 

 

EXTRN

_ _acrtused:BYTE

; Used to initialize C

 

 

 

;

startup code

DGROUP

GROUP

_DATA,CONST,_BSS

; Establish the DGROUP

_TEXT

SEGMENT

WORD PUBLIC ‘CODE’

; Name the code

 

 

 

;

segment _TEXT

 

ASSUME

CS:_TEXT,DS:DGROUP,SS:DGROUP

 

 

PUBLIC

_main

; Our function is

 

 

 

;

main()

_main:

mov

word ptr nCount,0000H

; Initialize nCount to

 

 

 

;

zero

 

mov

ax,offset DGROUP:szBuffer

; Get address of

 

 

 

;

szBuffer[]

 

push

ax

; Push on stack as the

 

 

 

;

last\parameter to

printf()

 

 

 

 

 

mov

ax,offset DGROUP:L1

; Get format string

 

 

 

;

address

 

push

ax

; Push on stack as the

 

 

 

;

next parameter to

 

 

 

;

printf()

 

call

near ptr _printf

; Now call printf()

 

add

sp,0004H

; Discard printf()’s

 

 

 

;

parameters

 

mov

word ptr nCount,ax

; Save printf()’s

 

 

 

;

return value

 

 

 

; Done, return to

 

 

 

;

caller

_TEXT

ENDS

 

 

 

_DATA

SEGMENT

WORD PUBLIC ‘DATA’

; Set up the data

 

 

 

;

segment

continues

439

Part III • Working with Others

Listing 11.1. continued

 

 

 

; PUBLIC is the same

 

 

 

;

as C’s

 

 

 

; extern variables

 

PUBLIC

szBuffer

; szBuffer is a public

 

 

 

;

name

 

PUBLIC

nCount

; nCount is a public

 

 

 

;

name

szBuffer

LABEL

BYTE

 

 

 

DB

“This is an assembly program.”

 

 

DB

0aH,00H

; append the \n for

 

 

 

;

newline

nCount

LABEL

BYTE

 

 

 

DB

00H,00H

; nCount, init to zero

_DATA

ENDS

 

 

 

CONST

SEGMENT

WORD PUBLIC ‘CONST’

 

 

L1

LABEL

BYTE

 

 

 

DB

“%s”,00H

; Our format string, a

 

 

 

;

constant, in the

 

 

 

;

CONST

 

 

 

;

segment

CONST

ENDS

 

 

 

_BSS

SEGMENT WORD PUBLIC ‘BSS’

; The BSS segment is

 

 

 

;

used

 

 

 

;

by C to find the

 

 

 

;

stack and

 

 

 

;

has other uses,

 

 

 

;

including

 

 

 

;

storage for global

 

 

 

;

variables

 

 

 

;

not initialized

 

 

 

;

explicitly

_BSS

ENDS

 

;

by the program

 

END

 

; End of our program

 

 

 

 

 

440

C and Other Languages

C C C

 

11C

 

C C C

 

C C

Nobody recommends that you write an assembly program that calls C functions. Instead, write the program as a C program, then call the functions coded in assembly from C.

FORTRAN

FORTRAN was the first programming language developed, although the first compilers were created by Grace Hopper in the early 1950s. These compilers were simple and inefficient, and the “languages” they supported were never named.

FORTRAN (short for FORmula TRANslation) can trace its roots to the early 1950s, when John Backus and Irving Ziller at IBM set out to develop a new computer language for the soon to be released IBM 704 computer. The development team grew to many more members, and in April 1957, they completed the first FORTRAN compiler.

The IBM 704 was the first computer to implement floating point in hardware. Until that time, computers used software emulation to perform floating-point math.

A typical FORTRAN program is shown in Listing 11.2, DEMO.FOR.

Listing 11.2. DEMO.FOR.

*DEMO.FOR

*A simple, typical FORTRAN program. This program

*is equivalent to the standard HELLO.C program.

*2345678----

program hello

print *, ‘Hello (FORTRAN)’

end

441

Part III • Working with Others

Pascal

Pascal is taught extensively at schools and universities, but has never caught on in a nonacademic environment, mostly due to the lack of good compilers. Apple released a UCSD Pascal system for the Apple II, but the implementation was crude and almost impossible to use productively, requiring a custom operating system incompatible with the existing Apple II operating system. Pascal became popular on PCs due only to the efforts of Borland, who released a good and inexpensive compiler called Turbo Pascal.

Although Pascal is still used today (and some Pascal compilers, most notably Turbo Pascal, remain), you will seldom see libraries of Pascal code that you will want to include in your C application. It is more likely you will have to convert a Pascal program to C. This conversion is easier if you can call Pascal functions from the C code, and convert each function one at a time. A typical Pascal program is shown in Listing 11.3.

Listing 11.3. HELLO.PAS.

/* HELLO.PAS

*A simple, typical Pascal program. This program

*is equivalent to the standard HELLO.C program.

*/

program hello

begin

writeln(‘Hello, from Pascal’);

end.

The example program looks very much like a C program. The comments are delimited in the same manner (using /* and */), statements end with a semicolon, and the begin and end keywords are similar to braces in C.

442

C and Other Languages

C C C

 

11C

 

C C C

 

C C

BASIC

BASIC (Beginner’s All-Purpose Symbolic Instruction Code) is the first language used by most beginning programmers. It is simple and easy to learn, but not used for serious programming due to its limitations.

There are few reasons to interface BASIC code with C and even fewer methods. Several BASIC compilers are available, but none produce code compatible with C code created with a C compiler. The best way to interface BASIC and C is to convert the BASIC code to C, producing a new program that is bound to be better than the original.

A simple BASIC program is shown in Listing 11.4, HELLO.BAS. It’s the shortest example of a hello program!

Listing 11.4. HELLO.BAS.

PRINT “Hello”

Calling Other Languages from C

Usually, you write the main body of your program in C. Then you may use a few functions written in another language because you want to enhance the speed of the program (assembly code can be much faster than code written in a higher level language) or because you do not want to rewrite the functions in C.

This section describes how to create a basic C application and how to call a function created in another language. First, the main program is created in C, as shown in Listing 11.5, CALLNOTC.C. This program calls a non-C function called max() to determine the maximum of two numbers.

Listing 11.5. CALLNOTC.C.

/* CALLNOTC program, written 1992 by Peter D. Hipson */

Listing 11.5./* This C program calls C, FORTRAN, or assembly */

continues

443

Part III • Working with Others

Listing 11.5. continued

#include <stdio.h> #include <stddef.h> #include <stdlib.h> #include <string.h> #include <time.h>

int

cdecl maximum(int nVar1, int nVar2);

int

main()

{

 

int

nVar1 = 0;

int

nVar2 = 1;

char szBuffer[256];

printf(“Enter the same number twice to end\n”);

while(nVar1 != nVar2)

{

printf(“Enter two integers, separated with blanks”);

gets(szBuffer);

sscanf(szBuffer, “%d %d”, &nVar1, &nVar2);

printf(“The values entered are %d and %d. The larger is %d\n”, nVar1,

nVar2,

maximum(nVar1, nVar2));

}

return(0);

}

/* This is maximum() written in C */ int maximum(

444

C and Other Languages

C C C

 

11C

 

C C C

 

C C

int

nVar1,

int

nVar2)

{

if (nVar1 < nVar2)

{

return(nVar2);

}

else

{

return(nVar1);

}

}

In the maximum() function, four lines of code do most of the work: a compare and two return values. Many programmers consider multireturns in a single function to be poor programming style. I do not agree, but I do not use goto except to a single label near the end of the function just before the cleanup code.

To see what a typical C compiler does with the maximum() function, look at the following output from the Microsoft C 7.00 compiler (without optimization):

 

 

_maximum:

 

*** 00008a

55

 

push

bp

*** 00008b

8b

ec

mov bp,sp

*** 00008d

81

ec 00 00

 

sub sp,OFFSET L00390

*** 000091

56

 

push

si

*** 000092

57

 

push

di

;; Line 50 if (nVar1 < nVar2)

***000093 8b 46 06 mov ax,WORD PTR 6[bp]

***000096 39 46 04 cmp WORD PTR 4[bp],ax

*** 000099

7c

03 e9 00

00

jge L00387

; ; Line 51

 

{

 

 

 

; ; Line 52

 

 

return(nVar2);

 

*** 00009e

8b

46 06

mov ax,WORD PTR 6[bp]

*** 0000a1

e9

00 00

jmp L00386

; ; Line 53

 

}

 

 

 

; ; Line 54

 

else

 

 

 

*** 0000a4

e9

00 00

jmp L00388

 

 

 

L00387:

 

 

; Line 54

else (continued...)

 

continues

445