2017-04-23 68 views
2

我想提供一個最終項目的框架,這是一個FP計算器。但是,我遇到了一些麻煩。如果我編譯這個代碼,我得到Picture of Error Messages。我不確定這是什麼彙編,但我相信它的32位和我正在使用MASM編譯器。「Error A2006:Undefined Symbol,Macro Called From,Main Line Code」

這樣做的要點是從輸入文件中讀取一行,並進行執行操作。但是,我只是在做定義部分,我的合作伙伴會考慮實施這些操作。

如果我要將主函數減去「Only_Nums,Character_Error:和Invalid_Char:」,程序將編譯。

你能幫我確定爲什麼它不會編譯。我能想到的唯一合乎邏輯的事情是,被引用的代碼並沒有被首先定義,但是,它是。

謝謝!

編輯:用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 
+2

'[BP + 8 + ESI]'不是有效的尋址模式。你應該給'[BP + 8 + SI]'。你也應該改變你使用ESI到SI的其他地方。由於「.MODEL Small」指令,您顯示的代碼爲16位,因此您使用的是16位尋址,這意味着在SI上使用ESI作爲索引沒有意義。沒有什麼可以比64k更大。 –

+0

完成,但同樣的錯誤仍然存​​在。 – Jordan

+0

使用ESI作爲索引有時會帶來一個好處:它會強制彙編器添加32位大小覆蓋前綴,這就開闢了使用16位模式不支持的其他尋址模式的可能性。但是,羅斯的建議仍然很好。除非你知道自己在做什麼,否則16位代碼只能使用16位寄存器,而不能使用「E」前綴。 –

回答

2

被拒絕的符號位於內部一個過程(PROC..ENDP),因此本地爲一個較新的MASM代替ESI。他們在程序之外是未知的。

如果您雙擊冒號(::)你聲明的標籤爲「全球性」:

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 

更好的是要避免的過程間的標籤。例如,JB Only_Nums從程序中間Token跳轉到程序MAIN的中間。這被稱爲「意大利麪代碼」,並可能導致麻煩。您至少在堆棧上留下了Token的返回地址。看到MAIN的未來程序員不會知道這一點。

+0

非常感謝,這解決了我的問題! 你是什麼意思interprocedural標籤? 我很想讓這段代碼更好,我如何製作本地標籤? – Jordan

+0

@Jordan:我試圖在我的編輯中解釋它;-)。更好......嗯......避免跳出程序。用於此目的只能調用併爲目標創建單獨的過程(PROC..ENDP)。避免使用宏,如果你不是絕對堅定的話。宏不應該成爲程序的替代品。 – rkhb

+0

我看到了,是的,我正在考慮製作一個宏,它將接收錯誤消息字符串的偏移量;這將消除程序之外的呼叫。儘管我很困惑,爲什麼我應該避免使用宏,以及在哪裏用宏替換過程。我相信,讀取trig和log函數的宏應該在那裏,因爲它們通過了不同的變量。 – Jordan

相關問題