# recursive factorial

I got it to where I can display the number inputted. The code i have thus far will give me this. But, I need to add to it in order to verify that the number entered is between 1-8, and for what number 1-8 is entered, produces the factorial of that number. I am at a loss here. HELP! The following is what I have:

.model small
.stack 100h
.data
Prompt db 'Enter a number 1-8: \$'
msg2 db 10, 10, 13, 'Factorial is: \$'

.code
fact proc
mov ax, @data
mov ds,ax
mov dx,offset prompt
mov ah,9h
int 21h

mov ah, 01h; get character input
int 21h

mov ah, 0
sub ax, 30h; make it a number from ASCII char
push ax

call div10; proc to create the base 10

mov ah,9h
mov dx, offset msg2
int 21h

int 21h

fact endp

div10 proc
mov cx,0

divi10:

mov dx, 0
mov bx, 10
div bx
push dx
cmp ax, 0
jg divi10

disp10:

pop dx
mov ah, 02h
int 21h
loop disp10

ret; return after the call

div10 endp
end fact

• : I got it to where I can display the number inputted. The code i have thus far will give me this. But, I need to add to it in order to verify that the number entered is between 1-8, and for what number 1-8 is entered, produces the factorial of that number. I am at a loss here. HELP! The following is what I have:

like assembly, take your problem and reduce it to the smallest pieces. Once you get used to working on that level, writing in assembly is fun because you have such complete control over everything, not to mention the challenge of checking each step along the way!

Let's tackle the first problem: telling if a number inputted is between 1 and 8:

After you convert your number from ascii, check to see if it's between 1 and 8.

:
: mov ah, 01h; get character input
: int 21h
:
:
: mov ah, 0
: sub ax, 30h; make it a number from ASCII char
: push ax
:

you know AX (actually just AL) is your number. you need the CMP (compare) instruction here.

cmp al, 1 ; check low boundry- is the number 1?
jb do_over ; jb = jump if BELOW.

cmp al, 8 ; check upper boundry- is number 8?
ja do_over ; ja = jump if ABOVE

; if your code gets here, you know the value inputted is between 1 and 8 (inclusive)

Now you will also need to add the label "do_over" somewhere in your code. You could put it right before you input the character, or you could put it rigth before you print the message asking for input. Whatever you want to do.

There are other similar instructions like "jb" and "ja" such as "jl" and "jg" (jump if less and jump if greater) In this case, you want to use JB and JA instructions because you're dealing with an unsigned number. (ie, no negative values) It's easy to forget and use JL or JG instructions and then not realize that the CPU is checking the sign of a value as well as its value.

Ask yourself what steps are required to produce a factorial of a number, and see if you can write some very simple code to do whatever you need to do it. Don't write it in assembly if you don't want to, just break the steps down as much as possible and you'll (hopefully!) find that you can convert your logical steps into assembly code that compiles.

Of course, I'm having you do this because I'm not even sure what steps are involved with producing a factorial!
But once we get the steps down, the code will be a natural progression.

[soapbox time, apologies]

I assume this is a homework assigment? It's really too bad that teachers assign such god awful tasks as producing factorials or figuring out batting average for a baseball team. Who in their right mind would ever write that drivel in the first place, let alone do it in assembly?

I believe that the mindlessly horrid tasks that teachers assign students in programming classes only re-enforces the idea that assembly language is the most banal and opressively nit-picky language ever invented. Yes it has some tedious moments like checking user input from every possible angle to see if it's within bounds, but when viewed properly, assembly is the most beautiful of languages: Complete control over all the hardware done in logical steps that are perfectly in sync with the way the CPU itself runs. It's programming and engineering all rolled into one. It's elegance is in its simplicity.

ah, I better stop now before I get hurt.

-jeff!
• Yes, homework, and thank you. It is really making sense now.
:

• : Yes, homework, and thank you. It is really making sense now.
: :
:
:

Man, I'm sorry that you have to write such lame programs for homework!
I got my start in assembly by removing the doc check from DOS games, and it just grew from there. "Hey, if I can modify the outcome of this doc check on this game, what other kind of control can I have over a machine?" I was drunk with power after my 1st crack!

I should warn you that in the code snippet that I helped check to see if the range of input was correct, there is a bug:

----------
:
: mov ah, 01h; get character input
: int 21h
:
:
: mov ah, 0
: sub ax, 30h; make it a number from ASCII char
: push ax
:

you know AX (actually just AL) is your number. you need the CMP (compare) instruction here.

cmp al, 1 ; check low boundry- is the number 1?
jb do_over ; jb = jump if BELOW.

cmp al, 8 ; check upper boundry- is number 8?
ja do_over ; ja = jump if ABOVE

-----------

Do the PUSH AX after you do the cmp's otherwise you'll screw up the stack if the program jumps back to do_over. There's no point in saving the user's input if it was out of range, right?

best of luck.

-jeff!
• Saw that. Did something stupid though, and ran into a problem with that do_over call. Put it all after the number was input, including the label, and ran into an infinite loop. Took care of that, and everyting is running smoothly now!