Tips and Tricks for DOS and DOS Apps.
See below for compiler/assembler and DOS Programming tips
See below for Misc DOS Programming tips

DIR: You can use the /p parameter with DIR to make DIR pause between pages. You knew that right? But did you know that if you put the following line in your autoexec.bat file, DIR will pause between pages without you having to use the /p parameter?
SET DIRCMD=/p

DIR, TYPE, or any other command line program that prints to the screen: If the display just keeps scrolling and scrolling and you didn't catch it all, use the '|' (above the ENTER key) (ascii 124) and the MORE command:
type somefile.txt|more
This will print one page at a time to the screen, waiting for a keystroke.

DIR, TYPE, or any other command line program that prints to the screen: You can also make the display print to a file using indirection:
dir somedir > afile.txt
(afile.txt now holds the contents of SOMEDIR)

COPY: Since about DOS 5, if you used the copy command to copy a file to a different directory and the file with that same name already existed there, COPY would ask you if you wanted to replace it. Gets on your nerves don't it? Use the following line in your autoexec.bat file to stop COPY from asking you if you want to replace a file:
SET COPYCMD=/y
You can always use /-y as a parameter to override.

LINK and LIB:Tired of telling LINK or LIB where your libs are? Use the following in your autoexec.bat file to tell LINK or LIB once and for all:
SET LINK=C:\COMPLRS\QB45
SET LIB=\COMPLRS\QB45

INCLUDE:Tired of telling your C compiler(s) where your include files are? Use the following in your autoexec.bat file to tell the compiler where to look:
SET INCLUDE=\COMPLRS\LEARN_C\INCLUDE

MODE:Have you ever exited a program and it left the DOS prompt in different colors or sizes or just plane gone? Use MODE CO80. This sets the display to color enabled and 80 lines per page. Also see my page called Misc Programming Files for a small program to fix the display, turn off the sound, and any other setting that might not be right. (NORMAL.COM)
**Note: MODE works different on all machines. Be careful with MODE. MODE also sets the printer output, the PORT(s) status and much more. Don't full around with MODE**

EDIT: To enter a special character in EDIT press the 'ctrl'+'p' combination and EDIT should put a line at the status bar asking for the character. Now you can enter one of the 256 ascii chars (except the NULL (zero) char) with the number keypad.
Example: To enter the PageBreak char (ascii 12) hit 'ctrl'+'p' then hold down the 'alt' key and type '1' then the '2' at the number keypad.




Tips and Tricks for DOS Programming

I know that this is no where near a good list of tip and tricks, but I hope to keep building on them when I have the time

Goto Quick Basic Programming tips
Goto C Programming tips
Goto Pascal Programming tips


Assembly
Here is a space saving tip that I have seen a few times in boot sectors and the such. It is a string printing tip that saves time and space. First the code, then the explaination:
   .
   .
   call prtstring
   db   13,10,'This is a string to print',0
   xor  ax,ax
   mov  bx,10
   .
   .
   .exit

prtstring:
   cld
   pop  si
ploop:
   lodsb
   or   al,al
   jz   short ploop_done
   mov  ah,0Eh
   xor  bx,bx
   int  10h
   jmp  short ploop
ploop_done:
   jmp  si

Notice that the string to print is just after the call instruction and there is no code to jump over the string. Well, there is no need to. Notice in the prtstring function, si is set to the offset after the call, which is the string. While the string is being printed, si is incremented. Once the NULL char is found, si points to the next byte in memory, which in our code is the next instruction.



Here is a fast and easy way to setup a far proc in assembly. (MASM 5.1x)
          public  procname
procname  PROC far basic uses ax bx,parm1:word
           .
           .
           .
           .
           .
           .
          ret
procname  endp

This will allow you to call a far proc easier. (You must use .model medium (or larger))
When you call this procedure from another file, push the value for parm1 on to the stack. When the assembler assembles this proc., it will automatically put whatever was on the stack in to parm1. When it hits the RET, it will automatically set the stack pointer (sp) to what it should be. ie. it will do the same as if you put (RET 2). So on return to the parent, the stack does not need to be 'cleaned'. SP points to where it was before you pushed the parm values.

Note that BASIC is used after the far dir. This tells the assembler to get the parms of the stack in basic order. If you used pascal, it would get the parms in pascal order. etc...



Shift right 1 pos is the same as dividing by 2.
Shift left 1 pos is the same as multiplying by 2.

With a 186 you can put a literal as a shift rather than using CL.
i.e. shr ax,03 is the same as shr ax,cl (where cl = 3)

If you have a few variables to set to the same value (clear to zero), if they are in consecutive order in memory, use the rep stosb instead of changing/clearing each one individually.



Basic
The Quick Basic compiler comes with an OBJ file called: NOCOM.OBJ; If you don't use any communications commands in you program, you can include this file with your program to make the EXE smaller and faster.

Quick Basic allocates all available memory at startup. This doesn't allow you to dynamically allocate any yourself. Use the SETMEM() statement to decrease the amount it has allocated to allow you to use it.

When you read and write to a file, Quick Basic does a lot of error checking:
- For reading; Read in all bytes needed into a buffer, then 'read' each byte from the buffer rather than reading each byte from the file.
- For writing; Write each byte to a buffer, then when the buffer is full or you are finished, write the buffer to the file, rather than writing each file individually.

Boolean expressions are faster and smaller. If you have a lot of IF/THEN/ELSE's that use TRUE/FALSE flags then rather than doing this:
--IF var = 0 THEN
or
--IF var = 1 THEN
set two const at the top of the main module: FALSE = 0, TRUE = NOT FALSE
Now use:
--IF var THEN
or
--IF NOT var THEN
where var was defined either true or false earlier in the program.



C
var += 22; is same as var = var + 22;

var++; is same as var=var+1;

If you want to get the value of var and then increment var:
var1 = var2++; will put the value of var2 in var1 and then inc var2.
var1 = ++var2; will inc the value of var2 and then put that value in var1.

C contains a ternary operator that is most useful:
rather than doing:
-> if (condition) var = exp1; else var = exp2;
try:
-> var = condition ? exp1 :exp2;



Pascal



Misc Tips and Tricks
Getting the command line parameters: Rather than relying on the value at bx:80h for finding the end of the command line, just test to see if the char is the CR (enter key (0Dh)). DOS will always put this char at the end of the line, because at the DOS prompt (except for extreme hacking) there is no other way to execute a command with out hitting the enter key at the end of the command line.

To turn on/off the Insert state set/clear bit 7 of the word at 0000:0417h
To turn on/off the Caps Lock state set/clear bit 6 of the word at 0000:0417h
To turn on/off the Num Lock state set/clear bit 5 of the word at 0000:0417h
To turn on/off the Scroll Lock state set/clear bit 4 of the word at 0000:0417h
If bit 3 is set then any Alt key is pressed, if cleared then none pressed
If bit 2 is set then any Ctrl key is pressed, if cleared then none pressed
If bit 1 is set then left shift key is pressed, if cleared then not pressed
If bit 0 is set then right shift key is pressed, if cleared then not pressed


Bit rep at low memory: 0040:0017h
7 - Insert state 1=active
6 - Caps Lock 1=active
5 - Num Lock 1=active
4 - Scroll Lock 1=active
3 - 1 = alt pressed
2 - 1 = Ctrl pressed
1 - 1 = L shift pressed
0 - 1 = R shift pressed

Bit rep at low memory: 0040:0018h
7 - 1 = Ins Pressed
6 - 1 = Caps Lock pressed
5 - 1 = Num Lock pressed
4 - 1 = Scroll Lock pressed
3 - 1 = pause pressed (Ctrl num lock)
2 - 1 = Sys Req pressed
1 - 1 = L Alt pressed
0 - 1 = L Ctrl pressed