We don't really get "numbers" from the keyboard, we get characters. Well, we do get numbers - the ascii codes for the characters... the ascii code for the character '1' is not 1. This is why we have to "convert" from string to number... and back, when we want to display a number. Typing "man ascii" should get you an ascii chart. As you can see, the ascii code for '1' is (skip the pesky octal) 49 decimal or 0x31 hex. Fortunately, the codes for '0' through '9' are contiguous (This is not so in all systems of encoding characters, I'm told! These systems have mostly been abandoned. Wonder why?). You don't really need to remember the numbers, "sub al, '0'" will convert from character to number, and "add dl, '0'" from number to character, and the '0' makes the code somewhat "self-documenting" compared to "sub al, 060q" or so...
Simple enough for a single digit. Multi-digit numbers have to be handled one at a time. Converting string->number, the general idea is: make sure we've got a(nother) valid decimal (or other) digit, multiply the "result so far" (which should begin with zero, obviously) by ten, add in the new digit - as a number, not a character - and go back for more. A string entered from the keyboard will end with a linefeed (ascii 10). When you find that, you're done. Up to you what you want to do if you encounter invalid characters before that. Easiest thing - what C does - is to treat any invalid character as the end of the string, and whatever you've got so far is the number. But you could holler "A NUMBER, Idiot!" or "'!@#$' is not a number I can understand. Please try again.", or whatever... You may also want to think about overflow. Easiest thing is to just let it "roll over" and use the result, modulo 32 bits. This is "correct", but possibly not what the user expects. You may want to detect it and complain "5000000000 won't fit into 32 bits. Please try again." (or "Not so big, Idiot!") Limiting the number of characters the user can enter is a possible way around this, too.
Converting number->string, so we can print it, is probably going to involve the "div" instruction. There are other - faster - ways to do it, but "div" is easy. It does have a "gotcha" that often bites newbies...
mov ebx, 10
div ebx
That will divide edx:eax (that is, edx * 4G + eax) by ten, leaving the quotient in eax and the remainder in edx. If the result won't fit in eax, it causes an exception. Since the number we're dividing will presumably fit in eax, we forget about edx, but the CPU does not forget! We want edx to be zero, and since the "div" instruction itself alters edx, we're going to have to zero it before the "div", every time!
After the "div", the remainder in edx is the digit we're looking for. We get 'em in the "wrong" order, though. We can stuff 'em in the buffer starting at the end, and working forward, or we could "push" 'em on the stack in the order we get 'em, and "pop" 'em off in the right order to print. A recursive implementation is cute. Don't forget to add '0' somewhere along the line, to convert the digit to a character!
In between, you'll need the "add" instruction. I don't think you'll have any trouble figuring that out. Remember "add eax, [first_number]", not "add eax, first_number"! This is another place where you might encounter an overflow of 32 bits, if you want to do something about it.
Don't forget to exit cleanly!
Just a thought... if you "can not figure out anything till now", you might want to tackle this in smaller steps...
Best,
Frank