Assembly Nasm中断调用被跳过并输出多行

Assembly Nasm中断调用被跳过并输出多行,assembly,x86,buffer,nasm,interrupt,Assembly,X86,Buffer,Nasm,Interrupt,在进行前两次调用后,不会发生任何不好的情况,但只要按enter键选择菜单,它就会输出两个提示,要求用户输入,而不是在每次提示输入操作数时暂停 为什么中断会跳过 我现在真的很困惑 SECTION .data AskForCalculationPrompt: db "Choose which operation you want", 0xA, "1. Addition", 0xA, "2.Subtraction", 0xA, "3. Multiplication", 0xA, "4

在进行前两次调用后,不会发生任何不好的情况,但只要按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

我认为您遇到的是这样一个事实,
sys\u read
(来自stdin)在看到换行符(“回车”键)之前不会返回。只有您要查找的一个字符进入缓冲区(选项),换行符保留在操作系统的缓冲区中(称之为“键盘缓冲区”)。当下一个
sys\u read
出现时,它将该换行符读入下一个缓冲区(第一个操作数)。。。继续。。。欢闹接踵而至

修复它的简单方法是使这些缓冲区
resb2
edx
2,并相信用户只输入一个键,然后“输入”。。。每次。。。然后故意忽略每个缓冲区中的第二个字节

更好的方法可能是“刷新缓冲区”——操作系统的键盘缓冲区,而不是刚刚读入的缓冲区。当
sys\u read
返回时,读取的数字在
eax
中。如果小于
edx
,您应该是好的(在这种情况下不会是好的)。如果相等(不应大于),请检查最后一个字符是否为该换行符。如果是的话,你很好。如果没有,操作系统的缓冲区中会有更多的积垢(这会使你的下一次系统读取变得一团糟)。每次读取一个字节到“虚拟”缓冲区(在
.bss
或堆栈上),直到找到换行符-
cmp字节[dummybuf],0Ah
左右。那你准备好继续了

这就是原始系统调用编程的乐趣。:)

您没有问,但eax可能会自找麻烦。这将写入您的单字节缓冲区。。。还有后面的三个字节!它之后什么都没有,而且它不会与你不“拥有”的内存相冲突,所以现在不会引起问题,但它是一个“等待发生的bug”。使用
al
(应该可以在这里使用),或者回答
resd
,这样它将适合所有
eax


这不会给你你期望的答案。在对每个操作数进行算术运算之前,需要先从每个操作数中减去“0”(或30h或48),然后在打印之前将“0”加回答案。有了不止一个数字,情况就更糟了!首先让中断按预期工作。

是的,我应该移动al而不是eax。对于减法“0”,我发现我的输出是笑脸。你推荐过关于如何正确设计/构造汇编程序的书吗?因为我知道基本函数/寄存器,但我不知道如何正确地将它们组合在一起。我一步一步地使用汇编语言,这很好,但它没有深入到我的口味。