2013-06-20 15 views
0

在第一次2次呼叫後,沒有什麼不好的事情發生,但只要按下回車鍵選擇菜單,它會輸出兩個提示,要求用戶輸入,而不是在每次提示時暫停輸入操作數。納斯姆中斷呼叫跳過並輸出多行

爲什麼中斷會跳過?

我現在很困惑。

SECTION .data 

     AskForCalculationPrompt: db "Choose which operation you want", 0xA, "1. Addition", 0xA, "2.Subtraction", 0xA, "3. Multiplication", 0xA, "4. Division", 0x3 
     AskForCalculationPromptln: equ $-AskForCalculationPrompt 

     FirstOperandPrompt: db "Enter the first operand:", 0xA 
     FirstOperandPromptln: equ $-FirstOperandPrompt 

     SecondOperandPrompt: db "Enter the second operand:", 0xA 
     SecondOperandPromptln: equ $-SecondOperandPrompt 

     AnswerPrompt: db "The answer is: " 
     AnswerPromptln: equ $-AnswerPrompt 

     ErrorMsg: db "Wrong Choice made...insert correct choice" 
     ErrorMsgln: equ $-ErrorMsg 


SECTION .bss 

     Choice: resb 1 
     FirstOperand: resb 1 
     SecondOperand: resb 1 
     Answer: resb 1 

SECTION .text 

     ;Make interrupt to ask for a prompt ask for calculation prompt 
     global _start 

     _start: 

     mov eax, 4 ;Specify sys_write call 
     mov ebx, 1 ;Standard output 
     mov ecx, AskForCalculationPrompt 
     mov edx, AskForCalculationPromptln 
     int 80h 

     ;Make interrupt to read textfrom keyboard 
     READ: 

     mov eax, 3 ;Sys_read call 
     mov ebx, 0 ;Standard input file descriptor 0 
     mov ecx, Choice 
     mov edx, 1 
     int 80h 

     ;Determine what we inserted 

     ;Prompt for first operand 
     mov eax, 4 
     mov ebx, 1 
     mov ecx, FirstOperandPrompt 
     mov edx, FirstOperandPromptln 
     int 80h 

     ;Retrieve first operand input 
     mov eax, 3 
     mov ebx, 0 
     mov ecx, FirstOperand 
     mov ebx, 1 
     int 80h 

     ;Prompt for second operand 
     mov eax, 4 
     mov ebx, 1 
     mov ecx, SecondOperandPrompt 
     mov edx, SecondOperandPromptln 
     int 80h 

     ;Retrieve second operand input 
     mov eax, 3 
     mov ebx, 0 
     mov ecx, SecondOperand 
     mov edx, 1 
     int 80h 

     ;Load values retrieved into registers eax, ebx, ecx, for comparison and operation 
     mov al, byte [Choice] 
     mov bl, byte [FirstOperand] 
     mov cl, byte [SecondOperand] 


     JMP SWITCH 
;******************************************************************************* 
;SWITCH************************************************************************* 
;******************************************************************************* 
     SWITCH: 

       cmp al, 0x31 
       je ADDLABEL 

       cmp al, 0x32 
       je SUBTRACTLABEL 

       cmp al, 0x33 
       je MULTIPLICATIONLABEL 

       cmp al, 0x34 
       je DIVISIONLABEL 

       JMP DEFAULTLABEL 

     DEFAULTLABEL: 

       mov eax, 4 
       mov ebx, 1 
       mov ecx, ErrorMsg 
       mov edx, ErrorMsgln 
       int 80h 
       JMP READ 


;***************************************************************************** 
;OPERATIONS******************************************************************* 
;***************************************************************************** 

     ADDLABEL: 
       mov al, cl 
       add al, bl 
       JMP DISPLAYOPERATION 

     SUBTRACTLABEL: 
       mov al, cl 
       sub al, bl 
       JMP DISPLAYOPERATION 

     MULTIPLICATIONLABEL: 
       mov al, cl 
       mul cl 
       JMP DISPLAYOPERATION 

     DIVISIONLABEL: 
       mov al, cl 
       div cl 
       JMP DISPLAYOPERATION 

;***************************************************************************** 
;DISPLAYOPERATION************************************************************* 
;***************************************************************************** 

     DISPLAYOPERATION: 

       mov [Answer], eax 
       mov eax, 4 
       mov ebx, 1 
       mov ecx, Answer 
       mov edx, 1 
       int 80h 

       mov eax, 1 
       mov ebx, 0 
       int 80h 

回答

1

我想你碰到的是一個事實,即sys_read(從標準輸入)不會返回,直到它看到一個換行符(「回車」鍵)。只有你正在尋找的一個字符進入你的緩衝區(選擇),換行符保留在操作系統的緩衝區中(稱之爲「鍵盤緩衝區」)。當下一個sys_read出現時,它讀取到您的下一個緩衝區(FirstOperand)中的換行......並繼續進行......歡鬧隨之而來!

解決這個問題的簡單方法是讓這些緩衝區resb 2和使edx 2,並相信用戶只輸入一個密鑰,然後「輸入」...每次...然後好好忽略第二個字節在每個緩衝區中。

更好的方法可能是「刷新緩衝區」 - 操作系統的鍵盤緩衝區,而不是剛纔讀入的緩衝區。當sys_read返回時,讀取的數字是eax。如果它小於edx,你應該很好(在這種情況下,它不會)。如果相同(不應該更大),請檢查最後一個字符是否是換行符。如果是,你很好。如果沒有,操作系統緩衝區中會有更多的垃圾(這會使你的下一個sys_read搞砸!)。讀取一個「虛擬」緩衝區(在.bss或堆棧中),一次一個字節,直到找到那個換行符 - cmp byte [dummybuf], 0Ah左右。然後你就可以繼續...

這就是原始sys_call編程的樂趣。 :)

你不問,但mov [Answer], eax可能會有問題。這將寫入您的單字節緩衝區......以及之後的三個字節!之後沒有任何東西,它不會對付你不擁有的「記憶」,所以它現在不會造成問題,但它是一個「等待發生的錯誤」。要麼使用al(應該在這裏工作),或做出解答resd所以它會適合所有的eax

這不會給你所期望的答案。您需要從每個操作數中減去'0'(或30h或48),然後再對其進行算術運算,然後在打印之前將「0」加回到答案中。不止一個數字,情況更糟!首先讓中斷按照預期工作。

+0

是的,我應該移動al而不是eax。而當減去'0'時,我發現當我的輸出是笑臉時。 – Kelvin

+0

感謝您的幫助 – Kelvin

+0

您是否推薦過關於如何正確設計/構造組裝程序的書籍?因爲我知道基本的功能/寄存器,但我不知道如何正確地把它們放在一起。我一步一步地使用匯編語言,這是偉大的,但它沒有足夠深入我的口味。 – Kelvin