在进行前2次调用后,没有任何不良情况发生,但只要按Enter键选择菜单,它就会输出两个提示,要求输入用户输入,而不是在每次提示时暂停以输入操作数。
为什么中断会跳过?
我现在真的很困惑。
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
答案 0 :(得分:1)
我认为你遇到的是sys_read
(来自stdin)直到看到换行符(“输入”键)才返回的事实。只有您要查找的一个字符进入缓冲区(选择),换行符保留在OS的缓冲区中(称之为“键盘缓冲区”)。当下一个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
这不会给你你期望的答案。在对em进行算术运算之前,需要从每个操作数中减去“0”(或30h或48),然后在打印之前将“0”添加回答案。如果不超过一位数,那就更糟了!首先让中断按预期工作。