Длинное деление в ASM x86 - PullRequest
0 голосов
/ 29 мая 2018

Я пишу программу ASM, которая делит два числа и вычисляет 20 десятичных знаков.Моя стратегия заключалась в том, чтобы вычислять следующие цифры с помощью процесса длинного деления и помещать их в стек.Затем получите указатель стека, вычтите из него 20 цифр * 8 бит и запишите цифру с этого адреса, затем добавьте 8 к этому адресу, запишите эту цифру и т. Д. Но когда я пытаюсь это записать только нули.Цифры находятся в стеке, потому что я попытался просто «вытолкнуть» их, и это прекрасно работает.Мне просто нужно, чтобы они появлялись в том же порядке, в котором они были нажаты, а не перевернуты.

мой код:

dane        SEGMENT ;segment danych
text        db 0dh, 0ah,"Give b (a/b)", 0dh, 0ah, "$"
text2       db 0dh, 0ah,"Give a (a/b)", 0dh, 0ah, "$"
text3       db 0dh, 0ah,"a/b:", 0dh, 0ah, "$"
quot        db 0h
rem         db 0h
counter     db 0h
dane        ENDS
; C:\ml /Fl /Zm /Zi /c lab3.asm
; E:\link /CODEVIEW lab3.obj

rozkazy     SEGMENT 'CODE' use16 ;segment rozkazu
        ASSUME cs:rozkazy, ds:dane
    start:  

        mov ax, SEG dane
        mov ds, ax

        mov cl, 03h
        mov ch, 0Ah

        mov dx, offset text
        mov ah, 09h
        int 21h                 ; "input divisor"

        mov ah, 01h
        int 21h                 ; input into al

        mov cl, al              
        sub cl, 30h             ; move to cl and subtract 30h to get value instead of ascii


        mov dx, offset text2
        mov ah, 09h
        int 21h                 ; "input dividend"

        mov ah, 01h
        int 21h 
        sub al, 30h             ; input into al and get number instead of ascii

        jmp divide





    divide: 
        cbw
        div cl                  ; convert al to ax and divide by cl
        mov dl, ah      

        cbw                     ; convert al -> ax

        push ax                 ; push ax to stack

        mov al, dl              ; move remainder from division to al
        xor ah, ah              
        cbw
        mul ch                  ; clear ah and al - > ax, multiply remainder times 10
        inc counter             ; increase counter by 1

        cmp counter, 14h        ; if the division was preformed 20 times, jump to show 
            jz show



        jmp divide

    show: 

        mov dx, offset text3
        mov ah, 09h
        int 21h             ; "your number" 

        mov bx, sp
        sub bx, 160         ; get stack pointer address and subtract by 8*20 (to get address of the number that is 20 positions down from sp) 

        jmp show2

    show2: 

        mov dx, [bx]        ; move value to dx from address that is stored in bx
        add dl, 30h         ; add 30h to get ascii
        mov ah, 02h
        int 21h             ; write dl out

        dec counter         ; decrease counter

        add bx, 8h          ; move our memory pointer 8 up (to next number)

        cmp counter, 0h
            jz finish       ; if counter = 0 jump to finish

        jmp show2

    finish:     
        mov ah, 4CH
        int 21H

rozkazy ENDS


stosik SEGMENT stack
    dw  128 dup(?)
stosik ENDS

END start

1 Ответ

0 голосов
/ 29 мая 2018

push ax сохраняет 2 байта в памяти, и вы делаете это 20 раз = 40 байтов.Я не понимаю, как вам удалось найти 160 для sub bx.

Также стек растет вниз, т.е. если перед вашим циклом sp равен 1234, то после первого push ax онбудет настроен на 1232 (-2), а значение al находится прямо на [1232] и ah на [1233].

Так что вы должны вместо add bx,19*2 вычислитьадрес первой сохраненной цифры, а затем sub bx,2 для перехода к следующей.

Кстати, в этом случае было бы эффективнее даже не сохранять значения, а просто выводить их немедленно, поэтому яПредположим, вы выполняете манипулирование стековой памятью.

Также используйте некоторый отладчик, чтобы проверить память и адресацию самостоятельно, ваша ошибка должна быть очевидной, если вы укажете sp после каждого push ax, где вы хранили конкретныйцифра.Был какой-то "cv.exe" (представление кода) из Microsoft DOS, или вы можете попытаться найти другие популярные отладчики DOS, хотя большинство из них, вероятно, трудно получить легальным путем.

Выможет также подумать об использовании некоторых современных инструментов, таких как эмуляторы DOS со встроенными отладчиками (в некоторых сборках dosbox, или BOCHS и т. д.), которые обычно более мощные, чем отладчик SW, работающий в DOS.


О, теперь я вижу ...

вычесть из него 20 цифр * 8 бит

Память адресуется байтами, а не битами, так чтоПредположим, вы можете настроить на 20 (20 цифр * 1 байт).Но вы делаете push ax, сохраняя 16 бит, а не только 8 (потому что на процессорах x86-16 нет инструкции push 8 bits), а 16 бит составляют 2 байта, поэтому необходимо 20 * 2 = 40 и в противоположном направлении.

...