如何在程序集中添加? [英] How to add in assembly?

查看:45
本文介绍了如何在程序集中添加?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试组装一个计算器.您引入两个变量,然后选择操作.现在的操作只是加法.我只处理 BIOS 中断,不处理 DOS.有人可以向我解释如何制作吗?我有两个问题,我被它们困住了:

I am trying to make a calculator in assembly. You introduce two variables and then you choose the operation. Now the operation is only addition. I am working only with BIOS interrupts, no DOS. Can someone explain to me how to make it? I have two problems and I am stuck with them:

  1. 第一个问题是当我添加 5+6 时,例如它返回ASCII 码为 59(48+11).我认为一个解决方案是以十进制打印,但我在互联网上没有发现任何仅使用 BIOS 中断的内容.
  2. 第二个问题是,当我加上 49+59 时,它返回 9,所以它只添加第一个字符.

代码:

    firstVariableKeyboard: ;store in var1 first variable
        mov ah,0x0
        int 16h ;keyboard interrupt

        cmp al,0x0d
        je returnEnter

        mov ah,0eh ;tty mode
        int 10h

        mov byte [var1 + bx],al
        inc bx

        jmp firstVariableKeyboard

    secondVariableKeyboard: ;store in var2 second variable
        mov ah,0x0
        int 16h

        cmp al,0x0d
        je returnEnter

        mov ah,0eh
        int 10h

        mov byte [var2 + bx],al
        inc bx

        jmp secondVariableKeyboard

   equalMath:
        ;introduce first variable
        mov si,math_description0
        call printString

        mov bx,0
        call firstVariableKeyboard
        mov dl,[var1]
        ;conversion from ascii to decimal
        sub dl, '0'

        ;new line
        mov si,newLine
        call printString

        ;introduce second variable
        mov si,math_description1
        call printString

        mov bx,0
        call secondVariableKeyboard
        mov dh,[var2]
        ;conversion from ascii to decimal
        sub dh, '0'

        ;new line
        mov si,newLine
        call printString

        ;the result
        mov si,math_description2
        call printString

        ;adding
        add dl, dh
        ;conversion from decimal to ascii
        add dl, '0'

        mov byte [result], dl
        mov si,result
        call printString

        ;new line
        mov si,newLine
        call printString

        jmp mainLoop

printString:
    push ax                   ; save ax to stack

    mov ah, 0x0e              ; call tty function
    call printChar      

    pop ax                    ; take ax out of the stack
    ret                      
printChar:
    mov al, [si]              ; load symbol

    cmp al, 0                 ; if si empty then jump
    jz ifZero               

    int 0x10                  ; if not print al
    inc si                    ; increment si

    jmp printChar       ;again untill stack empty
ifZero:
    ret

    var1: times 64 db 0 
    var2: times 64 db 0 
    result:  times 64 db 0 

  1. 5+6=11 示例
  2. 两个字符 + 两个字符的例子

推荐答案

这两个问题几乎相同.您正在尝试用 1 个 ASCII 字节表示一个包含 2 位数字的数字.你需要在你的输出上循环你的输入 AND.让我解释.我提前道歉,这个例子是 64 位的......你没有发布你的完整代码,所以我只是用我最了解的东西来写这个答案.

The two issues are almost the same. You are trying to represent a number containing 2 digits with 1 ASCII byte. You need to loop over your input AND over your output. Let me explain. I apologise in advance that the example is 64-bit ... you didn't post your complete code so I just ran with what I knew best to write this answer.

您实际上是在执行此操作:(53 - 48) + (54 - 48).这给了我们 11 的值.到目前为止一切顺利.将 11 表示为单个字符的 ASCII 值是多少?

You're essentially doing this: (53 - 48) + (54 - 48). This gives us the value 11. So far so good. What is the ASCII value for representing 11 as a single character?

没有一个.您需要的是打印字符 '1',两次(形成字符串 "11").

There isn't one. What you need, is to print the character '1', twice (to form the string "11").

那么您需要的是一种将超过 1 位数的数字转换为字符串的方法.也许类似于 C 标准中的 itoa 函数图书馆就足够了.

What you need then, is a way to convert a number that has more than 1 digit into a string. Perhaps something like the itoa function in the C standard library would be sufficient.

本质上,您需要遍历数字并将每个数字转换为一个字符以形成一个可以打印的字符串.您可以通过每次迭代将数字除以 10 并检查余数来完成此操作.这是在 IDEOne 上运行的示例

Essentially you need to loop over the number and convert each digit into a character to form a string you can print. You can do this by dividing the number by 10 each iteration and checking the remainder. Here is an example running on IDEOne

itoa 例子的核心是除法循环:

The core of the itoa example is the division loop:

.divloop:
    xor rdx,rdx         ; Zero out rdx (where our remainder goes after idiv)
    idiv rcx            ; divide rax (the number) by 10 (the remainder is placed in rdx)
    add rdx,0x30        ; add 0x30 to the remainder so we get the correct ASCII value
    dec rdi             ; move the pointer backwards in the buffer
    mov byte [rdi],dl   ; move the character into the buffer
    inc dword [rbp-4]   ; increase the length

    cmp rax,0           ; was the quotient zero?
    jnz .divloop        ; no it wasn't, keep looping

让我们逐步运行第二个示例中的数字 59:

Let's run the number 59 from your second example through this step by step:

当前缓冲区:

[0][0][0][0][0][0][0][0][0][0]

第一次迭代:

59 / 10 = 5 remainder 9
9 + 48 = 57 (the ASCII value of '9')

[0][0][0][0][0][0][0][0][0][57]
                            ^ place the ASCII value in the buffer, decrease the pointer and update the number to be the quotient from the idiv instruction

所以如果我们现在打印这个,我们会得到数字 9.不过商不是零,所以我们再次循环:

So if we print this now, we'd get the number 9. The quotient wasn't zero though so we loop around again:

5 / 10 = 0 remainder 5
5 + 48 = 53 (the ASCII value of '5')

[0][0][0][0][0][0][0][0][53][57]
                          ^ place the ASCII value in the buffer, decrease the pointer and update the number to be the quotient from the idiv instruction

最后一次迭代的商为零,因此我们不会循环并退出函数.

The quotient is zero from this last iteration, and so we don't loop and exit the function.

缓冲区中的这两个字节现在是 5357,它们是字符 59<的 ASCII 值/code> 分别.如果要将此缓冲区打印到标准输出,它将生成字符串 "59"(此示例函数还返回结果字符串的长度,以便可以正确打印).

These two bytes in the buffer are now 53 and 57 which are the ASCII values of the characters 5 and 9 respectively. If you were to print this buffer to your stdout, it would produce the string "59" (this example function also returns the length of the resulting string so that it can be printed correctly).

您的输入存在类似问题.您正在传递字符串49"和59",并且只读取第一个字符.您需要遍历此字符串并将其转换为整数.这应该是相当直接的,所以我将把它留给你作为练习.

There is a similar issue with your input. You are passing in the strings "49" and "59" and only reading the very first character. You need to loop over this string and convert it to an integer. This should be fairly straight forward so I will leave that as an exercise for you.

第二个例子有效"的原因(它打印了一个你有点期待的数字)是因为上面的错误.您只是将 4 和 5 相加,结果是 9 - 一个只有一位数的数字.

The reason the second example "works" (it prints a number you somewhat expect) is because of the bug above. You're only adding 4 and 5 together which results in 9 - a number that has a single digit.

希望能帮到你.

这篇关于如何在程序集中添加?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆