Как сложить цифры числа в сборке x86

Я работаю над программой на языке ассемблера, которая будет вычислять сумму цифр целого числа, которое будет введено клиентом. Номер всегда будет состоять из 10 цифр. Я очень новичок в сборке, и я понятия не имею, как действовать дальше. Вот что я написал до сих пор:

        SECTION .data

msg1:   db "Enter a number 10 digits long: "
len1:   equ $-msg1

msg2:   db "The sum of the digits is "
len2:   db $-msg2


        SECTION .bss

num:    resb 10
sum:    resb 3


        SECTION .text
        global _start

_start: nop

start:

        ;prompt for number
        mov     eax, 4
        mov     ebx, 1
        mov     ecx, msg1
        mov     edx, len1
        int     080h

        ;input number
        mov     eax, 3
        mov     ebx, 0
        mov     ecx, num
        mov     edx, 10
        int     080h

init:
        mov     esi, num
        mov     edi, sum

add_digits:

        ;loop 10 times
        ;retrieve next digit
        ;add '0' to convert to number
        ;add to sum

        ;subtract 0 to sum


        ;print results
        mov     eax, 4
        mov     ebx, 1
        mov     ecx, msg2
        mov     edx, len2
        int     080h

        mov     eax, 4
        mov     ebx, 1
        mov     ecx, sum
        mov     edx, 3
        int     080h

        ;exit
exit:
        mov     eax, 1
        mov     ebx, 0
        int     080h        

Мне просто нужно знать, как реализовать псевдокод в «add_digits». Кроме того, дайте мне знать, если я написал какой-либо код выше плохо/неправильно. Очень ценится.


person Community    schedule 19.02.2013    source источник
comment
Домашнее задание случайно?   -  person Seva Alekseyev    schedule 20.02.2013
comment
У меня есть вариант этого в качестве домашнего задания, но это основная часть того, что мне нужно сделать, и я понятия не имею, как это написать.   -  person    schedule 20.02.2013
comment
Крайняя левая цифра числа — это остаток от деления числа на 10. С другой стороны, частное дает вам число, в котором крайняя правая цифра стерта. Повторяйте, пока он не упадет до нуля.   -  person Seva Alekseyev    schedule 20.02.2013
comment
Спасибо! Но есть ли способ сделать это без использования модуля или деления? Но вместо этого использовать esi и edi?   -  person    schedule 20.02.2013
comment
Поскольку вы владеете искусством системных вызовов, вы можете также вызвать sprintf, чтобы сделать грязную работу и просмотреть результат.   -  person Aki Suihkonen    schedule 20.02.2013
comment
esi и edi — это просто регистры (переменные AKA). Ничего волшебного в них нет. rep команды, которые иногда используют эти две, не очень помогут. Вы можете повторно реализовать деление с вычитанием в цикле, но зачем?   -  person Seva Alekseyev    schedule 20.02.2013


Ответы (3)


Прочтите об инструкции деления AKA div, как она дает вам и частное, и остаток. Затем подумайте о связи между извлечением цифр числа и делением на 10.

person Seva Alekseyev    schedule 19.02.2013

Если вы читаете число в память как двоичное, вам нужно будет снова извлечь цифры из числа, то есть вам нужно преобразовать из двоичного в десятичное. Для преобразования между системами счисления нужно делить (в данном случае делить на 10) или использовать специальные алгоритмы. Существует двойное прикосновение для преобразования из двоичного в десятичное без деления, но, возможно, это медленнее, чем деление на поддерживаемых архитектурах. операция деления.

Самый простой способ - прочитать цифры одну за другой и сразу добавить к сумме, или прочитать целое число как строку, а затем добавить символы

person phuclv    schedule 31.10.2013

  1. так как sys_read всегда возвращает перевод строки - без него не вернется - я бы выделил 11 байт для буфера и поставил 11 в edx для sys_read. Возможно, вы также захотите очистить буфер...
  2. вы хотите вычесть '0' для преобразования символа в число и добавить '0' для преобразования числа в символ. В ваших комментариях это наоборот.
  3. так как мы знаем, согласно "спецификации", что сумма не будет превышать 90, что уместится в байте и может быть представлено двумя символами, да, есть способ избежать div...

    ; sum in al...
    aam ; split the byte in al into two digits in al and ah
    add ax, 3030h ; add '0' to both digits
    xchg al, ah  ; swap 'em into right order
    mov [edi], ax ; store both characters in "[sum]"
    mov byte [edi + 2], 10 ; linefeed after printing it?
    

(ВНИМАНИЕ, непроверенный код!) Это красиво и коротко, но ограничено диапазоном чисел, которые он будет преобразовывать — удобно для чисел «времени». Я бы научился делать это с помощью div и/или научился использовать библиотечные функции C, но, если мне не изменяет память, это должно сработать.

person Frank Kotler    schedule 20.02.2013