Смысл этого кода в том, чтобы продемонстрировать один из нескольких методов, которые можно использовать для возврата десятичного целого числа, представляющего количество цифр в строке, так как эта часть отсутствует в OP.Обычно после этого используется какой-то алгоритм преобразования, но я подумал, что было бы интересно посмотреть, как это можно сделать при разборе строки.
Поскольку многие примеры приложений DOS по сути являются не более чем плоской памятьюВ моделях я обойдусь без лишних вещей, таких как секции (.data, .const, .text) и использую RET , чтобы вернуться в командную строку, так как нас не очень заботит код возврата.Редко я резервирую место, как в COM файле, и все, что происходит, - это раздувает приложение.
Собран с использованием NASM name.asm -oname.com версия2.11.08
Протестировано с использованием DOSBOX 0.74
WRITE_STR equ 9
READ_STR equ 0xc0a ; Buffered input with initial flush
DOS equ 33
org 100H ; DOS 6.22 COM file
; ----------------------------------------------------------------------------
Begin:
; Every program should have some sort of prompting so operator has an idea
; of what is expected.
mov dx, Prompt
mov ah, WRITE_STR
int DOS
; Not absolutely required, but AH = 0CH & AL = 0AH accepts buffered input
; but assures there aren't any straggling characters as buffer pointed to by
; DX is flushed first.
mov dx, Users_Entry
mov ax, READ_STR
int DOS
; Setup pointer to string, count of characters entered and initial count
; of digit characters in string
mov si, dx ; Point to input buffer
inc si ; Bounce over maximum characters
xor ax, ax
push ax
lodsb ; Read # of characters entered
mov cx, ax ; Move to counter register for loop
; Of the four possible outcomes, each message must be preceded with
; double return & tab.
mov dx, PreAmb
mov ah, WRITE_STR
int DOS
; The reason AX is being used because a packed BCD value is going to be
; created on the fly, but for this to work DAA must be used and it only
; works on the accumulator.
pop ax ; Restore initial digits count
mov dx, Err00 ; By default, assume nothing was entered.
jcxz Finished ; Branch in buffer is empty
.NextChr:
mov bl, [si] ; Read first or next character
inc si ; Bump pointer
cmp bl, '0'
jb .notNum
cmp bl, '9'
ja .notNum
add al, 1
daa ; Bump counter and decimal adjust
.notNum:
loop .NextChr
mov dx, Msg01 ; Assume a single digit character.
cmp al, 1
jz Finished
mov dx, Msg00
or al, al
jz Finished ; No digit characters found
; Now we are going to replace the word "No" with the BCD value in AX
cld
mov di, dx
push ax
mov dx, di ; Needed to ultimately display string
; There is a good change the value is < 10, so initially we are going
; to convert to space.
shr ax, 4 ; Shift tens into low nibble
or al, ' '
cmp al, ' '
jz $ + 4 ; I
or al, 10000b ; Convert ot digit 1 - 9
stosb ; Write to destination string
pop ax
and ax, 1111b ; Mask out high nibble (tens)
or al, '0'
stosb ; Write units digit.
; Now the appropriate final message can be displayed appending modified
; PreAmb to it.
Finished:
call Show ; Display desired result string
mov dx, PreAmb + 1 ; Do one less line-feed
mov di, dx
mov byte [di+2], '$' ; Don't want to do TAB
Show:
mov ah, WRITE_STR
int DOS
ret ; Return to DOS or maybe DEBUG
; NOTE: alignment is for convenience sake so things can be identified a little
; more readily using hex dumps in DEBUG.
align 16
; ----------------------------------------------------------------------------
Prompt: db 27, '[2J', 10 ; VT100 emulation clears screen and sets
; cursor to 0:0
db ' Please enter alphanumeric string (max 48 chars)'
db 10, 10, ' --> $'
PreAmb: db 10, 10, 9, '$'
Err00: db '--> FAILED <-- NULL string$'
Msg00: db 'No digit characters were found$'
Msg01: db 'Only a single digit character found$'
align 8
Users_Entry: db 49 ; NOTE: change prompting text too.