所以我有这段代码应该要求输入 2 个数字,然后对它们进行一些操作,在完成一个操作并输出答案后,它应该再次要求输入 2 个数字和一个选项,直到用户选择退出选项。但是由于某种原因,在打印一次结果之后,第二次它跳过了一个输入。
segment .data
prompt db "Please enter the first number: "
promptLen equ $-prompt
prompt2 db "Please enter the second number: "
prompt2Len equ $-prompt2
prompt3 db 10, "Your result is: "
prompt3Len equ $-prompt3
linefeed db 10
menu1 db "Please chose what to do with the numbers: ", 10
menu1Len equ $-menu1
menu2 db "1. Add", 10
menu2Len equ $-menu2
menu3 db "2. Multiply", 10
menu3Len equ $-menu3
menu4 db "3. Divide", 10
menu4Len equ $-menu4
menu5 db "4. Nothing, exit.", 10
menu5Len equ $-menu5
menu6 db "5. Surprise me"
menu6Len equ $-menu6
menu7 db 10, "Selection: "
menu7Len equ $-menu7
segment .bss
Num1 resb 8
Num2 resb 8
uNum1 resd 1
uNum2 resd 1
choice resd 1
uRes resd 1
Result resb 8
ResultLen resd 1
segment .text
global _start
_start:
call getNumbers
call getMenuOption
mov eax, [choice]
cmp eax, 49
je Addition
cmp eax, 50
je Multiply
cmp eax, 51
je Divide
cmp eax, 52
je exit
cmp eax, 53
je surprise
getNumbers:
mov eax, 4
mov ebx, 1
mov ecx, prompt
mov edx, promptLen
int 80h
mov eax, 3
mov ebx, 0
mov ecx, Num1
mov edx, 8
int 80h
mov esi, Num1
call dec2eax
mov [uNum1], eax
mov eax, 4
mov ebx, 1
mov ecx, prompt2
mov edx, prompt2Len
int 80h
mov eax, 3
mov ebx, 0
mov ecx, Num2
mov edx, 8
int 80h
mov esi, Num2
call dec2eax
mov [uNum2], eax
ret
dec2eax: ; Arg ESI: ASCII-string (0x0A-terminated) with decimal digits
xor eax,eax ; Result
xor edx, edx ; Especially to clear the 32-bit-part of EDX
.loop:
mov dl, byte [esi] ; Read digit
cmp dl, 10 ; End of string (SYS_READ - in certain cases not existent)?
je .finish ; Yes: done
lea eax, [eax*4+eax] ; EAX = 5 * EAX ...
add eax, eax ; ... and EAX = 2 * EAX results in EAX = EAX * 10
add esi, 1 ; Increment pointer to string
and dl, 0x0F ; Eliminate ASCII part of digit
add eax, edx ; Add digit to result
jmp .loop ; Next character
.finish:
ret ; Result: Converted unsigned integer in EAX
eax2dec: ; Arg EDI: Pointer to string that gets ASCII-characters
mov ebx, 10 ; Divisor
xor ecx, ecx ; CX=0 (number of digits)
.first_loop:
xor edx, edx ; Attention: DIV applies also DX!
div ebx ; DX:AX / BX = AX remainder: DX
push dx ; LIFO
inc cl ; Increment number of digits
test eax, eax ; AX = 0?
jnz .first_loop ; No: once more
mov ebx, ecx ; Save strlen
.second_loop:
pop ax ; Get back pushed digit
or al, 00110000b ; AL to ASCII
mov byte [edi], al ; Save AL
inc edi ; DI points to next character in string DECIMAL
loop .second_loop ; Until there are no digits left
mov byte [edi], 0 ; End-of-string delimiter (ASCIZ)
mov eax, ebx ; Return strlen in EAX
ret
getMenuOption:
mov eax, 4
mov ebx, 1
mov ecx, menu1
mov edx, menu1Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, menu2
mov edx, menu2Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, menu3
mov edx, menu3Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, menu4
mov edx, menu4Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, menu5
mov edx, menu5Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, menu6
mov edx, menu6Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, menu7
mov edx, menu7Len
int 80h
mov eax, 3
mov ebx, 0
mov ecx, choice
mov edx, 1
int 80h
ret
Addition:
xor edx, edx
mov eax, [uNum1]
mov ebx, [uNum2]
add eax, ebx
mov [uRes], eax
call printResult
jmp _start
Multiply:
xor edx, edx
mov eax, [uNum1]
mov ebx, [uNum2]
mul ebx
mov [uRes], eax
call printResult
jmp _start
Divide:
xor edx, edx
mov eax, [uNum1]
mov ebx, [uNum2]
div ebx
mov [uRes], eax
call printResult
jmp _start
surprise:
jmp _start
printResult:
mov eax, [uRes]
mov edi, Result
call eax2dec
mov [ResultLen], eax
mov eax, 4
mov ebx, 1
mov ecx, prompt3
mov edx, prompt3Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, Result
mov edx, [ResultLen]
int 80h
mov eax, 4
mov ebx, 1
mov ecx, linefeed
mov edx, 1
int 80h
ret
exit:
mov eax, 1
xor ebx, ebx
int 80h
我非常感谢有人指出它有什么问题,因为我对这种编程语言非常陌生。
编辑:这是我运行代码时发生的情况。
./menu
Please enter the first number: 3
Please enter the second number: 5
Please chose what to do with the numbers:
1. Add
2. Multiply
3. Divide
4. Nothing, exit.
5. Surprise me
Selection: 1
Your result is: 8
Please enter the first number: Please enter the second number: 3
Please chose what to do with the numbers:
1. Add
2. Multiply
3. Divide
4. Nothing, exit.
5. Surprise me
Selection: 1
Your result is: 3
Please enter the first number: Please enter the second number: 3
Please chose what to do with the numbers:
1. Add
2. Multiply
3. Divide
4. Nothing, exit.
5. Surprise me
Selection: 1
Your result is: 3
Please enter the first number: Please enter the second number: ^C
因此,在通过一个 jmp 回到 _start 之后,它会跳过一个输入,但是如果我取出“getMenuOption”并让它每次运行正常时都执行一个操作。