'=========================================================================== ' Subject: ASSEMBLY TO BASIC Date: 04-28-97 (12:15) ' Author: Petter Holmberg Code: QB, QBasic, PDS ' Origin: petter.holmberg@usa.net Packet: ASMCODE.ABC '=========================================================================== ' -------------------------------------------------------------------------- ' ' Absolute Assembly by Petter Holmberg, -97. Ver. 1.1beta: ' ' ' ' I recently started using DEBUG to create Assembler routines for BASIC with ' ' CALL ABSOLUTE. It didn't took me very long to discover that turning ' ' Assembler code into a BASIC string with machine language was a long and ' ' tedious process. Working with the code in a text file instead of directly ' ' from within DEBUG and then then type: ' ' DEBUG < sourcefile > destfile ' ' made it a little easier, but it was still a lot of work. ' ' Before the first run through DEBUG, there's no way of knowing how many ' ' bytes of code to unassemble, and after the second run when the source file ' ' was modified to unassemble the correct number of bytes, there was still a ' ' lot of work moving the machine code to BASIC. If you have tried yourself, ' ' you know what I mean. ' ' So I made a program to do the work for me. Absolute Assembly 1.0. ' ' But soon after I had finished Absolute Assembly 1.0, I needed to do a ' ' routine with a JMP instruction. So I made this new version with support ' ' for line labels and comments. ' ' This program will let you choose a text file with assembler instructions, ' ' a destination file name and a string variable name. The result will be a ' ' set of commented BASIC lines in the destination file which declares a ' ' string with the name you have chosen, ready to be executed. ' ' Ex: ' ' ' ' You have a text file looking like this: ' ' ' ' XOR AX, AX ; Set AX to 0. ' ' MOV CX, 10 ; Prepare for a loop. ' ' TheLoop: INC AX ; Increase AX. ' ' LOOP TheLoop ; Loop 10 times. ' ' RETF ; Return to BASIC. ' ' ' ' Run it through this program and you will get these lines moved into a ' ' selected QBASIC program: ' ' ' ' asm$ = "" ' ' asm$ = asm$ + CHR$(&H31) + CHR$(&HC0) ' XOR AX,AX ' ' asm$ = asm$ + CHR$(&HB9) + CHR$(&H10) + CHR$(&H0) ' MOV CX,0010 ' ' asm$ = asm$ + CHR$(&H40) ' TheLoop: INC AX ' ' asm$ = asm$ + CHR$(&HE2) + CHR$(&HFD) ' LOOP TheLoop ' ' asm$ = asm$ + CHR$(&HCB) ' RETF ' ' ' ' Notes: ' ' þ All lines in the source file must have one Assembler instruction in it. ' ' Don't use blank lines or lines with just comments. ' ' þ Comments must start with a semicolon, (;). ' ' þ The maximum number of labels is 256. You shouldn't need half as much. ' ' þ The maximum number of letters for a label is 16. It's easy to change ' ' the program to accept a larger number, but it's probably not necessary. ' ' þ A label must be immediately followed by a colon, (:). ' ' þ Never use Assembly opcodes or numbers as labels. ' ' þ "Label:" and "label:" are processed as different labels. ' ' þ Do not write lines like: REP MOVSB. When assembling, DEBUG will divide ' ' this into two lines; REPZ and MOVSB. This will mess up everything for ' ' this program. Sorry, I didn't bother to write any code to handle such ' ' occurrences. ' ' þ This program was made in QB45, but you should be able to run it in ' ' QBASIC, PDS, VBDOS and PB as well. ' ' þ I haven't really tested this program for bugs, so please be patient with ' ' me. :) ' ' þ Any comments/suggestions can be sent to: petter.holmberg@usa.net ' ' þ I know, I know, the source code is VERY crappy, but I wrote this in just ' ' an hour or two and it works! Maybe I'll add some more functions later... ' ' ' ' Enjoy the program and have fun! ' ' -------------------------------------------------------------------------- ' CONST rundebug$ = "C:\DOS\DEBUG.EXE" ' Change this if you have DEBUG on ' another location. CONST tempfile1$ = "TEMPFIL1.TXT" ' Change this if this filename already ' are in use. CONST tempfile2$ = "TEMPFIL2.TXT" ' Change this if this filename already ' are in use. CONST tempfile3$ = "TEMPFIL3.TXT" ' Change this if this filename already ' are in use. TYPE labeltype ' Usertype for storing of labels. labelname AS STRING * 16 labelpos AS STRING * 4 labelnum AS INTEGER END TYPE DIM label(1 TO 256) AS labeltype ' Array for storing of labels. numlabels% = 0 ' Label counter. linecounter% = 1 ' Line counter. CLS PRINT "Absolute Assembly by Petter Holmberg, -97. Ver. 1.1beta:" PRINT INPUT "Assembly source text file: ", sourcefilename$ INPUT "QBASIC destination file : ", destfilename$ INPUT "Name of code string : ", codestring$ PRINT conversiontime! = TIMER ' Insert DEBUG instructions and assembly source code into tempfile and take ' care of lables and comments: OPEN tempfile1$ FOR OUTPUT AS #1 OPEN sourcefilename$ FOR INPUT AS #2 DO LINE INPUT #2, sourceline$ IF INSTR(sourceline$, ";") THEN sourceline$ = LEFT$(sourceline$, INSTR(sourceline$, ";") - 1) END IF IF INSTR(sourceline$, ":") THEN numlabels% = numlabels% + 1 label(numlabels%).labelname = LEFT$(sourceline$, INSTR(sourceline$, ":") - 1) sourceline$ = MID$(sourceline$, INSTR(sourceline$, ":") + 1) label(numlabels%).labelnum = linecounter% END IF PRINT #1, sourceline$ linecounter% = linecounter% + 1 LOOP UNTIL EOF(2) CLOSE #2 CLOSE #1 OPEN tempfile2$ FOR OUTPUT AS #1 PRINT #1, "a" OPEN tempfile1$ FOR INPUT AS #2 DO LINE INPUT #2, sourceline$ FOR labelscan% = 1 TO numlabels% IF INSTR(sourceline$, RTRIM$(label(labelscan%).labelname)) THEN sourceline$ = LEFT$(sourceline$, INSTR(sourceline$, RTRIM$(label(labelscan%).labelname)) - 1) + "100" END IF NEXT labelscan% PRINT #1, sourceline$ LOOP UNTIL EOF(2) CLOSE #2 PRINT #1, "" PRINT #1, "u 100, 100" PRINT #1, "q" CLOSE #1 ' Run DEBUG to create DEBUG output file: SHELL rundebug$ + "<" + tempfile2$ + ">" + tempfile2$ ' Get length in bytes of source code: OPEN tempfile2$ FOR INPUT AS #1 DO oldline$ = midline$ midline$ = newline$ LINE INPUT #1, newline$ SEEK #1, SEEK(1) + 2 IF INSTR(newline$, "^") THEN PRINT "Error in source code detected. Look in "; tempfile2$; " for information." END END IF LOOP UNTIL newline$ = "-u 100, 100" CLOSE #1 asmlength$ = MID$(oldline$, INSTR(oldline$, ":") + 1, 4) PRINT "Source code byte length detected." OPEN tempfile2$ FOR OUTPUT AS #1 PRINT #1, "a" OPEN tempfile1$ FOR INPUT AS #2 DO LINE INPUT #2, sourceline$ FOR labelscan% = 1 TO numlabels% IF INSTR(sourceline$, RTRIM$(label(labelscan%).labelname)) THEN sourceline$ = LEFT$(sourceline$, INSTR(sourceline$, RTRIM$(label(labelscan%).labelname)) - 1) + "100" END IF NEXT labelscan% PRINT #1, sourceline$ LOOP UNTIL EOF(2) CLOSE #2 PRINT #1, "" PRINT #1, "u 100, "; asmlength$ PRINT #1, "q" CLOSE #1 ' Run DEBUG to create DEBUG output file again: SHELL rundebug$ + "<" + tempfile2$ + ">" + tempfile2$ OPEN tempfile2$ FOR INPUT AS #1 DO LINE INPUT #1, readline$ LOOP UNTIL INSTR(readline$, "-u 100,") SEEK #1, SEEK(1) + 2 labelcounter% = 1 linecounter% = 1 DO LINE INPUT #1, readline$ IF label(labelcounter%).labelnum = linecounter% THEN label(labelcounter%).labelpos = MID$(readline$, 6, 4) labelcounter% = labelcounter% + 1 END IF linecounter% = linecounter% + 1 LOOP UNTIL readline$ = "-q" CLOSE #1 OPEN tempfile2$ FOR OUTPUT AS #1 PRINT #1, "a" OPEN tempfile1$ FOR INPUT AS #2 DO LINE INPUT #2, sourceline$ FOR labelscan% = 1 TO numlabels% IF INSTR(sourceline$, RTRIM$(label(labelscan%).labelname)) THEN sourceline$ = LEFT$(sourceline$, INSTR(sourceline$, RTRIM$(label(labelscan%).labelname)) - 1) + label(labelscan%).labelpos END IF NEXT labelscan% PRINT #1, sourceline$ LOOP UNTIL EOF(2) CLOSE #2 PRINT #1, "" PRINT #1, "u 100, "; asmlength$ PRINT #1, "q" CLOSE #1 PRINT "Label conversion completed." ' Run DEBUG to create DEBUG output file again: SHELL rundebug$ + "<" + tempfile2$ + ">" + tempfile2$ PRINT "DEBUG output file successfully created." ' Transform the source code into BASIC string declaration lines: OPEN tempfile2$ FOR INPUT AS #1 DO LINE INPUT #1, readline$ LOOP UNTIL INSTR(readline$, "-u 100,") SEEK #1, SEEK(1) + 2 OPEN destfilename$ FOR OUTPUT AS #2 OPEN tempfile1$ FOR INPUT AS #3 PRINT #2, codestring$ + " = " + CHR$(34) + CHR$(34) linecounter% = 1 labelcounter% = 1 DO LINE INPUT #1, readline$ IF NOT EOF(3) THEN LINE INPUT #3, sourceline$ ELSE sourceline$ = "" 'PRINT sourceline$ readline$ = RTRIM$(readline$) IF readline$ <> "-q" THEN sourcedata$ = MID$(readline$, 11, 14) basicline$ = codestring$ + " = " + codestring$ + " + " FOR makebasicline% = 1 TO 13 STEP 2 IF MID$(sourcedata$, makebasicline%, 2) <> " " THEN basicline$ = basicline$ + "CHR$(&H" + MID$(sourcedata$, makebasicline%, 2) + ") + " END IF NEXT makebasicline% basicline$ = RTRIM$(basicline$) basicline$ = LEFT$(basicline$, LEN(basicline$) - 1) basicline$ = RTRIM$(basicline$) basicline$ = basicline$ + " ' " IF label(labelcounter%).labelnum = linecounter% THEN basicline$ = basicline$ + RTRIM$(label(labelcounter%).labelname) + ": " labelcounter% = labelcounter% + 1 END IF basicline$ = basicline$ + RIGHT$(readline$, (LEN(readline$) - 24)) FOR labelscan% = 1 TO numlabels% IF INSTR(sourceline$, RTRIM$(label(labelscan%).labelname)) THEN basicline$ = LEFT$(basicline$, LEN(basicline$) - 4) basicline$ = basicline$ + RTRIM$(label(labelscan%).labelname) END IF NEXT labelscan% basicline$ = RTRIM$(basicline$) PRINT #2, basicline$ END IF linecounter% = linecounter% + 1 LOOP UNTIL readline$ = "-q" PRINT #2, "" CLOSE #3 CLOSE #2 CLOSE #1 PRINT "Source code successfully moved to QBASIC destination file." KILL tempfile1$ KILL tempfile2$ PRINT PRINT "Time of conversion:"; TIMER - conversiontime!; "seconds."