【问题标题】:Calculator in Assembly Language - Linux x86 & NASM - Division汇编语言计算器 - Linux x86 & NASM - 除法
【发布时间】:2012-02-24 17:59:26
【问题描述】:

我正在用汇编语言制作一个可以在 x86 处理器上执行的计算器。

基本上,我的计算器要求用户输入两个数字,然后指示要对它们执行的操作(加法、减法、乘法和除法)。

我的计算器加减乘法正确,但无法除法。在进行除法时,我总是得到 1 作为结果。

然后我让我的应用程序代码完整:

section .data

    ; Messages

    msg1        db      10,'-Calculator-',10,0
    lmsg1       equ     $ - msg1

    msg2        db      10,'Number 1: ',0
    lmsg2       equ     $ - msg2

    msg3        db      'Number 2: ',0
    lmsg3       equ     $ - msg3

    msg4        db      10,'1. Add',10,0
    lmsg4       equ     $ - msg4

    msg5        db      '2. Subtract',10,0
    lmsg5       equ     $ - msg5

    msg6        db      '3. Multiply',10,0
    lmsg6       equ     $ - msg6

    msg7        db      '4. Divide',10,0
    lmsg7       equ     $ - msg7

    msg8        db      'Operation: ',0
    lmsg8       equ     $ - msg8

    msg9        db      10,'Result: ',0
    lmsg9       equ     $ - msg9

    msg10       db      10,'Invalid Option',10,0
    lmsg10      equ     $ - msg10

    nlinea      db      10,10,0
    lnlinea     equ     $ - nlinea

section .bss

    ; Spaces reserved for storing the values ​​provided by the user.

    opc         resb    2
    num1        resb    2
    num2        resb    2
    result      resb    2

section .text

    global _start

_start:

    ; Print on screen the message 1
    mov eax, 4
    mov ebx, 1
    mov ecx, msg1
    mov edx, lmsg1
    int 80h

    ; Print on screen the message 2
    mov eax, 4
    mov ebx, 1
    mov ecx, msg2
    mov edx, lmsg2
    int 80h

    ; We get num1 value.
    mov eax, 3
    mov ebx, 0
    mov ecx, num1
    mov edx, 2
    int 80h

    ; Print on screen the message 3
    mov eax, 4
    mov ebx, 1
    mov ecx, msg3
    mov edx, lmsg3
    int 80h

    ; We get num2 value.
    mov eax, 3
    mov ebx, 0
    mov ecx, num2
    mov edx, 2
    int 80h

    ; Print on screen the message 4
    mov eax, 4
    mov ebx, 1
    mov ecx, msg4
    mov edx, lmsg4
    int 80h

    ; Print on screen the message 5
    mov eax, 4
    mov ebx, 1
    mov ecx, msg5
    mov edx, lmsg5
    int 80h

    ; Print on screen the message 6
    mov eax, 4
    mov ebx, 1
    mov ecx, msg6
    mov edx, lmsg6
    int 80h

    ; Print on screen the message 7
    mov eax, 4
    mov ebx, 1
    mov ecx, msg7
    mov edx, lmsg7
    int 80h

    ; Print on screen the message 8
    mov eax, 4
    mov ebx, 1
    mov ecx, msg8
    mov edx, lmsg8
    int 80h

    ; We get the option selected.
    mov ebx,0
    mov ecx,opc
    mov edx,2
    mov eax,3
    int 80h

    mov ah, [opc]   ; Move the selected option to the registry ah
    sub ah, '0'     ; Convert from ascii to decimal

    ; We compare the value entered by the user to know what operation to perform.

    cmp ah, 1
    je add
    cmp ah, 2
    je subtract
    cmp ah, 3
    je multiply
    cmp ah, 4
    je divide

    ; If the value entered by the user does not meet any of the above 
    ; conditions then we show an error message and we close the program.
    mov eax, 4
    mov ebx, 1
    mov ecx, msg10
    mov edx, lmsg10
    int 80h

    jmp exit

add:
    ; We keep the numbers in the registers eax and ebx
    mov eax, [num1]
    mov ebx, [num2]

    ; Convert from ascii to decimal
    sub eax, '0'
    sub ebx, '0'

    ; Add
    add eax, ebx

    ; Conversion from decimal to ascii
    add eax, '0'

    ; We move the result
    mov [result], eax

    ; Print on screen the message 9
    mov eax, 4
    mov ebx, 1
    mov ecx, msg9
    mov edx, lmsg9
    int 80h

    ; Print on screen the result
    mov eax, 4
    mov ebx, 1
    mov ecx, result
    mov edx, 1
    int 80h

    ; We end the program
    jmp exit

subtract:
    ; We keep the numbers in the registers eax and ebx
    mov eax, [num1]
    mov ebx, [num2]

    ; Convert from ascii to decimal
    sub eax, '0'
    sub ebx, '0'

    ; Subtract
    sub eax, ebx

    ; Conversion from decimal to ascii
    add eax, '0'

    ; We move the result
    mov [result], eax

    ; Print on screen the message 9
    mov eax, 4
    mov ebx, 1
    mov ecx, msg9
    mov edx, lmsg9
    int 80h

    ; Print on screen the result
    mov eax, 4
    mov ebx, 1
    mov ecx, result
    mov edx, 1
    int 80h

    ; We end the program
    jmp exit

multiply:

    ; We store the numbers in registers ax and bx
    mov ax, [num1]
    mov bx, [num2]

    ; Convert from ascii to decimal
    sub ax, '0'
    sub bx, '0'

    ; Multiply. AL = AX x BX
    mul bx

    ; Conversion from decimal to ascii
    add al, '0'

    ; We move the result
    mov [result], al

    ; Print on screen the message 9
    mov eax, 4
    mov ebx, 1
    mov ecx, msg9
    mov edx, lmsg9
    int 80h

    ; Print on screen the result
    mov eax, 4
    mov ebx, 1
    mov ecx, result
    mov edx, 1
    int 80h

    ; We end the program
    jmp exit

divide:
    ; IN THIS LABEL IS THE ERROR!

    ; We store the numbers in registers ax and bx
    mov dx, 0
    mov ax, [num1]
    mov bx, [num2]

    ; Convert from ascii to decimall
    sub ax, '0'
    sub bx, '0'
    ; Division. AX = DX:AX / BX
    div bx

    ; Conversion from decimal to ascii
    add ax, '0'
    ; We move the result
    mov [result], ax

    ; Print on screen the message 9
    mov eax, 4
    mov ebx, 1
    mov ecx, msg9
    mov edx, lmsg9
    int 80h

    ; Print on screen the result
    ; ALWAYS PRINTS 1
    mov eax, 4
    mov ebx, 1
    mov ecx, result
    mov edx, 1
    int 80h

    ; We end the program
    jmp exit

exit:
    ; Print on screen two new lines
    mov eax, 4
    mov ebx, 1
    mov ecx, nlinea
    mov edx, lnlinea
    int 80h
    ; End the program
    mov eax, 1
    mov ebx, 0
    int 80h

错误必须在标签“divide”中找到。

为什么我总是得到 1 作为除法的结果?

我希望有更多经验的人可以帮助我。


非常感谢大家。我的计算器终于可以用了。这是我的最终代码:

    section .data

    ; Messages

    msg1        db      10,'-Calculator-',10,0
    lmsg1       equ     $ - msg1

    msg2        db      10,'Number 1: ',0
    lmsg2       equ     $ - msg2

    msg3        db      'Number 2: ',0
    lmsg3       equ     $ - msg3

    msg4        db      10,'1. Add',10,0
    lmsg4       equ     $ - msg4

    msg5        db      '2. Subtract',10,0
    lmsg5       equ     $ - msg5

    msg6        db      '3. Multiply',10,0
    lmsg6       equ     $ - msg6

    msg7        db      '4. Divide',10,0
    lmsg7       equ     $ - msg7

    msg8        db      'Operation: ',0
    lmsg8       equ     $ - msg8

    msg9        db      10,'Result: ',0
    lmsg9       equ     $ - msg9

    msg10       db      10,'Invalid Option',10,0
    lmsg10      equ     $ - msg10

    nlinea      db      10,10,0
    lnlinea     equ     $ - nlinea

section .bss

    ; Spaces reserved for storing the values ​​provided by the user.

    opc:        resb    2
    num1:       resb    2
    num2:       resb    2
    result:     resb    2

section .text

    global _start

_start:

    ; Print on screen the message 1
    mov eax, 4
    mov ebx, 1
    mov ecx, msg1
    mov edx, lmsg1
    int 80h

    ; Print on screen the message 2
    mov eax, 4
    mov ebx, 1
    mov ecx, msg2
    mov edx, lmsg2
    int 80h

    ; We get num1 value.
    mov eax, 3
    mov ebx, 0
    mov ecx, num1
    mov edx, 2
    int 80h

    ; Print on screen the message 3
    mov eax, 4
    mov ebx, 1
    mov ecx, msg3
    mov edx, lmsg3
    int 80h

    ; We get num2 value.
    mov eax, 3
    mov ebx, 0
    mov ecx, num2
    mov edx, 2
    int 80h

    ; Print on screen the message 4
    mov eax, 4
    mov ebx, 1
    mov ecx, msg4
    mov edx, lmsg4
    int 80h

    ; Print on screen the message 5
    mov eax, 4
    mov ebx, 1
    mov ecx, msg5
    mov edx, lmsg5
    int 80h

    ; Print on screen the message 6
    mov eax, 4
    mov ebx, 1
    mov ecx, msg6
    mov edx, lmsg6
    int 80h

    ; Print on screen the message 7
    mov eax, 4
    mov ebx, 1
    mov ecx, msg7
    mov edx, lmsg7
    int 80h

    ; Print on screen the message 8
    mov eax, 4
    mov ebx, 1
    mov ecx, msg8
    mov edx, lmsg8
    int 80h

    ; We get the option selected.
    mov ebx,0
    mov ecx,opc
    mov edx,2
    mov eax,3
    int 80h

    mov ah, [opc]       ; Move the selected option to the registry ah
    sub ah, '0'     ; Convert from ascii to decimal

    ; We compare the value entered by the user to know what operation to perform.

    cmp ah, 1
    je add
    cmp ah, 2
    je subtract
    cmp ah, 3
    je multiply
    cmp ah, 4
    je divide

    ; If the value entered by the user does not meet any of the above
    ; conditions then we show an error message and we close the program.
    mov eax, 4
    mov ebx, 1
    mov ecx, msg10
    mov edx, lmsg10
    int 80h

    jmp exit

add:
    ; We keep the numbers in the registers al and bl
    mov al, [num1]
    mov bl, [num2]

    ; Convert from ascii to decimal
    sub al, '0'
    sub bl, '0'

    ; Add
    add al, bl

    ; Conversion from decimal to ascii
    add al, '0'

    ; We move the result
    mov [result], al

    ; Print on screen the message 9
    mov eax, 4
    mov ebx, 1
    mov ecx, msg9
    mov edx, lmsg9
    int 80h

    ; Print on screen the result
    mov eax, 4
    mov ebx, 1
    mov ecx, result
    mov edx, 2
    int 80h

    ; We end the program
    jmp exit

subtract:
    ; We keep the numbers in the registers al and bl
    mov al, [num1]
    mov bl, [num2]

    ; Convert from ascii to decimal
    sub al, '0'
    sub bl, '0'

    ; Subtract
    sub al, bl

    ; Conversion from decimal to ascii
    add al, '0'

    ; We move the result
    mov [result], al

    ; Print on screen the message 9
    mov eax, 4
    mov ebx, 1
    mov ecx, msg9
    mov edx, lmsg9
    int 80h

    ; Print on screen the result
    mov eax, 4
    mov ebx, 1
    mov ecx, result
    mov edx, 1
    int 80h

    ; We end the program
    jmp exit

multiply:

    ; We store the numbers in registers al and bl
    mov al, [num1]
    mov bl, [num2]

    ; Convert from ascii to decimal
    sub al, '0'
    sub bl, '0'

    ; Multiply. AX = AL x BL
    mul bl

    ; Conversion from decimal to ascii
    add ax, '0'

    ; We move the result
    mov [result], ax

    ; Print on screen the message 9
    mov eax, 4
    mov ebx, 1
    mov ecx, msg9
    mov edx, lmsg9
    int 80h

    ; Print on screen the result
    mov eax, 4
    mov ebx, 1
    mov ecx, result
    mov edx, 1
    int 80h

    ; We end the program
    jmp exit

divide:

    ; We store the numbers in registers ax and bx
    mov al, [num1]
    mov bl, [num2]

    mov dx, 0
    mov ah, 0

    ; Convert from ascii to decimall
    sub al, '0'
    sub bl, '0'

    ; Division. AL = AX / BX
    div bl

    ; Conversion from decimal to ascii
    add ax, '0'
    ; We move the result
    mov [result], ax

    ; Print on screen the message 9
    mov eax, 4
    mov ebx, 1
    mov ecx, msg9
    mov edx, lmsg9
    int 80h

    ; Print on screen the result
    mov eax, 4
    mov ebx, 1
    mov ecx, result
    mov edx, 1
    int 80h

    ; We end the program
    jmp exit

exit:
    ; Print on screen two new lines
    mov eax, 4
    mov ebx, 1
    mov ecx, nlinea
    mov edx, lnlinea
    int 80h
    ; End the program
    mov eax, 1
    mov ebx, 0
    int 80h

【问题讨论】:

  • 即使您使用汇编语言进行编码,您也应该使用 C 库进行系统调用,并且您的程序入口点应该是 main,而不是 _start

标签: linux assembly x86 nasm division


【解决方案1】:

您正在将两个字节(字符)读入 num1num2 以供您输入数字。这通常是您输入的单个数字 (0-9) 和换行符。当你去执行一个操作时,你将 2 个字节分别读入 ax 和 bx,所以如果num1 为 5,num2 为 1,则 ax 将为 0xa35,bx 将为 0xa31。然后从每个中减去 0x30 并除以,在所有情况下都为 1,然后将其转换为 0x31 '1' 并打印。

现在在其他情况下(add/sub),您实际上是在将 4 个字节加载到 eax 和 ebx 中。因此,当您添加 51 时,您将在 eax 中获得 0xa310a35,在 ebx 中获得 0x????0a31(???? 来自 result 中发生的任何内容。)但是,在减去之后0x30 从每个加起来,eax 的最低字节将为 0x06,因此您将打印 6,因为您忽略了高字节中的内容。

【讨论】:

  • 非常感谢您的回复,但我无法完全理解您的回答。你能以代码的形式写下你的答案吗?很抱歉给您带来不便。
  • 我也尝试这样做,但我得到“浮动逗号异常”:` mov ax, [num1] mov bl, [num2] ;从 ascii 转换为十进制 sub ax, '0' sub bl, '0' ;分配。 AL = DX:AX / BX div bl ;从十进制转换为ASCII加al,'0';我们移动结果 mov [result], al`
  • @NicolasObesio:如果您只接受单个数字作为输入,您应该只读取一个字节。使用mov al,[num]mov [result],al 等,并仅对单个字节执行所有相关操作。
  • @ChrisDodd:我认为你成功了。
  • 克里斯做得很好,我不知道你知道 asm!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-03
  • 2018-05-14
相关资源
最近更新 更多