6
\$\begingroup\$

I am working on a project for class, and it works as required by the rubric, though I am wondering if there is a slightly better way to implement a few things. I was docked a few points for an unnecessary mov in another project.

Problem 1:

"If—else (34 points): Write a program that asks the user to enter a single digit. If that digit is less 5, you will state so and you will add 5 to it and store it in a variable; if the digit is greater than 5, you will state so and then subtract 5 from it and store it in a variable; if the digit is 5, you will add 3 to it and state so and store it in a variable."

org 100h   
mov dx, offset start   ;move start of string address 'start' into dx
mov ah, 09h   
int 21h                ;print the string stored at DS:DX
mov ah, 01h            ;function for getting keyboard input
int 21h
sub al, 30h            ;subtract 30h to store our number as hexadecimal
mov bl, al             ;copying data to BL as the following commands manipulate the data
                       ;at AL. 
cmp bl, 5              ;BL = AL
jz ifZero              ;jump to ifZero if BL = 5
jl ifLess              ;jump to isLess if BL < 5
jg ifGreater           ;jump to ifGreater if BL > 5

ifZero:                ;direct console output function
mov ah, 06h            
mov dl, 0Ah
int 21h
mov dl, 0Dh
int 21h                ;print newline and character return
add bl, 03h            ;add 3 to BL, BL = 8
mov temp, bl           
mov dx, offset eq      ;move start of string address 'eq' into dx
mov ah, 09h
int 21h                ;print string
jmp exit               ;unconditional jump to end program

ifLess:                ;direct console output function
mov ah, 06h
mov dl, 0aH
int 21h
mov dl, 0Dh
int 21h                ;print newline and character return
add bl, 05h            ;add 5 to BL
mov temp, bl           
mov dx, offset less    ;move start of string address 'less' into dx
mov ah, 09h
int 21h                ;print string
jmp exit               ;unconditional jump to end program

ifGreater: 
mov ah, 06h            
mov dl, 0ah
int 21h
mov dl, 0dh
int 21h                ;print newline and character return
sub bl, 05h            ;subtract 5 from BL
mov temp, bl
mov dx, offset great   ;move starting address of string 'great' into dx
mov ah, 09h
int 21h                ;print string
jmp exit               ;unconditional jump to end program


exit:
ret

temp db ? 
start db "Please enter a number: $"
less db "Less than 5... adding 5 $"
great db "Greater than 5... subtracting 5 $"
eq db "Equal to 5... adding 3 $"

Problem 3:

Counter-controlled loop. The program will ask the user to enter a character and then it will display that character with a label five times

For example:

Enter a character: A

You entered: A

org 100h
mov cx, 05h             ;counter controlled loop, start as 5

LabelLoop:
mov dx, offset prompt   ;move string offset to dx
mov ah, 09h             ;function for printing string from dx
int 21h
mov ah, 01h             ;function to read character from keyboard
int 21h    
mov bl, al              ;preserving character read by copying to BL
                        ;as register data for AL will be changing
                        ;due to various functions
mov ah, 06h             ;function for direct console output
mov dl, 0ah
int 21h
mov dl, 0dh             ;these just make the text appear on a new
                    ;line
int 21h
mov dx, offset output   ;move the memory offset of output to dx
mov ah, 09h             ;printing another string
int 21h
mov ah, 02h             ;function to write a character to console
                        ;gets the value from DL
mov dl, bl                  ;so we copy BL to DL and print it
int 21h
jmp newLine             ;we unconditionally jump to the newLine
                        ;label and print a new line for the program
                        ;to run again

newLine:
mov ah, 06h
mov dl, 0ah
int 21h
mov dl, 0dh
int 21h
loop LabelLoop         ;we jump to LabelLoop and CX = CX - 1

mov dx, offset goodbye
mov ah, 09h
int 21h

ret

prompt db 'Enter a character: $'
output db 'You entered: $'
goodbye db 'Good bye!$'

I realize that AL = DL after:

mov ah, 06h
mov dl, 0ah
int 21h       ;AL = DL after execution

The version of the program that prints everything on its own line is worth extra points, so I opted to do that. When printing a character to console it gets its data from DL, but if I have to print a newline before that character, that data in AL is gone. Is sending that data to BL necessary? Is there a better option?

\$\endgroup\$
3
\$\begingroup\$

Write a program that asks the user to enter a single digit

This is where your program has its first error. You trust the user at the keyboard to actually input a digit, but your program should make sure it indeed got a digit!

InputAgain:
 mov dx, offset start   ;move start of string address 'start' into dx
 mov ah, 09h   
 int 21h                ;print the string stored at DS:DX
 mov ah, 01h            ;function for getting keyboard input
 int 21h
 cmp al, '0'
 jb InputAgain
 cmp al, '9'
 ja InputAgain
 sub al, 30h            ;subtract 30h to store our number as hexadecimal

The solution I've presented above will work out nicer if you add a single CR code to the message at start.

start db 13,"Please enter a number: $"

cmp bl, 5              ;BL = AL
jz ifZero              ;jump to ifZero if BL = 5
jl ifLess              ;jump to isLess if BL < 5
jg ifGreater           ;jump to ifGreater if BL > 5
ifZero:

The first improvement you should do is making use of the possibility to fall-through in the code. Don't use jz ifZero but rather fall through as equality is the only state that remains after jl and jg. Also ifEqual would be a more correct name for this state.

cmp bl, 5              ;BL = AL
jl ifLess              ;jump to isLess if BL < 5
jg ifGreater           ;jump to ifGreater if BL > 5
ifEqual:

A second optimization will be to get rid of all of those direct console outputs for CR and LF. You should incorporate these in the messages that you will print. Doing so will also remove the need to copy AL to BL using mov bl, al (you specifically asked this):

less  db 13,10,"Less than 5... adding 5 $"
great db 13,10,"Greater than 5... subtracting 5 $"
eq    db 13,10,"Equal to 5... adding 3 $"

Do observe that I wrote 13,10 and not 10,13. On the DOS platform convention dictates the use of CRLF=13,10. This might not seem too important to you but recently I came across a question on Stack Overflow where someone suffered a malfunctioning emulator precisely because of this!


  • Here's another opportunity to fall through:

    jmp exit               ;unconditional jump to end program
    exit:
    
  • Yet another such opportunity:

    jmp newLine             ;we unconditionally jump to the newLine
    newLine:
    

Your second program can benefit from these advices too.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.