|
Prev: "We Never Use Assembly Language"
Next: Survey
From: patrick_woflian on 14 Mar 2006 14:19 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 14 Mar 2006 14:27 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 14 Mar 2006 15:01 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 14 Mar 2006 19:41 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 15 Mar 2006 09:15 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 |