IN-LINE CODE. ßßßßßßßßßßßßß When a Turbo Pascal program is compiled it is converted to machine code, which can be inspected using the DOS Debug utility, as described in the module entitled 'Using Registers'. Of course, machine code can also be created by assembling code written in assembly language. This will generally be more efficient and/or precise than compiled code. There are two ways to link machine code with Turbo Pascal programs: For long machine code programs, it is advisable to write these as procedures or functions in assembly language and assemble them into .OBJ files. They can then be called from a Turbo Pascal program provided the procedure or function is declared as 'external'. Further details can be found in the Reference Guide on pages 199-205. Ideally Turbo Assembler (TASM) should be used for this purpose and this lies outside the scope of these notes. For very short assembly language subroutines, Turbo Pascal's 'inline' statements and directives are very convenient. They allow the insertion of machine code instructions directly into the program or unit instead of through an object file. An inline statement consists of the reserved word 'inline' followed by one or more inline elements, separated by slashes and enclosed in parentheses. The inline elements generally consist of two hexadecimal digits representing machine code operations or operands, separated by forward slashes. The op-code for 'No OPeration' (NOP) is $90 and three such NOP codes are often used to mark compiled code for ease of inspection. The appropriate inline statement is Inline($90/$90/$90); The hexadecimal values in the inline statement are the direct translation of assembly language mnemonics into machine code, which can be obtained by use of the DOS Debug utility. Assembly language is a low-level language closest to the native machine code of the computer, with each assembly language statement translating into one machine code instruction. In contrast Turbo Pascal statements may require many machine code instructions. Whereas it is possible to write directly in machine code, it is much easier to write in assembler, because the mnemonics used are meaningful. The 8086 instruction set has over 150 mnemonics and a suitable reference must be consulted for full details. ('Assembly Language Interfacing in Turbo Pascal' by Sanjiva Nath, MIS Press or 'Programming the 8086/8088' by James W. Coffron, Sybex Inc.). A few typical assembler mnemonics are as follows: ADD Add destination to source CMP Compare destination to source INT Call interrupt IRET Interrupt return JMP Jump to target JNZ Jump if not zero JZ Jump if zero MOV Move to destination from source MUL Multiply The mnemonic, which translates to the Op Code, is usually followed by operand(s), frequently the registers of the CPU or numerical values. This is illustrated below for a simple routine to activate the bell (ASCII code 7 or Ctrl G). MOV DL,07 { Move the value 7 into the register DL } MOV AH,02 { Move the value 2 into the register AH } INT 21 { Call interrupt 21 with AH = 2 to display output } INT 20 { Terminate the program } These instructions can be assembled in debug as follows: C:>debug { type debug after DOS prompt for active drive, etc } -a 0100 { type a and offset address after debug prompt - } 5D84:0100 mov DL,07 { } 5D84:0102 mov AH,02 { type assembly language instructions } 5D84:0104 int 21 { } 5D84:0106 int 20 { } 5D84:0108 [Enter] { just press the Enter key in response to prompt } -r cx { to ascertain the value in register CX } CX 0000 { CX contains zero at present } :08 { enter size of routine as 8 bytes } -n bell.com { name the file as bell.com } -w { write the file to disk } Writing 0008 bytes -g { g(o) runs the program and sounds the bell } Program terminated normally It is now possible to unassemble the program to see the machine code -u 5D84:0100 B207 MOV DL,07 5D84:0102 B402 MOV AH,02 5D84:0104 CD21 INT 21 5D84:0106 CD20 INT 20 5D84:0108 0000 ADD [BX+SI],AL It can be seen that the op code for move immediate (07) to register DL is B2 and that move immediate (02) to the register AH is B4. The code for calling an interrupt is CD, followed by the interrupt number. An assembly language statement may translate into one or more bytes. Some examples are: 90 NOP 89E5 MOV BP,SP BF5601 MOV DI,0156 F72E3E00 IMUL WORD PTR [003E] C7063E000300 MOV WORD PTR [003E],0003 Note that the offset address values and immediate values appear with the low byte first and then the high byte. The last statement involves 6 bytes, which is the maximum size. The bell-ring routine can now be inserted into a Turbo Pascal program to indicate a possible error, limit or reminder, as in the following example: program inline_example; {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} { This program illustrates the use of Inline Machine Code. } { } { The inline code causes the bell to sound to draw attention } { } { to the need for further user input, after a table of results. } { } { R. Shaw. 23.3.90 } {___________________________________________________________________} uses Crt; var i,x,y : integer; reply : char; begin repeat ClrScr; Writeln('PROGRAM TO MULTIPLY INTEGER NUMBERS BY 1 TO 10'); WRITELN; write('Enter an integer number '); readln(x); writeln; writeln; for i := 1 to 10 do begin y := i * x; writeln(i:2,' * ',x:2,' = ',y:2) end; inline($B2/$07/$B4/$02/$CD/$21); writeln; writeln; write('Do you wish to continue (y/n)? '); readln(reply); until UpCase(reply) <> 'Y'; end. When using machine code it is possible to use variable names, provided that they have been predeclared, since the variable is really just an offset value to the data in the data segment. The variable declaration in Turbo Pascal is the normal 'var' declaration. An example is given on page 205 of the Turbo Pascal reference Guide: inline(10/$2345/Count+1/Data-Offset); As shown it is possible to use offset specifiers consisting of the + or - sign followed by a constant. It is also possible to use optional size specifiers, < or >. If an inline element starts with a < operator, only the least-significant byte of the value is coded, even if it is a 16-bit value. With >, a word is always encoded, even though the most-significant byte is 0. In assembly language the declaration is achieved by means of the EQU (equate) pseudo-instruction, as illustrated on page 201 of the Reference Guide. Constant values can also be declared in this way. INLINE.TXT 23.3.90