3

I need to prompt to user a msg that tells him to write a number , then I store this number and do some operation on it After searching in INT 21h I found this :

INT 21h / AH=1 - read character from standard input, with echo, result is stored in AL.
if there is no character in the keyboard buffer, the function waits until any key is pressed. 

example:

    mov ah, 1
    int 21h

The main problem that this only reads one character and represent it as ASCII so If I need to write the number "357" I will read it as 3 , 5 , 7

and this is not my goal . any ideas ?

xsari3x
  • 442
  • 2
  • 12
  • 36
  • If you need to read three characters, you have to put the read-one-character call in a loop until you have the three characters you want. – Pete Wilson Oct 23 '11 at 18:47
  • @PeteWilson I need to read the whole number as a "whole" so I can do for example addition on it ...etc – xsari3x Oct 23 '11 at 19:05

2 Answers2

4

When you managed to get the user input, put the its pointer in ESI (ESI = address to the string)

.DATA
myNumber BYTE "12345",0        ;for test purpose I declare a string '12345'

Main Proc
    xor ebx,ebx                ;EBX = 0
    mov  esi,offset myNumber   ;ESI points to '12345'

loopme:

    lodsb                      ;load the first byte pointed by ESI in al

    cmp al,'0'                 ;check if it's an ascii number [0-9]
    jb noascii                 ;not ascii, exit
    cmp al,'9'                 ;check the if it's an ascii number [0-9]
    ja noascii                 ;not ascii, exit

    sub al,30h                 ;ascii '0' = 30h, ascii '1' = 31h ...etc.
    cbw                        ;byte to word
    cwd                        ;word to dword
    push eax
    mov eax,ebx                ;EBX will contain '12345' in hexadecimal
    mov ecx,10
    mul ecx                    ;AX=AX*10
    mov ebx,eax
    pop eax
    add ebx,eax
    jmp loopme                 ;continue until ESI points to a non-ascii [0-9] character
    noascii:
    ret                        ;EBX = 0x00003039 = 12345
Main EndP
龚元程
  • 417
  • 1
  • 5
  • 14
  • Use `imul ebx, eax, 10`, not that clumsy `push` / `mul` stuff. Also, use `movsx eax, [esi]` if that's what you want, or better just zero-extend, as in [NASM Assembly convert input to integer?](https://stackoverflow.com/a/49548057) – Peter Cordes Apr 06 '20 at 11:13
1

Once you've got the string you have to convert it to number. The problem is, you have to code your own procedure to do that. This is the one I usually use (written in C though):

int strToNum(char *s) {
    int len = strlen(s), res = 0, mul = 0;
    char *ptr = s + len;

    while(ptr >= s)
        res += (*ptr-- - '0') * (int)pow(10.0, mul++);

    return res;
}

Here's the explanation. First of all, *ptr-- - '0' gets the integer representation of a number (so that '9' - '0' = 9, then it decremenst ptr so that it points to the previous char. Once we know that number, we have to raise it to a power of 10. For example, suppose the input is '357', what the code does is:

('7' - '0' = 7) * 10 ^ 0 =   7 +
('5' - '0' = 5) * 10 ^ 1 =  50 +
('3' - '0' = 3) * 10 ^ 2 = 300 = 
---------------------------------
                           357
BlackBear
  • 22,411
  • 10
  • 48
  • 86
  • 1
    how to do this in assembly :) ? – xsari3x Oct 23 '11 at 19:20
  • @xsari3x: Just translate the code to assembly ;) The most difficult part is the pow() function which you have to code by yourself. If you want hex numbers, though, you can do it by a simple shift left. – BlackBear Oct 23 '11 at 19:24
  • 1
    This algorithm doesn't translate easily into asm. `res = res * 10 + (digit - '0')` is more efficient and easy to implement. See [NASM Assembly convert input to integer?](https://stackoverflow.com/a/49548057) for x86 asm that does it. – Peter Cordes Apr 06 '20 at 11:11