【问题标题】:"Error A2006: Undefined Symbol, Macro Called From, Main Line Code"“错误 A2006:未定义符号、调用宏、主行代码”
【发布时间】:2017-04-23 02:16:06
【问题描述】:

我正在尝试提供一个最终项目的骨架框架,它是一个 FP 计算器。但是,我遇到了一些麻烦。如果我编译这段代码,我会得到。我不确定这是什么程序集,但我相信它是 32 位的,并且正在使用 MASM 编译器。

这样做的目的是从输入文件中读取一行,然后执行操作。不过,我只是在做定义部分,我的合作伙伴会想办法实现这些操作。

如果我要注释掉主函数,减去“Only_Nums, Character_Error:, and Invalid_Char:”,程序就会编译。

你能帮我确定它为什么不能编译吗?我能想到的唯一合乎逻辑的事情是,被引用的代码不是首先定义的,但是,它是。

谢谢!

编辑:将 ESI 替换为 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

【问题讨论】:

  • [BP+8+ESI] 不是有效的寻址模式。你应该把它发给[BP + 8 + SI]。您还应该将使用 ESI 的所有其他地方更改为 SI。由于 .MODEL Small 指令,您显示的代码是 16 位的,因此您使用的是 16 位寻址,这意味着在 SI 上使用 ESI 作为索引是没有意义的。没有什么可以大于 64k。
  • 完成,但同样的错误仍然存​​在。
  • 有时使用 ESI 作为索引有一个优势:它强制汇编器添加 32 位大小的覆盖前缀,这开辟了使用 16 位不支持的其他寻址模式的可能性模式。但是,是的,罗斯的建议仍然很好。除非你知道自己在做什么,否则 16 位代码应该只使用 16 位寄存器,没有 E 前缀。

标签: assembly masm undefined-function


【解决方案1】:

被拒绝的符号位于内部过程 (PROC..ENDP),因此对于较新的 MASM 而言是 本地。它们在程序之外是未知的。

如果将冒号 (::) 加倍,则将该标签声明为“全局”:

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 的未来程序员不会知道这一点。

【讨论】:

  • 非常感谢,这解决了我的问题!!!你是什​​么意思跨过程标签?我很想把这段代码做得更好,我是如何制作本地标签的?
  • @Jordan:我试图在我的编辑中解释它;-)。更好...嗯...避免跳出程序。仅用于该目的调用并为目标创建单独的过程 (PROC..ENDP)。避免使用宏,如果你不是绝对坚定的话。宏不应替代过程。
  • 我明白了,是的,我正在考虑制作一个宏来获取错误消息字符串的偏移量;这将消除程序之外的调用。虽然我很困惑为什么我应该避免使用宏,以及在哪里用宏替换过程。我相信,读取 trig 和 log 函数的宏应该在那里,因为它们传递不同的变量。
猜你喜欢
  • 1970-01-01
  • 2011-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-10
  • 2013-10-22
  • 2014-06-01
相关资源
最近更新 更多