Assembly Nasm中断调用被跳过并输出多行
在进行前两次调用后,不会发生任何不好的情况,但只要按enter键选择菜单,它就会输出两个提示,要求用户输入,而不是在每次提示输入操作数时暂停 为什么中断会跳过 我现在真的很困惑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
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”,我发现我的输出是笑脸。你推荐过关于如何正确设计/构造汇编程序的书吗?因为我知道基本函数/寄存器,但我不知道如何正确地将它们组合在一起。我一步一步地使用汇编语言,这很好,但它没有深入到我的口味。