From: patrick_woflian on
Hey Guys,
I have to make an assembly program that after the user enters either
'c' or 'f' will then be prompted for a number to be converted into
celcius or fahrenheit.. It is my first time making a program of this
sort and i have come up with the following code which works, but is
very basic. it simply outputs a message on screen saying 'enter....'
and i was just wondering for help on how to read the character entered
by the user to prompt the next message before calculations took place.
i have made the calculations aswell but haven't been able to use them
as of yet. I am using TextPad and a A86 compiler, on windows. Here is
my code:

JMP START

msg DB 'Please enter which you would like to change a number to, C or
F? ', 13,10,"$"
input DB ?
tempA DB ?

START:
LEA DX,msg
MOV AH, 9 ;print first message to screen
INT 21h
MOV AH,1
INT 21H
SUB AL,30H
SUB AH,AH

;Centigrade
CF: MOV AH,0



FAH PROC NEAR ;Fahrenheit procedure
SUB AL, 32D
MOV CL, 5D
MUL CL
MOV CL, 9D
DIV CL
RET
FAH ENDP


CENT PROC NEAR ;Celcius procedure
MOV CL, 9D
MUL CL
MOV CL,5D
DIV CL
SUB AL,32D
RET
CENT ENDP




FINISH:
MOV AH,4Ch ;exit program
INT 21h


Cheers for your help!
Steve

From: patrick_woflian on
I have added a bit of code in the last few minutes, a wee break
through.. well.. sort of. i can now enter 'C' to prompt the next
message which is to do with values.. i think i need to do an if
statement now, but im not sure at all. Heres the new code:

JMP START

msg DB 'Please enter which you would like to change a number to, C or
F? ', 13,10,"$"
prompt DB ' Please enter a number to be converted', 13,10,"$"
input DB ?
tempA DB ?
tempB DB ?

START:
LEA DX,msg
MOV AH, 9 ;print first message to screen
INT 21h
MOV AH,1
INT 21H
SUB AL,30H
SUB AH,AH
MOV tempA,AL

;Centigrade
CF: LEA DX,prompt
MOV AH, 9 ;print first message to screen
INT 21h
MOV AH,1
INT 21H
SUB AL,30H
SUB AH,AH
MOV tempB,AL



FAH PROC NEAR ;Fahrenheit procedure
SUB AL, 32D
MOV CL, 5D
MUL CL
MOV CL, 9D
DIV CL
RET
FAH ENDP


CENT PROC NEAR ;Celcius procedure
MOV CL, 9D
MUL CL
MOV CL,5D
DIV CL
SUB AL,32D
RET
CENT ENDP




FINISH:
MOV AH,4Ch ;exit program
INT 21h


Cheers again,
Steve

From: randyhyde@earthlink.net on

patrick_woflian wrote:
> Hey Guys,
> I have to make an assembly program that after the user enters either
> 'c' or 'f' will then be prompted for a number to be converted into
> celcius or fahrenheit..


As you're obviously working under DOS, you might want to take a look at
the "UCR Standard Library for 80x86 Assembly Language Programmers" as
this library contains lots of routines for numeric input and the like.

Normally, my first thought would have been "gee, you're not paying
attention in class, are you?" But given the number of posts to this
newsgroup (and others) on this very homework problem, I suspect that
the instructor has given you an assignment without realizing the
background material that is necessary.

In any case, you can find the UCR Standard Library here:

http://webster.cs.ucr.edu/AsmTools/MASM/MASMLibs.html

You might also want to check out "The Art of Assembly Language" at
http://webster.cs.ucr.edu
Cheers,
Randy Hyde

From: Evenbit on

patrick_woflian wrote:
> Hey Guys,

It seems that you haven't read Frank's post (understandable that it got
buried amoung the usual USENET noize) so I have taken the liberty of
reproducing it here:

NNTP-Posting-Date: Sat, 11 Mar 2006 21:36:05 -0600
Date: Sat, 11 Mar 2006 22:34:38 -0500
From: Frank Kotler <fbkot...(a)comcast.net>
Organization: N
User-Agent: Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7)
Gecko/20040618
X-Accept-Language: en-us, en
MIME-Version: 1.0
Newsgroups: alt.lang.asm
Subject: Re: Input/Output

patrick_woflian wrote:
> This is the code ive come up with so far:

Ah, code! Now we've got something we can help you with! Dos, good.
Notepad... tends to save your "myfile.asm" as "myfile.asm.txt"...
apparently you know how to fix that...

A86 is... okay for what it is. You'll soon want something that knows
about 386's n'stuff. You can *use* 32-bit stuff even in dos. Your
"little dos .com" file can be quite impressive! A86 is okay for now -
you may not have a choice - but, at your earliest convenience, get a
better assembler. Register A86, if you like it, and get A386...

The *good* thing about A86 is it means you've got D86. That's a nice
debugger, as I recall - been a *long* time since I used it. Seems to me

that the process to set up a "memory window" is a bit complex for a
beginner, but gives a nice range of display formats. Make D86 your
friend!

> JMP START
> VarA DB 4
> VarB DB 0
> Temp1 DB ?
> Temp2 DB ?
>
>
> MESSAGE: DB "Please select C or F", CR,LF,"$"
> NUMBER: DB "Please select number to be converted"

Missing '$'.

> ANSWER: DB "Answer is $"
>
>
> START:
> MOV DX, MESSAGE
>
> ---- This will output the message to the user,

Well, not quite yet, it won't.

> but i just wondered how
> to work on their answer?

You're getting ahead of yourself. In asm, we gotta do every stinkin'
thing, y'know! First finish up displaying the prompt!

mov ah, 9
int 021

(that's how A86 does hex, isn't it? You *do* want hex here! Int 21
decimal will *not* do what you want! I'm more used to "21h"...)

Then we can do some input... Santosh suggested int 21h/0Ah. That's a
good one. Requires a special buffer set up before you call it - first
byte is the maximum number of bytes to get (and is thus "safe", unlike
the vile, evil "gets()"! :) - second byte is where the OS will return
the number of bytes actually read - then you need more reserved space
for what the user types - at least as many bytes as you said in the
"max" byte! The buffer offset goes in dx for the interrupt, but to
process or print the text (it is *not* 0- or $-terminated! it'll end
with a CR), you want "offset buffer + 2".

Other OSen, Windows or Linux, don't have anything quite like that. You
*might* be better off to learn file I/O. To read/write from/to a disk
file, you have to open it first. But dos has already got files open to
read the keyboard, and write to the screen (and "stderr" - also the
screen, and I think dos opens "stdprn" and "stdaux" too). It really
isn't any more complicated to use:

mov ah, 3Fh
; hope x86 accepts that notation for hex...
mov bx, 0 ; or "xor bx, bx" "stdin"
mov cx, max_length
mov dx, offset buffer
int 21h

Now dos will read into the buffer - "max-length - 1" bytes. If the
pesky
user types more than we said, the "extra" just gets lost - it doesn't
overrun our buffer. The buffer is always terminated by a carriage
return
(0Dh), as I recall, so the useable input is "max - 1". Actual number of

bytes read (counting the CR, as I recall) is in ax (if error,
carry-flag
is set, and ax is the errror code). To simply write what we just
read...

jc someplace ; *really* should check for error!
mov cx, ax ; bytes to write
mov dx, offset buffer
mov bx, 1 ; "stdout"
mov ah, 40h
int 21h

That isn't too tough. And if you learn "open" and "close" - maybe
"lseek" - you'll have disk files. Linux puts the buffer in ecx, and the

length in edx, but is otherwise fairly similar. Windows pushes
parameters on the stack, but there are parallels. So you're halfway to
learning that, too!

For this particular simple program, you could input just a character at

a time. First, just get the 'C' or 'F' we asked for"

get_c_or_f:

mov ah, 8
int 21h

> i know i will need an if statement, say if
> user enters C

Okay. What if user enters 'c' instead of 'C'? What if it's neither 'C'
nor 'F'? We can "force" the input to either uppercase or lowercase,
might be "simpler" to check for each...

cmp al, 'c'
je do_c2f
cmp al, 'C'
je do_c2f
cmp al, 'f'
je do_f2c
cmp al, 'F'
je do_f2c

I might have gotten that backwards. It isn't entirely clear from your
prompt whats going to happen when I press C or F. You might want to
"improve" that. Anyway, if we get to here, the disobediant s.o.b. has
entered something other than C or F! You might want to consider
anything
else as "exit" (might want to provide an "exit" option here, so you can

"loop back and do another" instead of quitting after just one.Mention
it
in the prompt :) Or print an error message. Or ignore it and get
another
key until the stupid git *does* hit C or F. This is why I chose that
particular dos int - it doesn't "echo", so bad input won't mess up our
pretty display :)

jmp get_c_or_f

> then output message 'please enter number' and then that
> number needs to be converted into Centigrade..

Mmmm. I *did* get 'em backwards. Well, do the right thing.

> if F then output message
> 'please enter number' and then that number needs to be converted into
> Fahenheit..

Okay, these two have got a couple things in common. First, they print
the prompt. Then they get some input from the user by some means or
another. In any case, it'll be "text" and will have to be converted to
a
number. Then... you say you've got the conversions - two different ones

- so do them... whichever one. Then we're back to "same thing" again -
convert the "answer" back to text, and print it. Does this suggest
anything? Do you know how to write a subroutine?

> else output message 'failed'.

Okay. Do we wanna tell 'em why? Or just "bad, bad, bad"? There are a
couple of "gotcha"s... In an earlier message, you say "a number above
zero". Sounds like you don't want to handle negative numbers (don't
blame ya!). What if the user wants to convert 10 F to C? (damn shame
that the "degree sign" isn't an ascii character) We could change the
prompt... "above 32 if F" :) Maybe we *do* want to handle negative
numbers? You've allocated bytes for your variables - they'll hold
numbers from 0 to 255, or -127 to +127 if we're going that route.
Anything over 123 C is going to be a problem! Or over 52 C... Maybe we
better change the prompt to "between freezing and boiling"! :) You
could
increase the size of the variables to words. Not much harder - I don't
know what it'll do to your conversion calculations. That'll go 0 to
65535, or -32767 to +32767... well "absolute zero" becomes a problem -
-270-odd C, -460-odd F, I think?... "fail" there, too? That still won't

convert the temperature of the sun. Using 32-bit registers in 16-bit
code is perfectly possible - that'd get us +/- two billion and change -

but A86 doesn't know 'em. Doing 32-bit calculations is possible - much
like doing it on paper. And, like doing it on paper, you want to avoid
it if you can :) So figure out what range you want to handle...

I mentioned you could do all the input one character at a time...
Here's
a simple, get an "always positive" word, and return it in ax (untested
and from memory...)

get_ax:
xor bx, bx ; zero our "result"
get_ax_top:
mov ah, 8 ; get a character
int 21h

cmp al, 13 ; user hit "enter"?
je got_ax ; we done.

If it's not a valid decimal digit, ignore it and get another one.

cmp al, '0'
jb get_ax_loop
cmp al, '9'
ja get_ax_loop

So far, we haven't echoed the character. Since we've got a valid one,
print it now. Save it first, 'cause we're gonna trash ax!

push ax
mov ah, 2
mov dl, al
int 21h

Multiply our result so far by ten. If A86 knows the two and three
operand forms of imul... just "imul bx, 10". Strictly speaking, this is

for signed numbers, and in case A86 is "8086 only"(???), do it this
convoluted way...

mov ax, bx
mov bx, 10
mul bx
mov bx, ax

pop ax ; get our character back
and ax, 0Fh ; clear high bits - convert char->num
add bx, ax ; add to our result
jmp get_ax_loop
got_ax:
mov ax, bx
ret

It'll be a miracle if that actually works :) It could/should be
improved
a lot - we don't check for overflow, and we trash some registers that
really should be preserved, but it shows the general idea. If instead
of
"one character at a time", you get a string with int 21h/0Ah or int
21h/3Fh or whatever, you'll have to do much the thing with each
character in the string.

Then do your calculations - if what you've got doesn't expect the
number
to convert in ax, move it from ax to where it does expect it, or alter
the routine so it returns the number in the right register.

Here's one way to display the result (if it isn't in ax, put it in ax):

showax:
xor cx, cx
mov bx, 10
push_loop:
xor dx, dx
div bx
add dx, '0'
push dx
inc cx
test ax, ax
jnz push_loop
mov ah, 2
pop_loop:
pop dx
int 21h
loop pop_loop
ret

Again, that's untested and from memory...

Santosh is right that you need Ralf Brown's Interrupt List to do much
of
anything in dos. (and the "ports.lst" is useful outside of dos!)
There's
an "online" version here...

http://www.ctyme.com/rbrown.htm

Best,
Frank


And here is a collection of those bits-n-pieces into a program that you
can cut-n-paste:

;---------------
; cf.asm
;
; Code taken mainly from Frank's post.
;
; Assemble with:
;
; a86 cf.asm
;

code segment
org 100h
clear MACRO sub #1,#1 #EM
print MACRO
pusha
mov dx, offset #1
mov ah, 9
int 21h
popa
#EM
jmp start

msg: db 13, 10, "Please type 'C' or 'F': ", 13, 10, "$"
num: db 13, 10, 'Please enter a number: ', 13, 10, '$'
msgf2c: db 13, 10, 'Converting F to C.', 13, 10, '$'
msgc2f: db 13, 10, 'Converting C to F.'
CRLF: db 13, 10, '$'

start:

print msg

get_c_or_f:

mov ah, 8
int 21h
cmp al, 'c'
je do_f2c
cmp al, 'C'
je do_f2c
cmp al, 'f'
je do_c2f
cmp al, 'F'
je do_c2f
jmp get_c_or_f

do_f2c:

print msgf2c
jmp over

do_c2f:

print msgc2f

over:

print num

print CRLF
call get_ax

print CRLF
call showax

int 20h ; Exit back to DOS!

;--------------------------------
; Below here are our subroutines.
;

;/-------
; get_ax - gets a number from the user
; and places its value in AX.
;\-------

get_ax:

push bx
push dx
clear bx ; zero our "result"

get_ax_loop:
mov ah, 8 ; get a character
int 21h

cmp al, 13 ; user hit "enter"?
je got_ax ; we done.

cmp al, '0'
jb get_ax_loop
cmp al, '9'
ja get_ax_loop

push ax
mov ah, 2
mov dl, al
int 21h

mov ax, bx
mov bx, 10
mul bx
mov bx, ax

pop ax ; get our character back
and ax, 0Fh ; clear high bits - convert char->num
add bx, ax ; add to our result
jmp get_ax_loop
got_ax:
mov ax, bx
pop dx
pop bx
ret

;/-------
; showax - takes the value in AX and
; displays it to the screen.
;\-------

showax:

push bx
push cx
push dx
clear cx
mov bx, 10
push_loop:
clear dx
div bx
add dx, '0'
push dx
inc cx
test ax, ax
jnz push_loop
mov ah, 2
pop_loop:
pop dx
int 21h
loop pop_loop
pop dx
pop cx
pop bx
ret

end

Nathan.

From: patrick_woflian on
hey guys, i dont know which thread to blooming post too.. but here is
updated code, i have been told that i can assume that no errors will be
made on input (pretty stupid if you ask me) but there we go.. i have a
sub routine up to cmp the input and the calculate the integer input to
convert it.. however it is still not working, can any one see where ive
gone wrong? Heres the code:

JMP START

msg DB 'Please enter which you would like to change a number to, C or
F? ', 13,10,"$"
prompt DB ' Please enter a number to be converted', 13,10,"$"
answer DB 'The answer is ', 13,10,"$"
input DB ?
tempA DB ?
tempB DB ?


;sub routine
CMP AL, 'F'
CALL FAH
CMP AL, 'C'
CALL CENT


;enter C of F
START:
LEA DX,msg
MOV AH, 9 ;print first message to screen
INT 21h
MOV AH,1
INT 21H
MOV tempA,AL

;enter number
CF: LEA DX,prompt
MOV AH, 9 ;print second message to screen
INT 21h
MOV AH,1
INT 21H
SUB AL,30H
SUB AH,AH
MOV tempB,AL

FAH PROC ;Fahrenheit procedure
SUB AL, 32D
MOV CL, 5D
MUL CL
MOV CL, 9D
DIV CL
RET
FAH ENDP


CENT PROC ;Celcius procedure
MOV CL, 9D
MUL CL
MOV CL,5D
DIV CL
SUB AL,32D
RET
CENT ENDP

;the answer
LEA DX,answer
MOV AH, 9 ;show answer
INT 21h


FINISH:
MOV AH,4Ch ;exit program
INT 21h

Thank you
Steve

 | 
Pages: 1
Prev: "We Never Use Assembly Language"
Next: Survey