Перевод числа в строку - Assembler

Узнай цену своей работы

Формулировка задачи:

MASM, DosBox 0.76, строка не меняется. Компиляция: c:\masm611\bin\ml main.asm /c Линковка: c:\masm611\bin\link main.obj Код:
.model small
.stack 150h
 
.code
 
call main
 
NumToStr proc
    push ax ;Сохраняем в стек значения нужных регистров
    push bx
    push cx
    push bp
    push dx
    
    mov bp, sp ;Указатель на стек
    mov bl, 10; Делитель
    mov cx, 0; Каунтер в цикле
    mov al, [bp + 14] ;Аргумент 1 - число для помешения в строку
    
    DigitCounterBegin: ;Отличная реализация цикла по подсчёту количества цифр
    cmp ax, 0
    je DigitCounterEnd
    inc cx
    div bl
    mov ah, 0
    jmp DigitCounterBegin
    DigitCounterEnd: ;Конец цикла
    
    mov al, [bp + 14] ;см. строка 18
    cmp cx, 1
    je OnlyOneDigitInNumber ;Если всего одна цифра
    
    mov dx, 0
    
    ;Идея такая: Есть адрес строки и число (допустим)123, тогда:
    ;Адрес + 2 = '3'
    ;Адрес + 1 = '2'
    ;Адрес + 0 = '1'
    ;Именно в таком порядке
    
    ;cx теперь не количество всех цифр,
    ;а кол-во оставшихся
    
    StringDigitInserterBegin:
    cmp cx, 0; Когда не осталось цифр - выходим
    je StringDigitInserterEnd
    mov dh, 0
    mov dl, [bp + 12] ;Адрес (в dx адрес впихиваться не хотел, поместил в dl)
    ;Только ради этого и использовал регистр dx
    mov myaddr, dx; см. строка 78
    dec cx; Уменьшается колво оставшихся цифр
    ;Ведь вторую цифру нужно писать не в myaddr+2, а myaddr+1
    
    div bl; делим число на 10, чтобы получить в ah остаток (самую правую цифру)
    ;Поэтому я и записываю число справа налево
    
    add myaddr, cx; Смещение в строке
    
    mov bx, ax; Создаю копию получившегося числа
    mov bl, bh  ;см след. строку
    mov bh, 0   ;из (остаток - bh)(число - bl) делаем (0)(Остаток - bl)
    mov [myaddr], bx; по нужному адресу записываем цифру
    mov bx, 10; Восстанавливаем число 10, чтобы дальше делить на него
    mov ah, 0; обнуляем остаток, чтобы получить корректное число
    jmp StringDigitInserterBegin
    StringDigitInserterEnd:
    
    jmp MoreThanOneDigitInNumber; обход случая с одной цифрой
    
    OnlyOneDigitInNumber:
    add al, 48; 1 + '0' = '1', 2 + '0' = '2', ... 9
    mov [[bp + 12]], al; [bp+12] = адрес места, куда записываем
    
    MoreThanOneDigitInNumber: ;см строку 68
    
    pop dx ;Восстанавливаем значения  регистров
    pop bp
    pop cx
    pop bx
    pop ax
ret
    myaddr dw 0; Адрес места, куда нужно записать число
NumToStr endp
 
main proc
    mov ax, cs
    mov ds, ax; Чтобы объявлять данные прямо в коде, имхо так удобнее
    
    mov ax, 123; Что записывать
    push ax
    mov ax, offset mys + 14; Куда записывать
    push ax
    
    call NumToStr
    
    pop ax
    pop ax
    
    mov ax, 0
    
    mov dx, offset mys; Строка
    mov ah, 9; Печать
    int 21h
    
    mov ax, 4c00h
    int 21h; exit(0);
    
    mys db "My Number is: ___$"; ___ - место под число
    
main endp
end
P.s. Заметил странную особенность - все упоминания переменной myaddr в дизассемблерованом коде заменены на [myaddr] (TurboDebugger) P.s.s. Код "задокументировал" потому, что в асм'е новичек, и, наверняка, для кого-то без комментариев это будет не читаемый говнокод. Помогите :c

Решение задачи: «Перевод числа в строку»

textual
Листинг программы
.model small
.stack 150h
.data
    mys db "My Number is: "
    Number db "___$"; ___ - место под число
 
.code
 
NumToStr proc near
    push bp
    mov bp, sp ;Указатель на стек
 
    push ax ;Сохраняем в стек значения нужных регистров
    push bx
    push cx
    push dx
 
    mov bx, 10; Делитель
    mov cx, 0; Каунтер в цикле
    mov ax, [bp + 6] ;Аргумент 1 - число для помешения в строку
    ;в цикле получаются остатки от деления на 10, которые сохраняются в стеке
    ;а также в регистре cx подсчитывается количество цифр.
    @@DivLoop:
        mov     dx,     0
        inc     cx
        div     bx
        push    dx
        cmp     ax,     0
    jnz @@DivLoop
    ;цифры (остатки от деления на 10) извлекаются из стека и, после
    ;преобразования в символ, сохраняются в строку
    mov bx, [bp+4]
    @@ToStrLoop:
        pop     ax
        add     al,     '0'
        mov     [bx],   al
        inc     bx
    loop @@ToStrLoop
 
    pop dx ;Восстанавливаем значения  регистров
    pop cx
    pop bx
    pop ax
 
    pop bp
ret
NumToStr endp
 
main proc
    mov ax, @data
    mov ds, ax
 
    mov ax, 123; Что записывать
    push ax
    mov ax, offset Number; Куда записывать
    push ax
 
    call NumToStr
 
    pop ax
    pop ax
 
    mov dx, offset mys; Строка
    mov ah, 9; Печать
    int 21h
 
    mov ax, 4c00h
    int 21h; exit(0);
 
main endp
end  main

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 4.091 из 5