Вывод двойных слов - Assembler

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

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

Сап анон, полгода учу MASM 4.0 (Intel 8086). Возникла проблема с красивым выводом двойных слов. Ясно что можно выводить их как:
Листинг программы
  1. mov ax,word ptr x
  2. outint ax
  3. mov ax,word ptr x+2
  4. outint ax
Однако вывод не всегда корректный. Можете помочь с корректным выводом?

Решение задачи: «Вывод двойных слов»

textual
Листинг программы
  1.    
  2. ; Модуль IOPROC:  Процедуры ввода-вывода
  3. ;         испpавление - от 30.03.2001
  4.    
  5.   public procnl, procoutnum, procflush, procinch, procinint
  6.  
  7. iocode segment
  8.    assume cs:iocode
  9.    
  10. ;************************************************
  11. ;               ВЫВОД НА ЭКРАН
  12. ;************************************************
  13.  
  14. ;========================================
  15. ;  Перевод курсора на новую строку экрана
  16. ;   Обращение: call procnl
  17. ;   Параметров нет
  18. ;----------------------------------------
  19. procnl proc far
  20.       push dx
  21.       push ax
  22.       mov  ah,2
  23.       mov  dl,13        ; CR (курсор на начало строки)
  24.       int  21h
  25.       mov  dl,10        ; LF (курсор на следующую строку)
  26.       int  21h
  27.       pop  ax
  28.       pop  dx
  29.       ret
  30. procnl endp
  31.  
  32. ;==============================================================
  33. ;  Вывод целого числа-слова со знаком или без знака
  34. ;   Обращение:  call procoutnum
  35. ;   На входе:  ax - выводимое число
  36. ;              dh - число со знаком (1) или без знака (0)
  37. ;              dl - ширина поля вывода (>=0)
  38. ;    (если поле больше, чем надо, то слева добавляются пробелы,
  39. ;     если меньше - выводится только число)
  40. ;--------------------------------------------------------------
  41. procoutnum proc far
  42.       push bp
  43.       mov  bp,sp
  44.       push ax
  45.       push dx
  46.       push si
  47.       sub  sp,6         ; отвести 6 байтов в стеке под число
  48. ; учет знака
  49.       cmp  dh,1         ; вывод со знаком (dh=1)?
  50.       jne  pon0
  51.       cmp  ax,0
  52.       jge  pon0
  53.       mov  dh,2         ; если вывод со знаком и ax<0,
  54.       neg  ax           ;  то dh:=2, ax:=abs(ax)
  55. pon0: push dx           ; спасти dh (знак) и dl (ширину)
  56. ; запись цифр числа в стек обратном порядке)
  57.       xor  si,si        ; si - кол-во цифр в числе
  58. pon1: mov  dx,0         ; ax -> (dx,ax)
  59.       div  cs:ten       ; ax=ax div 10;  dx=ax mod 10
  60.       add  dl,'0'
  61.       mov  [bp-12+si],dl ; цифра -> стек
  62.       inc  si
  63.       or   ax,ax
  64.       jnz  pon1         ; еще не 0
  65. ; запись минуса, если есть, в стек
  66.       pop  dx
  67.       cmp  dh,2
  68.       jne  pon2
  69.       mov  byte ptr [bp-12+si],'-'
  70.       inc  si
  71. ; печать пробелов впереди
  72. pon2: mov  dh,0         ; dx - ширина поля вывода
  73.       mov  ah,2         ; функция 02 прерывания 21h
  74. pon21: cmp dx,si
  75.       jle  pon3         ; ширина <= длина числа
  76.       push dx
  77.       mov  dl,' '
  78.       int  21h
  79.       pop  dx
  80.       dec  dx
  81.       jmp  pon21
  82. ; печать (минуса и) цифр
  83. pon3: dec  si
  84.       mov  dl,[bp-12+si]
  85.       int  21h
  86.       or   si,si
  87.       jnz  pon3
  88. ; выход из процедуры
  89.       add  sp,6
  90.       pop  si
  91.       pop  dx
  92.       pop  ax
  93.       pop  bp
  94.       ret
  95. ten   dw 10
  96. procoutnum endp
  97.    
  98.    
  99. ;***********************************************************
  100. ;                 ВВОД С КЛАВИАТУРЫ
  101. ;***********************************************************
  102.  
  103. ;   буфер ввода с клавиатуры (для работы с функцией 0Ah)
  104. maxb  db 128            ; макс. размер буфера ввода
  105. sizeb db 0              ; число введенных символов в буфере
  106. buf   db 128 dup(?)     ; сам буфер ввода
  107. posb  db 0              ; номер послед. считан. символа из buf
  108.  
  109. ;===================================================
  110. ; вспомогательная процедура ввода строки символов
  111. ; (включая Enter) в буфер buf (ввод без приглашения)
  112. ;---------------------------------------------------
  113. readbuf proc near
  114.       push ax
  115.       push dx
  116.       push ds
  117.       mov  dx,cs
  118.       mov  ds,dx
  119.       lea  dx,buf-2     ; ds:dx - адрес buf[-2]
  120.       mov  ah,0Ah       ; ввод строки в буфер (включая Enter)
  121.       int  21h
  122.       call procnl       ; курсор на новую строку экрана
  123.       inc  cs:sizeb     ; в длине учесть Enter
  124.       mov  cs:posb,0    ; сколько символов уже считано из buf
  125.       pop  ds
  126.       pop  dx
  127.       pop  ax
  128.       ret
  129. readbuf endp
  130.  
  131. ;====================================
  132. ;  Очистка буфера ввода с клавиатуры
  133. ;   Обращение: call procflush
  134. ;   Параметров нет
  135. ;------------------------------------
  136. procflush proc far
  137.       push ax
  138.       mov cs:sizeb,0    ; очистка buf
  139.       mov cs:posb,0
  140.       mov ah,0Ch        ; очистка DOS-буфера
  141.       mov al,0          ; без допол. действий
  142.       int 21h
  143.       pop ax
  144.       ret
  145. procflush endp
  146.    
  147. ;==================================================================
  148. ;  Ввод символа пропуском или без пропуска Enter)
  149. ;   Обращение: call procinch
  150. ;   На входе:  al - Enter пропустить (0) или выдать как символ (1)
  151. ;   На выходе: al - введенный символ (ah не меняется)
  152. ;-----------------------------------------------------------------
  153. procinch proc far
  154.       push bx
  155. princh1:
  156.       mov  bl,cs:posb    ; номер последнего считанного символа
  157.       inc  bl            ; след. номер
  158.       cmp  bl,cs:sizeb   ; не последний символ буфера?
  159.       jb   princh2
  160.       jne  princh10      ; буфер не считан до конца?
  161.       cmp  al,0          ; считывать ли конец строки (Enter)?
  162.       jne  princh2
  163. princh10:
  164.       call readbuf       ; доввод в буфер
  165.       jmp  princh1       ; повторить
  166. princh2:
  167.       mov  cs:posb,bl    ;запомнить номер считываемого символа
  168.       mov  bh,0
  169.       mov  al,cs:buf[bx-1]   ;al:=символ
  170.       pop  bx
  171.       ret
  172. procinch endp
  173.  
  174. ;=================================================================
  175. ;  Ввод целого числа (со знаком и без) размером в слово
  176. ;   Обращение: call procinint
  177. ;   На входе:  нет
  178. ;   На выходе: ax - введенное число
  179. ;------------------------------------------------------------------
  180. procinint proc far
  181.       push bx
  182.       push cx
  183.       push dx
  184. ; пропуск пробелов и концов строк вначале
  185. prinint1:
  186.       mov al,0
  187.       call procinch     ; al - очер. символ пропуском Enter)
  188.       cmp al,' '        ; пробел?
  189.       je  prinint1
  190. ; проверка на знак
  191.       mov dx,0          ; dx - вводимое число
  192.       mov cx,0          ; ch=0 - нет цифры, cl=0 - плюс
  193.       cmp al,'+'
  194.       je  prinint2
  195.       cmp al,'-'
  196.       jne prinint3
  197.       mov cl,1          ; cl=1 - минус
  198. ; цикл по цифрам
  199. prinint2:
  200.       mov al,1
  201.       call procinch     ; al - очер. символ (Enter - символ)
  202. prinint3:               ; проверка на цифру
  203.       cmp al,'9'
  204.       ja  prinint4      ; >'9' ?
  205.       sub al,'0'
  206.       jb  prinint4      ; <'0' ?
  207.       mov ch,1          ; ch=1 - есть цифра
  208.       mov ah,0
  209.       mov bx,ax         ; bx - цифра как число
  210.       mov ax,dx         ; ax - предыд. число
  211.       mul cs:prten      ; *10
  212.       jc  provfl        ; >FFFFh (dx<>0) -> переполнение
  213.       add ax,bx         ; +цифра
  214.       jc  provfl
  215.       mov dx,ax         ; спасти число в dx
  216.       jmp prinint2      ; к след. символу
  217. ; кончились цифры (число в dx)
  218. prinint4:
  219.       mov ax,dx
  220.       cmp ch,1          ; были цифры?
  221.       jne prnodig
  222.       cmp cl,1          ; был минус?
  223.       jne prinint5
  224.       cmp ax,8000h      ; модуль отриц. числа > 8000h ?
  225.       ja  provfl
  226.       neg ax            ; взять с минусом
  227. prinint5:
  228.       pop dx            ; выход
  229.       pop cx
  230.       pop bx
  231.       ret
  232. prten dw 10
  233. ;---------- реакция на ошибки при вводе числа
  234. provfl:  lea cx,prmsgovfl   ; переполнение
  235.       jmp prerr
  236. prnodig: lea cx,prmsgnodig  ; нет цифр
  237. prerr: push cs          ; печать сообщения об ошибке
  238.       pop  ds           ; ds=cs
  239.       lea  dx,prmsg
  240.       mov  ah,9         ; outstr
  241.       int  21h
  242.       mov  dx,cx
  243.       mov  ah,9         ; outstr
  244.       int  21h
  245.       call procnl
  246.       mov  ah,4Ch       ; finish
  247.       int  21h
  248. prmsg      db 'Ошибка при вводе числа: ','$'
  249. prmsgovfl  db 'переполнение','$'
  250. prmsgnodig db 'нет цифры','$'
  251. procinint endp
  252. iocode ends
  253.    
  254.        end       ; конец модуля ioproc

Объяснение кода листинга программы

  1. Вывод на экран
    • procnl: процедура, которая переносит курсор на новую строку экрана
      • dx: регистр для операций с данными
      • ax: регистр для операций с данными
  2. Вывод целого числа на экран
    • procoutnum: процедура вывода целого числа со знаком или без знака
      • ax: выводимое число
      • dh: число со знаком (1) или без знака (0)
      • dl: ширина поля вывода (>=0)
  3. Ввод с клавиатуры
    • readbuf: вспомогательная процедура ввода строки символов в буфер buf
    • procflush: процедура для очистки буфера ввода с клавиатуры
    • procinch: процедура для ввода символа с пропуском или без пропуска Enter
      • al: Enter пропустить (0) или выдать как символ (1)
    • procinint: процедура для ввода целого числа (со знаком и без) размером в слово

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


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

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

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

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы