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