Project Document
last modified:
Overview
Computer operating systems provide management and access services for the
hardware resources of the system. These services are often accessible at
the programmer level as callable functions or at the user level through
some interface such as a command line in DOS and Unix or a GUI as in Mac
or Windows.. In DOS one types dir and the command.com program
reads the command and executes the directory listing program or
function. In Windows one clicks the Windows Explorer icon to perform much
the same operation.
The project is to implement a server that gives users access to operating
system functions and programs over the Internet through a standard browser.
Much of the functionality of a Web server will be implemented, including
the ability to execute CGI (Common Gateway Interface) programs. Commands
or programs can be entered from a browser, sent to the server, executed,
and the program output displayed back to the browser. From a browser, it
will be possible to control a remote computer's operation over an Internet
connection. The remote computer or server will execute C++,
Assembly programs and many DOS commands from a browser, providing access
and control of the server computer from across the Internet. In general,
the operation of the server is somewhat similar to the TicTacToe server
of a previous homework assignment.
A minimal server has already been implemented in a combination of C++
and Assembler as a starting point. The main project tasks are to:
- translate
several of the existing C++ functions into Assembler,
- extend the server
to perform additional functions, and
- implement some useful CGI operations
as Assembler programs.
The following diagram illustrates how the browser would get a directory
listing of the server computer. The user typed dir into the
browser, which sends the request to the server, which executes the DOS
dir
command. The dir command prints the directory listing to standard
output, which is sent back to the server, and finally back to the browser,
where it is displayed.
The following three figures depict:
-
User input of dir *.cpp to display the directory of only the C++
files.
-
The directory results displayed by the browser.
-
The server trace window showing the input to the server from the browser
and the output from the dir execution that was sent o the browser.
| User input of dir *.cpp to display the directory of only the
C++ files.

|
| The directory results displayed by the browser.

|
The server trace window showing the input to the server from the browser
and the output from the dir execution that was sent o the browser.

|
What the Server Can Do
The server lets one control the computer on which the server runs from a browser. It provides very
basic access to the computer on which it is running by executing the commands
typed into the browser. The server recognizes a limited number of commands
that are implemented internal to the server program as regular C++
or Assembler functions. Any command not recognized internally is
passed on to DOS which attempts to execute the command as a program contained
in the server directory or as a DOS command. Essentially any well behaved
program
that can be executed from the DOS command line can also be executed by
the server, that includes 16-bit and 32-bit programs.
The definition of a well behaved program is one that uses standard
input and standard output. This was discussed in Chapter 9 notes
in more detail. The basic idea is that a program that reads standard input
and writes standard output can read the keyboard or a file, write
the screen or a file, without any changes to the program. This is performed
by the operating system through redirection. For example, the following
C++ program reads until a ' ' or blank is entered, converting characters
'A'-'Z' to lowercase and outputting (note that other characters might be
mangled).
Suppose the name of the program executable is DOSlow.exe. Once
compiled, the program can be executed several ways.
-
DOSlow - The input is from the keyboard and output to the screen.
-
DOSlow < A2Z - The input is from the file A2Z and output
to the screen.
-
DOSlow > z2a - The input is from the keyboard and output to the
file z2a.
-
DOSlow < A2Z > z2a - The input is from the file A2Z and
output to the file z2a. Assuming that the A2Z file contained
the one line:
ABCDE Z 12345
the program would output to the file z2a the characters through
the first ' ' converted to lowercase as:
abcde
-
DOSlow ABCDE Z 12345 - From the browser as in the second figure
below. The third figure is the resulting output, stopping at the first
' '.
Convert to Lowercase on Standard Input and Output
C++ and Assembler
#include <iostream.h>
void main(void) {
char c;
do {
cin >> c;
c = c | 0x20;
cout << c;
} while (c != ' ');
}
|
.model small
.code
Main Proc near
@@do:
Mov Ah, 8 ; cin >> Al
Int 21H
Push Ax
Or Al, 20h
Mov Dl, Al
Mov Ah, 2 ; cout << Dl
Int 21H
Pop Ax
@@while:Cmp Al, ' '
Jne @@do
Mov Ah, 4ch
Int 21H
Main Endp
End Main
|
Input to Remote Server |
 |
| Remote Server results

|
How the Server Works
The server and browser interact as follows for implementing the Help
command:
- The user types in a command to the browser, such as Help, and
presses the Enter key to send the string Help to the server. The
browser can be on any computer on the Internet using the server name such as
www.ius.edu. If the browser and server are on the same machine, the
server is known as localhost.
- The server receives the string and determines whether it can execute the
command Help. Help is one of the internal commands
implemented by the server, which executes the command by returning HTML text
for the help.
- The browser receives the HTML text and renders it following the HTML
instructions.
Browser sends user input "Help" to server. Server recognizes
"Help" as an internal server command.
Server responds by sending HTML text for the "Help" command.
The server, as illustrated above, gets its input from the browser. This
input is just the string that the person using the browser typed in before
hitting the Enter key. The server examines this input to determine whether
either an
internal command, one that the server can handle itself,
or an
external command, one that the server doesn't have a clue
about and passes on. The server examines the input from the browser
and determines whether the first word the user typed was a server command.
Basically, the command tells the server what internal server function the
user wants executed. If the first word is an internal server command, the
server just executes the appropriate C++ or Assembler function. In the
above figure the input is a server command
help which is handled
internally by the server executing the HELP function and sending back a
string of help stuff.
If the server doesn't recognize that first word as a command, the server
lets DOS have a go at executing that word as the name of a DOS program.
In the below diagrams, the dir command is unrecognized by the server
so is passed on to DOS which returns a string containing the server directory
listing. For the dir command:
- The user types in a command to the browser, such as dir, and
presses the Enter key to send the string dir to the server.
- The server receives the string and determines whether it can execute the
command dir. dir is not one of the internal commands
implemented by the server, so is passed on to DOS as an external
command.
- DOS executes the dir command, the results are wrapped in HTML and
returned to the browser.
- The browser receives the HTML text and renders it following the HTML
instructions.
Browser sends user input "dir" to server. Server fails to
recognize "dir" as an internal server command and passes "dir" text to
DOS.
DOS executes "dir" returning generated text back to server. Server
returns text from DOS to browser.

The C++ server function EXECUTEcmd that distinguishes between internal
server and external DOS commands is given below. It receives two
strings, command is the command such as dir, DOSlow, echo, etc.
and input is the input to the command or program.
For example, if help were entered in the browser, command="help"
and
input=""
that
is the empty string. The function attempts to match command with
all the internal commands ("HELP", "STOP", and "VERSION") so would call
the function HELP and return the output of the HELP function. If echo
hello is entered at the browser then command="echo" and input="hello"
and a call of ECHO("hello") is executed.
If DOSlow ABCD 1234 were entered in the browser, command
= "DOSlow" and input="ABCD 1234". None of the internal
commands ("HELP", "STOP", and "VERSION") would match with DOSlow so the command and input would be passed to the DOS function and the execution
output returned.
If dir *.exe is entered at the browser,
since it matches neither HELP, STOP, VERSION, or ECHO a call
of DOS("dir", "*.exe") is executed.
EXECUTEcmd - Handle Server and DOS commands
extern "C" char * EXECUTEcmd(char command[], char input[]) {
if (STRcmp("HELP", STRupcase(command)) == 0)
return HELP();
if (STRcmp("STOP", STRupcase(command)) == 0)
return STOP();
if (STRcmp("VERSION", STRupcase(command)) == 0)
return VERSION();
if (STRcmp("ECHO", STRupcase(command)) == 0)
return ECHO(input);
return DOS(command, input);
}
|
How to do the Project
The project can be done in a combination of three approaches:
- Extending the server by adding new of
modifying existing capabilities.
- Converting
existing C++ functions to Assembler.
- Adding DOS commands, essentially
writing a standalone 16 or 32-bit program that can be executed at the DOS
prompt.
Extending the Server
The server can be extended by adding new internal commands similar to "HELP",
"STOP", and "VERSION". The extensions can be original or expanding upon
existing commands, for example the REGDUMP command which is already functional
but only partially completed. The REGDUMP command
displays
the CPU eAx, eBx and eCx register values in hexadecimal, it can be extended
to display additional registers, the stack, memory, etc. The REGDUMP command
display is at right.
It is important to note that ALL commands must return a pointer to
a string. The characters of the string are passed back by the server
to the browser for display. In the How
the Server Works section, the dir command returns a copy of
a string from DOS, which the server returns back to the browser.
The method of extending the server is:
-
Add the command to be recognized and the function call to the EXECUTEcmd
function. To add the VERSION command enter the two lines of:
if (STRcmp("VERSION",
STRupcase(command)) == 0)
return VERSION();
which matches command enter from the browser with "VERSION"
then calls the VERSION() function.
-
Add the prototype of the function called when the command is entered, for
the VERSION function:
extern "C" char *VERSION(void);
-
Write a C++ pseudocode then the assembler version in one file of the same
name as the function. It is not required that function and file be the
same but reduces confusion.
-
Use the same approach from Homework 8. There are several sample Assembler
functions given that can be used as models, including the VERSION.asm
file.
-
Assemble the function using (for VERSION.Asm):
ml /c /coff /Zi /Cp version.asm
-
Add the object and assembler files to the project.
-
Build the project.
-
Execute the server.
Converting
Existing C++ Functions to Assembler
The project is designed to be completed in several steps:
-
Start simple - The base project is written in C++ and some Assembler examples.
Get this to work first by assembling REGDUMP.asm by:
ml /c /coff
/Zi /Cp REGDUMP.asm
-
Rebuild the Project.exe
-
Execute to verify that the server works.
-
In a browser, enter the address localhost.
-
Enter a command such as dir.
-
Remove one C++ function at a time and replace it with the corresponding
Assembler function.
-
Delete everything from the first { to the last } of the function. For STRlen
the changes would be:
-
extern "C" int STRLEN(char s[]) { int eCx=0; while (*s++ != '\0') eCx++;
return eCx; }
-
extern "C" int STRLEN(char s[]);
-
Write the Assembler function, for example:
-
STRlen proc Near C, s:near ptr byte
-
Add Assembler object file to project.
-
Assemble using ml /c /coff /Zi /Cp filename.asm
-
Rebuild Project.exe and execute.
-
In a browser, enter the address localhost.
-
Enter a command such as dir.
-
Test project Assembler functions using same inputs as in Step 1. The results
should be the same.
Testing - Note that nearly all the functions in the student.cpp
file are used whenever a command is received from a browser so it is often
difficult to determine problem sources. Suggestions:
-
Implement only one function at a time.
-
Test function in a trivial case outside the server when possible.
-
Create a C++ test program.
-
Copy any C++ functions from the server that the new function calls. Check
the Server.cpp and Student.cpp for called function source.
-
Write a main function to call the new function from C++.
-
Translate the C++ function into Assembler and link as was done in Homework
8.
-
Perform unit level tests in the trivial case.
-
Link into the server and verify that the function works for the system
level test .
Test STRhex function in C++
#include <iostream.h>
#include <stdlib.h>
// STRnew - Returns a pointer to memory allocated of specified length
extern "C" char * STRnew(int length) {
return (new char[length]);
}
// STRcpy - Copy s1 to s2, assumes that size of s2 is equal or larger than s1.
extern "C" void STRcpy(const char s1[], char s2[]) {
int i1=0, i2=0;
while( s1[i1] != '\0')
s2[i2++] = s1[i1++];
s2[i2] = '\0';
}
// STRhex - Convert int to hexadecimal string, return a pointer to string.
// 25 points
extern "C" char * STRhex(unsigned int n) {
char hex[]="00000000", *retstr=STRnew(10);
int i=7, hexdigit;
while(n != 0 && i >= 0) {
hexdigit = n % 16;
n = n / 16;
if (hexdigit <= 9)
hex[i] = hexdigit + '0';
else
hex[i] = hexdigit + 'A' - 10;
i--;
}
STRcpy(hex, retstr);
return retstr;
}
void main(void) {
cout << "STRhex( 12 ) = " << STRhex( 12 ) << "\n";
}
|
| STRhex( 12 ) = 0000000C |
Adding DOS Commands
Writing a program that runs under DOS but is executed by the server offers
the greatest opportunity for accessing hardware and using DOS
functions. The DOS commands can be any executable program that uses standard
input and standard output. Otherwise, the programs can be very
similar to those implemented earlier in this course, except of course that
GetDec, PutDec, etc. cannot be used for input and output. Normally, a 16-bit program
would be written entirely in Assembler to use DOS or BIOS interrupts. If
implementing as a 32-bit program, the io.obj functions (PutDec, GetDec,
PutStrng, and PutChar) can be used for input/output, a mixed C++ and Assembler
program, or C library functions (see notes on Windows
programming, the C Functions example) can be invoked but DOS and BIOS cannot be used.16-bit
- An example 16-bit DOS program is DOSecho.asm which echoes all input
until a ASCII 13 (carriage return) is input. The program runs
under DOS and is given below. The suggested steps to implementing a DOS command
are:
-
Write a C++ or other pseudocode algorithm then convert to pure Assembler.
The DOSecho is a trivial example of a DOS program. Other examples in
the project directory are:
-
DOSdir - Print a simple DOS-style directory of selected files.
-
DOSsq - Inputs an unsigned integer and outputs the square of the number.
-
DOSlow - Converts uppercase input to lowercase until a ' ' is input.
-
DOShex - Inputs one character and outputs as hexadecimal.
-
Assemble, for example, DOSdir.asm:
- v:\common\user\c335\assembler
- ml DOSdir.asm DOSio.obj
-
Test that the program works at the DOS command line and can redirect all
input and output. For example, test DOSdir to list all ASM files to standard
output:
-
Copy the executable to the same directory as the server. If the server
directory (not the Debug directory) was C:\C335\Project then to copy the DOSlow.exe
program
there:
copy
DOSlow.exe C:\C335\Project
-
In the browser, enter the name of the program and one line of program input on the same
line. There is no opportunity for interaction with the program since all
input must sent to the DOS program when executed from the browser.
32-bit - One example is Homework 7, a 32-bit program that reads one line of
input using GetDec from the io.obj file. Any 32-bit program can
use GetDec, PutDec, PutStrng, and PutChar as used fin homeworks. Note that 32-bit
programs cannot invoke DOS or BIOS interrupts.
C library functions can also be used directly by defining the prototype to
invoke the function and linking in the C librabry. The DOSecho32.asm below echoes
all input until an ASCII 10 (new line) is input. For a more realistic example, see notes on Windows
programming, the C Functions example. The steps necessary to use C library
functions in DOSecho32.asm are:
- Copy the MSVCRT.LIB to the same directory as DOSecho32.asm:
- Visual Studio 6.0 - C:\Program Files\Microsoft Visual Studio\VC98\Lib\MSVCRT.LIB
- Visual Studio .NET - C:\Program Files\Microsoft Visual Studio
.NET\VC7\Lib\MSVCRT.LIB
- v:\common\user\c335\assembler32
- ml /coff /Zi DOSecho32.asm /link MSVCRT.LIB /subsystem:console
- DOSecho32
Title DOSecho.asm 16-bit
; Echo standard input
; until ASCII 13
.286
.model small
.code
Main Proc near
@@do:
Mov Ah, 8
Int 21h
Mov Ah, 2
Mov Dl, Al
Int 21h
@@while:
Cmp Al, 13
Jne @@do
Mov Ah, 4ch
Int 21h
Main Endp
End Main
|
// Echo standard input
// until ASCII 10 input
int getchar(void);
int putchar(int c);
void main(void) {
while(Al=getchar()!='\n')
putchar(Al);
}
|
Title DOSecho32.asm 32-bit
; Echo standard input until ASCII 10
.386
.model flat, stdcall
option casemap:none
.nolist
include v:\common\user\c335\masm32\include\windows.inc
include v:\common\user\c335\masm32\include\kernel32.inc
include v:\common\user\c335\masm32\include\masm32.inc
includelib v:\common\user\c335\masm32\lib\kernel32.lib
includelib v:\common\user\c335\masm32\lib\masm32.lib
.list
getchar proto near C
putchar proto near C, char : dword
.code
main proc near
@@while:
invoke getchar
cmp Al, 10
jne @@do
jmp @@endwhile
@@do:
invoke putchar, eAx
jmp @@while
@@endwhile:
invoke ExitProcess, 0
main endp
end main
|
Note that the output will be displayed in the browser just as it appears
when executed at the DOS prompt. HTML tags can be added to the text to
improve the appearance when displayed by the browser. For example, server
output will be displayed as bold faced by the browser if the text is surrounded
by <b> and </b>. For example, <b>bold stuff</b> will
appear as bold stuff.
Suggested Command Extensions
Other possible extensions are below, you are welcome to devise other, long
dreamed of commands. These may be implemented either internally by adding
to the server or externally as standalone DOS programs. Before implementing
any extension, please get the instructors approval, advice, and point value directly
or via email to verify the appropriateness and viability of the extension.
-
DEL - Delete a file or files.
-
SWAP - Swap contents of two files.
-
TAIL - Display a file from tail to head.
-
GREP - Scan a file for occurrences of a string and display lines on which
they are found.
-
TYPE - Display a file from head to tail.
-
COPY - Copy file to another.
-
APPEND - Append a file to another.
-
PRINT - Print a file.
-
DATE - Print system date.
-
TIME - Print system time.
-
DIR - File size, date, etc. to directory command.
-
RESOURCES - Display available memory/disk used/available.
-
REGDUMP - Extend the REGDUMP function for remaining registers including
eBp and eSp before the call to REGDUMP.
-
Special Characters - The browsers send certain special characters as the
hexadecimal code (e.g. ':' sent as %3A, ',' sent as %2C, '\' as %5C, etc.).
These are not translated currently and cannot be used in commands. Converting
%3A back to ':' would make a nice addition to the project.
-
GETDEC$, PUTDEC$, GETSTRNG, PUTSTRNG, ... - The text's input and output
functions used BIOS interrupts. These can be rewritten to use standard
input and standard output using DOS interrupts.
Software Download
There are several files required for the minimal server, the following
will create a project directory and copy necessary files by the
steps of:
-
Download the self expanding file project.exe
to your computer.
-
From DOS, change directory to where project.exe was saved and enter
project. Or from
Windows Explorer, click on the icon
.
Windows 95, 98, and ME users should extract files to a directory named Project.
Compiling, Linking and Execution
A Visual C++ project file is located in the project directory. The steps
to executing the minimal server are:
-
Assembler - Only necessary if you have changed any Assembly files.
-
Assemble asm files in the C:\C335\Project directory by:
-
cd C:\C335\Project
Change
to the project directory.
-
v:\common\user\c335\assembler32 At IUS for the network mappings.
-
ml /c /coff /Cp /Zi REGDUMP.asm
Assemble ASM files.
-
Visual C++
-
File | Open Workspace |

-
Rebuild All | Execute Project.exe
-
Browser, see the Overview section above for the visuals.
Testing
The obvious method of testing the server is to make changes and run the
server. However, if it fails, the difficulty is determining what conditions
existed at the point of failure. One method of testing functions translated
from C++ to Assembler is to first test using a small program that exercises
the function. For example, suppose that you had written STRcat and
wanted to test. A reasonable test would be the C++ program below which
allocates enough storage for the s string to have 3 characters "abc" concatenated
at the end of "123".
#include <iostream.h>
extern "C" void STRcat(const char t[], char s[]);
void main(void) {
char *t="abc",
s[10]={'1', '2', '3', '\0'}; // "123" with 6 bytes of storage for "abc"
cout << STRcat(t, s); // Output "123abc"
}
Another test function is for CHARrep:
#include <iostream.h>
extern "C" void CHARrep(char s[], char c1, char c2);
void main(void) {
s[10]={'a', 'b', 'a', 'b', 'a', '\0'};
cout << CHARrep(s, 'a', 'x'); // Replace 'a' with 'x'
}
The parameters would be pushed onto the stack, 4 bytes for each parameter.
The parameters can be accessed using either of the following:
s Equ dword ptr [eBp+8]
c1 Equ byte ptr [eBp+12]
c2 Equ byte ptr [eBp+16]
|
CHARrep proto near C, s:near ptr dword, c1:byte, c2:byte
|
When Your Server Crashes
Possible causes of a server crash or hang
-
Another server already running on Port 80 - Only one server can
use port 80, if already in use the remote server shuts down. There are several
possible solutions:
- Shut down the other server and rerun remote server. On XP and later
Windows 2000:
- Start | Control Panel | Administrative Tools | Internet Information
Services | Expand the Web Server Icon | Action | Stop
- Change the port in server.cpp program:
- Locate port=80 and change to port=880. Rebuild and start
server.
- In browser, enter the address: http://localhost:880
-
Memory faults - Remember that the server returns a string which is output
to the browser. Once the server is finished with the string returned, the
string memory is deleted by the server to conserve memory. If the memory
that the string pointer referenced was not allocated by STRnew there
will be some sort of a memory fault probably due to:
-
not allocating enough memory using the STRnew function, be sure
to count the '\0' byte of a string when allocating,
-
returning a pointer to locally allocated memory (e.g. static memory allocated
within the .DATA of a function or dynamically on the stack, neither should
have pointers returned for deallocation),
-
returning a pointer that hasn't been initialized to anything. Remember
that eAx should hold the pointer to the string's memory that was allocated
by STRnew.
-
Browser never gets output back - Probably because the server has started
a DOS program that doesn't stop running. The server hasn't really crashed
but the DOS program hasn't finished its work so the server can't return
the results of the DOS program. Stop the server in the DOS console window
with a Ctrl C.
Recovery from crash
-
Debugger - If running the program in the debugger, a crash is generally
not as serious (i.e. the system doesn't have to be rebooted). One simple
and useful debugging technique is to open the C++ or Assembly file that
you are working on, place the cursor on an interesting line within the
code, and enter Ctrl F10. The debugger will run to that point (assuming
it will eventually reach that line) and stop to await more debugger commands.
-
Console window - Open the Console window (black screen), if it says
Press
any key to terminate the crash was minor. Press any key with the console
window open and the debugger should point to where the crash occurred.
Suspect memory faults as described above.
-
Browser gets no response from server - Either the server isn't executing
which is easily corrected by pressing F5 to execute or the server never
returns anything back to the browser (again most likely due to a DOS program
that doesn't finish). In either case the prognosis is not generally fatal.
-
Windows 2000 - Simplest is to close the server's Console window.
-
Windows 95/98 - The DOS application can be killed from the Windows
Task Manager which is opened by entering:
Ctrl Alt Del
which should open a window where Winoldap is listed. Select
and click End Task to kill the program.

-
System locked - Usually occurs when the server Console window is
closed before the server terminates. If you can, stop the server with Ctrl
C in the server Console window. If not, there is usually not a good prognosis
and you'll have to restart Windows 95/98 to clear the TCP/IP ports bindings.
Windows 2000 is much more resilient.
Prevention
-
Test input - Verify that the input to the server from the
browser is being received and returned to the browser correctly after making
modifications.
-
Echo - Use the ECHO command to send back to the browser the input.
ECHO a b c d e g would send back a b c d e g.
-
Server Console - Check the server console window. It displays what
is received from and sent to the browser.
-
DOS programs
-
Verify that the program at least works with the input that should
be entered to the browser.
-
Verify that the program will stop if incorrect input is entered. Some reasonable
safe guards are to check for valid input in the program and exit if no
input or invalid input exists.
File List
There are several files supplied with the project. By default, these are
placed in the project directory when Project.exe is executed to
copy the project files. There are also several example C++ callable functions
and DOS programs included. These files and functions are:
-
student.cpp - The file that you will need to modify when adding
new server commands or replacing existing C++ functions with Assembler
functions.
-
REGDUMP.asm - Assembly file for the server's REGDUMP command.
Intended as an example of a C++ callable Assembler function. Assemble and
add to project, assemble as a 32-bit function by:
v:\common\user\c335\assembler32
ml /c /Cp /Zi /coff REGDUMP.asm
-
VERSION.asm - Assembly file for the server's VERSION command. Intended
as an example of a C++ callable Assembler function that outputs an HTML
formatted string. Assemble as a 32-bit function and add to project, assemble by:
v:\common\user\c335\assembler32
ml /c /Cp /Zi /coff VERSION.asm
-
DOSsq.asm - DOS Assembly program intended as an example of a regular
DOS program that reads a number from standard input and writes a number
to standard output. Can be assembled as a 16-bit function and linked to the DOSio functions
by:
v:\common\user\c335\assembler
ml /c DOSio.asm
ml DOSsq.asm DOSio.obj
Run on the server by:
DOSsq 5
-
DOSdir.asm - DOS Assembly program that reads a parameter
string for the directory and displays the file names in the directory.
Intended as an example of reading and writing strings using standard input
and output. Can be assembled and as a 16-bit function linked to the DOSio functions by:
v:\common\user\c335\assembler
ml /c DOSio.asm
ml DOSdir.asm DOSio.obj
Run on the server by:
v:\common\user\c335\assembler
DOSdir *.cpp
-
DOSio.asm - DOS Assembler functions for string and unsigned 16 bit
integer standard input and output. Assemble as a 16-bit function by:
v:\common\user\c335\assembler
ml /c DOSio.asm
Contains INTget, INTput, STRget, and STRput functions.
See sample programs DOSdir.asm, DOSsq.asm and DOSio.asm for use.
-
DOSlow.asm - DOS Assembly program that reads a string of characters
from standard input, converts all characters up to a blank to lowercase,
and outputs the character to standard output. Intended as an example of
reading and writing characters using standard input and output. Assembler as a
16-bit function
and link by:
v:\common\user\c335\assembler
ml DOSlow.asm
Run on the server by:
DOSlow ABc3E XYz
Output is:
abc3e
-
server.cpp - The main server file. Normally you won't need to make
any changes unless you want to print out some intermediate results.
-
network.cpp - The part of the server that handles the network
connections to the browser. Normally you won't need to make any changes
unless you want to print out some intermediate results.
-
pipe.cpp - The part of the server that runs DOS programs by
piping the program browser input and returning the program's output to
the browser. Normally you won't need to make any changes unless you want
to print out some intermediate results.
Notes and Warnings (FAQs)
Strings - All strings are terminated by a '\0'. Strings are always
passed by reference to functions so a function will receive a pointer
to the string. As an example, if the leftmost parameter to the function
is a string, to move the first character of the string into the Al register:
Mov eSi, [eBp+8]
Mov Al, [eSi]
Function Results - Almost all functions return type is char *
meaning that they return a pointer to memory that contains a string. Pointers
are 32 bit and should be returned in the eAx register. Generally,
any function that creates a string should dynamically allocate the memory
storage used to hold the string by calling the STRnew function.
See below.
Memory Allocation and STRnew - The server inputs strings of characters
from the browser and returns string of characters back to the browser.
The memory used to hold strings is assumed to be dynamically allocated
using the new function. The server dynamically deallocates all strings
when no longer needed. If the server attempts to deallocate memory that
doesn't exist (has not been allocated) some form of a memory allocation
error will occur.
For example, suppose that the VERSION function returned a string
defined as a local variable versionstr. When the function exits
it returns a pointer to the string memory but the storage has already been
deallocated by the function return.
extern "C" char * VERSION(void) {
char *versionstr = "<h2>Remote Server Version
2000</h2>";
// Allocate on
entry, deallocate on exit
return versionstr;
}
STRnew is a C++ function that allocates memory for type char
*. The STRnew returns a char * pointer to memory allocated
for strings. For example, to allocate 100 characters and point to it:
char *retstr = STRnew(100);
The VERSION function should allocate enough non-local memory to
the string that is be returned (retstr) and copy the characters into the
memory allocated. When the VERSION function returns the allocated
memory pointed to by retstr still exists until deallocated by the
server when finished with the string.
extern "C" char * VERSION(void) {
static char *versionstr = "<h2>Remote Server
Version 2000</h2>";
// Local string allocated on entry/deallocated
on exit
char *retstr = STRnew(STRlen(versionstr)+1);
// Allocate non-local memory
STRcpy(versionstr, retstr);
// Copy local string to memory pointed to by retstr
return retstr; // Return pointer to string
}
See also the assembler listing for Version.asm file that corresponds
to the above Version function.
Registers - Remember that C++ does NOT save all registers
used in functions. Only the segment registers (CS, DS, Es, and SS), eSi, eDi,
eBP,
and eSP are protected. Calling a C++ function may destroy the contents
of any other registers.
It is your responsibility to save any registers before pushing function
parameters and restore after the function call. In the following example,
the eCX register is saved and restored.
Mov eCx, 10
Do:
Push eCx ; Save eCx before parameters pushed
Push Offset String
Call puts
Add eSp, 4
Pop eCx ; Restore eCx
While: Loop Do
Stack - All functions used within a C++ program must use extern
"C" parameter passing methods used throughout this course. With "C"
parameter passing, the parameters are removed from the stack by the calling
function, for example, ADD eSp, 4 removes 4 bytes of parameters.
In the above example, after calling the puts function, remove 4
bytes of parameters. Remember that Visual C++ pushes 32 bit parameters
in right-to-left order.
32 bit registers and parameters - Also remember that Visual C++
has 32 bit parameters and flat addressing. For functions that are called
or call Visual C++ functions, always use the C++ conventions discussed
earlier in the course (see Chapter 7 and Homework 8).
Pointer versus Character Value parameters - Some of the functions
use 32 bit pointers to strings (reference parameters) and some, such as CHARrep, also use character values. Since pointers are 32 bits, each one
obviously occupies 4 bytes on the stack. However, characters are bytes
so how many bytes should they occupy on the stack? With VC++, all parameters
on the stack seem to be 4 bytes but which of the 4 bytes holds the character
parameter? The following is the definition of the stack parameters for CHARrep, where s is a pointer, c1 and c2 are character values, perhaps
c1 == 'A' and c2 == 'B'. Note that c1 and c2 are defined as byte. Character
parameters are pushed on the stack by Visual C++ using 4 bytes with the
character in the lowest byte.
; extern "C" void CHARrep( char s[], char c1, char c2);
Stack Offset
s Equ dword ptr [eBp+8]
8-11 12 34 56 78 Pointer
s
c1 Equ byte ptr [eBp+12]
12-15 41 00 00 00 Character
c1='A'
c2 Equ byte ptr [eBp+16]
16-19 42 00 00 00 Character
c2='B'
Interrupts - The text provides an overview of interrupts.
More complete information on interrupts is at:
DOS Interrupts - DOS interrupts CANNOT generally be executed
through a Visual C++ 6.0 function call but the server can execute DOS programs
that use interrupts. If function f contains a DOS Int 21h and is
called directly from C++ program then most likely the Windows operating
system will crash. Note that it is possible, Homework 8 is an example,
to call assembler functions from C++, the assembler function just cannot
use BIOS or DOS function (i.e. the Int 21h). Standalone Assembler programs
written for DOS, as have been most of the programs in the course, can use
BIOS or DOS interrupts. The difference is that calling a function
from C++ executes in 32 bit but the BIOS and DOS functions are 16 bit.
Bios Interrupts - For DOS programs only. Keyboard and video interrupts
CANNOT generally be used because input and output must be through standard
input and output. Other BIOS interrupts should be useable under
Windows 95/98, such as INT 12h to get the system memory size.
Input and Output - Assembler programs can perform standard input
and output using DOS Int 21h, function 1, 2, 7, 8 and 9 (see text, page
464 or Ralf Brown's INTerrupt list). Assembler functions that are part
of a C++ program can call a C++ function that has been written to perform
input and output. The GetDec, PutDec, etc. functions DO NOT support
redirection. The provided DOSio.asm contains unsigned integer and
string input and output functions that can be used by DOS programs.
Server Files - The server can only access files that are in the
project directory. Any executable programs must be copied to the project
directory (C:\C335\Project) for the server to execute. To execute DOS commands,
command.com
may need to be copied into the project directory. If DOS commands (e.g.
dir, ver, ...) fail, copy command.com to the project directory at
the DOS prompt by:
copy c:\command.com c:\C335\Project
Special characters - The browsers send certain many of the special
characters as the hexadecimal code (e.g. ':' sent as %3A, ',' sent as %2C,
'\' as %5C, etc.). These are not translated currently so cannot be used
in commands. Converting %3A back to ':' would make a nice addition to the
project.
Linking Errors - The most common problem is functions that exist
more than once. One way this can occur is if you add the student.cpp
to the project. Since the server.cpp file already includes the student.cpp
file by:
#include "student.cpp"
adding student.cpp to the project would make two occurrences. Solution
is to remove student.cpp from the workspace, don't delete the file
itself but take it out of the workspace so only one copy of student.cpp
is
compiled.
Building and Compiling - The one file that you'll be editing
is student.cpp which needs to be saved each time changes
are made. To compile the full server use Rebuild All to ensure that
all changed files are recompiled.
Grading
-
Based on a 100 point project for an individual.
-
Implement no more than 50 points by translating existing C++ routines into Assembler. You are free to choose from those
with point values listed in student.cpp
file.
-
Remaining 50 or more points should come from server extensions of your own design. Some
possible extensions are listed above. To ensure proper credit, the instructor must be informed and
points negotiated for extensions.
-
An individual could complete the project by implementing STRcat, STRcmp and
extending RegDump to dump other registers (e.g. eDi, eSi, eBp, eSp, flags, Cs,
Ds, etc.) and DOSdir to display file time/date/size and total number of
files and size.
Teams
Teams consist of no more than two individuals who will receive that same
score for the project. A team of two are expected to complete twice that of an
individual. In the case that only one of the team members contribute
significantly, each team member's grade will be adjusted accordingly.
Turn In
All files used for the project should be emailed to the instructor along
with instructions for executing each part of the project you completed.
Cover page and instructions can be composed using MS Word.
Cover page - Team member names, date, and Project.
For each function or program:
Source listing (what you typed).
Typed specification of its purpose.
Execution results of each function or program as a screen shot of browser
input and output after execution.
Instructions of the testing procedure to verify its correct operation according
to its specification. This may require an explanation of the conditions
under which the function was executed to produce the output given.
email
-
Directory - Create a directory named PROJECT that contains
all project files and instructions.
-
Zip - Use WINZIP to zip all files and subdirectories of the
PROJECT directory.
-
email - email the zipped project to yourself as a test.
-
Test - Unzip the emailed project zip file to a new directory and
make certain that it still works.
-
email - email the zipped project to
rwisman@ius.edu
Document last modified: