Assembly NASM中的计算器

Assembly NASM中的计算器,assembly,x86,nasm,dos,dosbox,Assembly,X86,Nasm,Dos,Dosbox,我正在尝试用NASM(Asembly)编写计算器。它并没有显示任何错误,但不知何故,在我输入两个数字相加后,程序就卡住了。在那之后我什么也做不了 以下是代码: org 100h _start: ;LOGO mov ah, 9 mov dx, logo1 int 21h mov ah, 9 mov dx, logo2 int 21h ;MENU mov ah, 9 mov dx, ramka1 int 21h mov ah, 9 mov dx, wybor int 21h mov ah

我正在尝试用NASM(Asembly)编写计算器。它并没有显示任何错误,但不知何故,在我输入两个数字相加后,程序就卡住了。在那之后我什么也做不了

以下是代码:

org 100h

_start:
;LOGO
mov ah, 9
mov dx, logo1
int 21h

mov ah, 9
mov dx, logo2
int 21h


;MENU
mov ah, 9
mov dx, ramka1
int 21h

mov ah, 9
mov dx, wybor
int 21h

mov ah, 9
mov dx, dzialanie1
int 21h

mov ah, 9
mov dx, dzialanie2
int 21h

mov ah, 9
mov dx, dzialanie3
int 21h

mov ah, 9
mov dx, dzialanie4
int 21h

mov ah, 9
mov dx, dzialanie5
int 21h

mov ah, 9
mov dx, ramka2
int 21h

mov ah, 9
mov dx, nwln
int 21h


; WYBOR DZIALANIA
mov ah, 0
int 16h

cmp al, '1' 
je dodawanie 

cmp al, '5'
je wyjscie


dodawanie:

mov ah, 9
mov dx, zmienna1
int 21h

mov ah, 0ah
mov dx, bufor
int 21h

lea si, [bufor + 2] 
mov cx, 0
mov cl, [bufor + 1]
call tekst_na_liczbe

mov [liczba1], ax

mov ah, 9
mov dx, nwln
int 21h

mov ah, 9
mov dx, zmienna2
int 21h

mov ah, 0ah
mov dx, bufor
int 21h

lea si, [bufor + 2]
mov cx, 0
mov cl, [bufor + 1]
call tekst_na_liczbe

add ax, [liczba1]

mov di, liczba
call liczbe_na_tekst

mov bl, '$'
mov bx,ax
mov [bx+liczba], bl

mov ah, 9
mov dx, wynik
int 21h

mov ah, 9
mov dx, liczba
int 21h

mov ah, 9
mov dx, nwln
int 21h

mov ah, 9
mov dx, nwln
int 21h

jmp _start


;WYJSCIE
wyjscie:

mov ax, 4C00h
int 21h

zmienna1 db "||Podaj pierwsza liczbe: $"

bufor db 15
db 0
times 15 db '$'

liczba db 15
db 0
times 15 db '$'

zmienna2 db "||Podaj druga liczbe: $"

liczba1 dd 0
liczba2 dd 0

wynik db 10, 13, "//Wynik: $"

nwln db 10, 13, '$'

menu db "Wybierz dzialanie:", 10, 13, 10, 13, '$'

;WYSWIETLENIE LOGO I MENU
logo1 db      "==============================================", 10, 13, "$"
logo2 db      "||Kalkulator w ASM                          ||", 10, 13, "$"
ramka1 db     "==============================================", 10, 13, "$"
wybor db      "||Wybierz dzialanie:                        ||", 10, 13, "$"
dzialanie1 db "||1.Dodawanie                               ||", 10, 13, "$"
dzialanie2 db "||2.Odejmowanie                             ||", 10, 13, "$"
dzialanie3 db "||3.Mnozenie                                ||", 10, 13, "$"
dzialanie4 db "||4.Dzielenie                               ||", 10, 13, "$"
dzialanie5 db "||5.Wyjcie z kalkulatora                    ||", 10, 13, "$"
ramka2 db     "==============================================", "$"



liczbe_na_tekst:
push cx
push dx
push si
mov cx, 10 
mov si, 0 
.dziel:
mov dx, 0 
div cx 
add dl, '0' 
mov bp,di
add di,si
mov dl,[bp]
inc si 
cmp ax, 1
jge .dziel 
push esi 
dec esi 
mov ecx, 0 
.odwroc:
mov bx, di 
mov di, cx 
add di, cx 
mov al,[bx] 
inc cx 
dec si
cmp cx, si
jl .odwroc 
pop ax 
pop dx
pop cx
ret


tekst_na_liczbe:
push bx
push dx
mov ax, 0 
mov bx, 0 
.petla:
mov dx, 10 
mul dx 
mov dl, [si+bx] 
sub dl, '0' 
add ax, dx 
inc bx 
cmp bx, cx 
jl .petla 
pop dx
pop bx
ret

很抱歉,部分代码是用波兰语编写的,但总体上应该是可以理解的。非常感谢你的帮助

因为绝对没有评论,所以很难理解到底发生了什么

liczbe_na_tekst
功能中,开始时按
cx
dx
si
,但最后弹出
ax
dx
cx
。在调用liczbe_na_tekst之前,
si
似乎包含缓冲区的地址。在
liczbe\u na_tekst
的末尾,它被传递到
ax

dodawanie
标签之后:

dodawanie:
 ...
lea si, [bufor + 2]
...
call liczbe_na_tekst

mov bl, '$'
mov bx,ax
在这里,您首先将
'$'
写入
bl
,但立即使用
ax
写入
bx
(丢失存储在
bl
中的
'$'
,只丢失前面的一条指令)
bx
现在包含
bufor+2
的地址(最初来自
lea si,[bufor+2]
),然后取代
“$”
bl
现在包含
bufor+2
的低8位地址

mov [bx+liczba], bl
然后,在这里写入
[bufor+liczba+2]
地址的低位8位
bufor+2
,而不是
“$”
bx
在这里包含
bufor+2
的地址

mov [bx+liczba], bl
我认为这不是你打算做的。当您修改
liczbe_na_-tekst
tekst_-na_-liczbe
的代码时(当您将地址
bufor
liczba
相加时,
liczbe_-na_-tekst
tekst_-na_-liczbe
的子函数都在内存中的数据之后),您的代码可能会崩溃,当CPU到达非法指令或进入无限循环时,程序崩溃

我认为您至少需要修复以下部分:

liczbe_na_tekst
push
pop
指令:

liczbe_na_tekst:
    push ax
    push cx
    push dx
    push si
    ...
    pop si
    pop dx
    pop cx
    pop ax
    ret
mov bx,ax
mov [bx+liczba], byte '$'
然后在
之后调用liczbe_na_tekst

liczbe_na_tekst:
    push ax
    push cx
    push dx
    push si
    ...
    pop si
    pop dx
    pop cx
    pop ax
    ret
mov bx,ax
mov [bx+liczba], byte '$'
可能还需要一些其他修复。尚未测试。

这可能不是“答案”。。。反正不是“答案”。。。但在我看来这是“错误的”。


如果输入正好是“5”,则转到
wyjscie
(波兰语表示“退出”?)。任何其他输入-包括但不限于“1”-我们“跌破”到
dodawanie
。这是您的意图吗?

看起来您可能在上传代码之前无意中删除了代码中的所有注释?请使用调试器逐步检查代码。@Inver:出于好奇,您是在MS-DOS操作系统中运行它,还是在虚拟机/DOS模拟器上运行它?我使用的是DosBox,同一个玩老游戏;)。哈,没错。2、3、4用于其余操作。现在我只专注于增加数字,如果这行得通,我会休息。好的。关注nrz已确定的问题。接得好,nrz!多达瓦尼的意思是额外的感谢,我会尽快测试它;D