Reputation: 21
I am trying to provide a skeleton frame of a final project, which is a FP calculator. However, I've run into some trouble. If I compile this code, I get . I am unsure what assembly this is, but I believe its 32bit and am using MASM compiler.
The point of this is to read a line from the input file, and make perform operations. However, I am only doing the defining section, my partners will figure out implementing the operations.
If I were to comment out the main function, minus "Only_Nums, Character_Error:, and Invalid_Char:" the program will compile.
Can you help me in determining why it won't compile. The only logical thing I can think of is that the code being referenced wasn't defined first, however, it was.
Thanks!
Edit: Replaced ESI with SI
.MODEL Small
.386
.387
.STACK
.DATA
FileN DB "FILENAME.DAT",0
Buffer DB 255 DUP (?)
StrinLen DB 0
Num2FP DB 0
Base DB 10.0
FPNum DT 0.0
.CODE
;------------------------------code to search file and opening file------------------------------------------------------------------------------------------
;------------------------------code for setting up the file pointer to, initally the first line, but after the first, to the next------------------------------
;------------------------------I am going to use buffer as the placeholder for the string of the line------------------------------------------------------------
;------------------------------String Length------------------------------------------------------------------------------------------------
String_Length PROC FAR
PUSHAD
Next_Element: MOV AL, BYTE PTR [BP + 0 + SI]
INC SI
CMP AL, 0Dh
JNE Next_Element
MOV [BP+2], SI
POPAD
RET
String_Length ENDP
;----------------------------------------------------------------------------------------------------------------------------------------
;------------------------------Macro to detect if trig and log are functions------------------------------------------------------------
Detect_Func MACRO W, X, Y, Z
INC SI
MOV BL, BYTE PTR [BP + 8 + SI]
.IF (BL != W) && (BL != Y)
JMP Character_Error
.ENDIF
INC SI
MOV BL, BYTE PTR [BP + 8 + SI]
.IF (BL != W) && (BL != Z)
JMP Character_Error
.ENDIF
ENDM
;------------------------------Reading the string from the input file, directing what the program does------------------------------------------
;------------------------------Didn't initially write this as procedure, so it will need to be converted----------------------------------------
Token PROC FAR
ReadIn: MOV BL, BYTE PTR [BP + 8 + SI]
.IF (BL < '0' && BL > '9')
JB Check_Invalid
.ENDIF
SUB BL, 30h
MOVZX BX, BL
MOV [BP+6], BX
FILD WORD PTR [BP + 6]
FLD DWORD PTR [BP + 2]
FMUL DWORD PTR [BP + 4]
FADDP ST(1), ST
FBSTP [BP + 2]
INC SI
CMP [BP], SI
JB Only_Nums
JMP ReadIn
Check_Invalid:
FLD DWORD PTR [BP + 2]
.IF BL == 0DH
;------------------------------write to file, move file pointer to next line and jump to readin-------------------------------------------------
;------------------------------there should be some stopping condition in the event there aren't any more lines to calculate--------------------
.ELSEIF BL == ' '
INC SI
JMP ReadIn
.ELSEIF BL == '+'
CALL FP_Add
RET
.ELSEIF BL == '-'
CALL FP_Sub
RET
.ELSEIF BL == '*'
CALL FP_Mul
RET
.ELSEIF BL == '/'
CALL FP_Div
RET
.ELSEIF BL == '('
.ELSEIF BL == ')'
.ELSEIF BL == '^'
CALL FP_Power
RET
.ELSEIF BL == '.'
CALL FP_Dec
.ELSEIF (BL == 'E' || BL == 'e')
CALL FP_E
.ELSEIF (BL == 'C' || BL == 'c')
Detect_Func 'o', 's', 'O', 'S'
CALL FP_Cos
RET
.ELSEIF (BL == 'S' || BL == 's')
Detect_Func 'i', 'n', 'I', 'N'
CALL FP_Sin
RET
.ELSEIF (BL == 'T' || BL == 't')
Detect_Func 'a', 'n', 'A', 'N'
CALL FP_Tan
RET
.ELSEIF (BL == 'L' || BL == 'l')
Detect_Func 'o', 'g', 'O', 'G'
Detect_Func '1', '0', '1', '0'
CALL FP_Log
RET
.ELSEIF (BL == 'R' || BL == 'r')
;------------------------------display error if number follows...?------------------------------------------------------------------------------------------
.ELSE
JMP Invalid_Char
.ENDIF
RET
Token ENDP
FP_Add PROC FAR
CALL Token
RET
FP_Add ENDP
FP_Sub PROC FAR
CALL Token
RET
FP_Sub ENDP
FP_Mul PROC FAR
CALL Token
RET
FP_Mul ENDP
FP_Div PROC FAR
CALL Token
RET
FP_Div ENDP
FP_Power PROC FAR
CALL Token
RET
FP_Power ENDP
FP_Dec PROC FAR
CALL Token
RET
FP_Dec ENDP
FP_E PROC FAR
CALL Token
RET
FP_E ENDP
FP_Cos PROC FAR
CALL Token
RET
FP_Cos ENDP
FP_Sin PROC FAR
CALL Token
RET
FP_Sin ENDP
FP_Tan PROC FAR
CALL Token
RET
FP_Tan ENDP
FP_Log PROC FAR
CALL Token
RET
FP_Log ENDP
MAIN PROC FAR
.STARTUP
MOV SI, 0
PUSH OFFSET StrinLen ;[BP+2]
PUSH OFFSET Buffer ;[BP]
MOV BP, SP
CALL String_Length
ADD SP, 4
POP BP
PUSH BP
PUSH OFFSET Buffer ;[BP+8]
PUSH OFFSET Num2FP ;[BP+6]
PUSH OFFSET BASE ;[BP+4]
PUSH OFFSET FPNum ;[BP+2]
PUSH OFFSET StrinLen ;[BP]
MOV BP, SP
CALL Token
ADD SP, 10
POP SP
Only_Nums: ;No operands was given error message
Character_Error: ;output error message (trig and log function)
Invalid_Char: ;output invalid character detected (invalid characted detected in input file
MAIN ENDP
END
Upvotes: 2
Views: 1829
Reputation: 14399
The rejected symbols are located inside a procedure (PROC..ENDP) and therefore local for a newer MASM. They are unknown outside the procedure.
If you double the colon (::
) you declare that label as "global":
Token PROC FAR
...
JB Only_Nums
...
JMP Character_Error
...
JMP Invalid_Char
...
RET
Token ENDP
MAIN PROC FAR
...
Only_Nums:: ;No operands was given error message
Character_Error:: ;output error message (trig and log function)
Invalid_Char:: ;output invalid character detected (invalid characted detected in input file
...
MAIN ENDP
Better is to avoid interprocedural labels. For example, JB Only_Nums
jumps from the middle of the procedure Token
right into the middle of the procedure MAIN
. This is called "spaghetti code" and can lead to trouble. You leave at least the return addres of Token
on the stack. A future programmer who looks at MAIN
won't know that.
Upvotes: 2