中缀到 MASM 程序集中的后缀转换



这是我使用 MASM 对输入文件中的内容进行简单计算的任务。我们使用的书是"x86处理器的汇编语言"。

现在我正在尝试进行中缀到后缀转换。我尝试转换的输入是:12/3+4,但它只是停止并显示.exe已停止工作,我发现它停止在 main 函数的INVOKE CheckAddSub处。

你能帮我看看那个过程中出了什么问题吗?我尝试使用堆栈来推送/弹出,但后来我改成了这个,因为因为我正在调用函数,我认为不使用堆栈会更容易做到这一点。非常感谢您抽出时间查看我的代码。

INCLUDE C:IrvineIrvine32.inc
INCLUDE C:Irvinemacros.inc
CheckAddSub PROTO, seStr1:PTR BYTE, outStr1:PTR BYTE, pCo:DWORD, pDo:DWORD, 
outCo1:DWORD
CheckMulDiv PROTO, seStr2:PTR BYTE, outStr2:PTR BYTE, theCo:DWORD, 
theDo:DWORD, outCo2:DWORD
.data
inputStr BYTE 20 dup(?)    ;input array
outputStr BYTE 20 dup(?)   ;postfix array
sizeSt DWORD 20
secStr BYTE 10 dup(?)    ;to store the operator
count DWORD 0
dStr BYTE 0
outCount DWORD 0
.code
main PROC
    mWrite "Input: "
    mov edx, OFFSET inputStr 
    mov ecx, SIZEOF inputStr - 1
    call ReadString
    mov esi, OFFSET inputStr     ;now the input str has elements
    mov edi, OFFSET outputStr    ;for storing the postfix 
    mov ecx, sizeSt              ;to loop
    mov edx, OFFSET secStr       ;to store operator
L1:
    mov ebx, [esi]
    .if bl=='+'|| bl=='-' 
        inc count             
    .if count > 1           ;when count is 2 mean there is already element in 
                             the secStr array so i can do the checking
        INVOKE CheckAddSub, ADDR secStr, ADDR outputStr, count, dStr,outCount
        inc dStr        ;dStr is to store the index number of the secStr 
                         array, after the zero index predencency is checked, 
                        ;increment dStr to indicate the index number this 
                         current operator in secStr array
    .endif
    mov [edx],ebx     ;put the operator into secStr
    add edx,1
    .elseif bl=='*'|| bl =='/'
        inc count
    .if count > 1
        INVOKE CheckMulDiv, ADDR secStr, ADDR outputStr , count, dStr, outCount
        inc dStr
    .endif
    mov [edx],ebx   
    add edx,1
    .else                  ;when it is operand(number), put into output array
       mov [edi], ebx
       inc outCount
    .endif
    inc edi
    inc esi
    dec ecx  
    cmp ecx,0
    jne L1    
    mov edx, OFFSET outputStr
    mWrite "the postfix string is: "
    call WriteString
   INVOKE ExitProcess,0
 main ENDP
 ;-----------------------------------------------------------
 CheckAddSub PROC USES edx edi eax ecx ebx,
 seStr1:PTR BYTE,      ;secStr
 outStr1:PTR BYTE,     ;outputStr
 pCo:DWORD, 
 pDo:DWORD,
 outCo1:DWORD
;------------------------------------------------------------
    mov edx, seStr1      
    mov edi, outStr1
LW:
    mov ebx, [edx+pDo]            ;edx+pDo is the last element in the array, 
                                     like stack the top element
    .if bl=='+'|| bl=='-'|| bl=='*' || bl=='/'
         mov [edi+outCo1],ebx      ;if one of these operator exists in the 
                                    secStr array, then put this operator into 
                                    the outputStr array 
         mov [edx+pDo], 0          ;put null in this current index,indicating 
                                    this element is already pop out from the 
                                    secStr array    
         inc outCo1 
    .endif
    .if pDo!=0
         sub pDo,1
    .endif
    dec pCo         
    cmp pCo,1
    jne LW
    je L5
L5: ret 
CheckAddSub ENDP
;------------------------------------------------------
CheckMulDiv PROC USES edx edi eax ecx ebx,
  seStr2:PTR BYTE, 
  outStr2:PTR BYTE, 
  theCo:DWORD, 
  theDo:DWORD,
  outCo2:DWORD
;-------------------------------------------------------
   mov edx, seStr2
   mov edi, outStr2
LR:
   mov ebx,[edx+theDo]
   .if bl=='*'|| bl=='/'
      mov [edi+outCo2],ebx
      mov [edx+theDo],0
      inc outCo2
   .endif
   .if theDo!=0
     sub theDo,1
   .endif
   dec theCo
   cmp theCo, 1
   jne LR
   je L6
L6: ret
CheckMulDiv ENDP
END main
call ReadString
mov esi, OFFSET inputStr     ;now the input str has elements
mov edi, OFFSET outputStr    ;for storing the postfix 
mov ecx, sizeSt              ;to loop

您使用的是固定次数的迭代。在本例中为 20,因为 sizeSt 是这样定义的。

你想要的是遍历你实际收到的字节。您从 ReadString EAX中获得了此计数,因此请使用它:

call ReadString
mov esi, OFFSET inputStr     ;now the input str has elements
mov edi, OFFSET outputStr    ;for storing the postfix 
mov ecx, eax                 ;to loop

mov ebx, [esi]
...
mov [edx], ebx
...
mov [edi], ebx

由于您正在处理字节,因此必须使用字节大小的BL寄存器,而不是 DWORD 大小的EBX寄存器!


dStr BYTE 0

考虑到 PROTO/INVOKE ,您需要将其更改为:

dStr DWORD 0

最新更新