Перевод числа в строку - Assembler
Формулировка задачи:
MASM, DosBox 0.76, строка не меняется.
Компиляция: c:\masm611\bin\ml main.asm /c
Линковка: c:\masm611\bin\link main.obj
Код:
P.s. Заметил странную особенность - все упоминания переменной myaddr в дизассемблерованом коде заменены на [myaddr] (TurboDebugger)
P.s.s. Код "задокументировал" потому, что в асм'е новичек, и, наверняка, для кого-то без комментариев это будет не читаемый говнокод.
Помогите :c
.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
Решение задачи: «Перевод числа в строку»
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
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д