4

So I'm trying to convert a string to a number so I can add another number to it later. here is what I have to far in my .text for the conversion. num2Entered is what the user entered. Num1plusNum2 is the label that I will eventually add to. They are both declared in the .bss section. Any help would be appreciated!

    mov ax, [num2Entered + 0]
    sub ax, '0'
    mov bx, WORD 1000
    mul bx
    mov [Num1plusNum2], ax

    mov ax, [num2Entered + 1]
    sub ax, '0'
    mov bx, WORD 100
    mul bx
    add [Num1plusNum2], ax

    mov ax, [num2Entered + 2]
    sub ax, '0'
    mov bx, WORD 10
    mul bx
    add [Num1plusNum2], ax

    mov ax, [num2Entered + 3]
    sub ax, '0'
    add [Num1plusNum2], ax
1

3 Answers 3

9

Each character is only a single byte, but you probably want to add it to a larger result. Might as well go for 32 bits... (can hobble your routine to 16 bits if you really want to)

mov edx, num3entered ; our string
atoi:
xor eax, eax ; zero a "result so far"
.top:
movzx ecx, byte [edx] ; get a character
inc edx ; ready for next one
cmp ecx, '0' ; valid?
jb .done
cmp ecx, '9'
ja .done
sub ecx, '0' ; "convert" character to number
imul eax, 10 ; multiply "result so far" by ten
add eax, ecx ; add in current digit
jmp .top ; until done
.done:
ret

That's off the top of my head and may have errors, but "something like that". It'll stop at the end of a zero-terminated string, or a linefeed-terminated string... or any invalid character (which you may not want). Modify to suit.

Sign up to request clarification or add additional context in comments.

Comments

4
or we can say:
"123"  -> starting from 1

1 + 0 * 10  = 1
2 + 1 * 10  = 12
3 + 12 * 10 = 123

This will match to atoi function as below:

atoi:

push    %ebx        # preserve working registers
push    %edx
push    %esi

mov $0, %eax        # initialize the accumulator
nxchr:
    mov $0, %ebx        # clear all the bits in EBX
    mov (%esi), %bl     # load next character in BL
    inc %esi            # and advance source index

    cmp $'0', %bl       # does character preceed '0'?
    jb  inval           # yes, it's not a numeral jb:jump below
    cmp $'9', %bl       # does character follow '9'?
    ja  inval           # yes, it's not a numeral ja:jump above

    sub $'0', %bl       # else convert numeral to int
    mull ten            # multiply accumulator by ten. %eax * 10
    add %ebx, %eax      # and then add the new integer
    jmp nxchr           # go back for another numeral

inval:
   pop  %esi            # recover saved registers
   pop  %edx
   pop  %ebx
   ret

Hope this will help.

1 Comment

imul $10, %eax would let you use EDX for something else, and be more efficient. Also, movzbl (%esi), %ebx is how you do a zero-extending byte load. The range-check can be done more efficiently; sub and cmp are the same operation, just not writing the result. Since you already do sub $'0', %bl later, you could just do that instead of the first cmp, and adjust the 2nd to check for it being less than or equal integer $9, not ASCII $'9'. Or use one unsigned compare, as in NASM Assembly convert input to integer?
2
"123"
 |||     val = 0
 |||______ val = val + ('3' - 48) * 10power0       [val now is 3]
 ||_______ val = 3   + ('2' - 48) * 10power1       [val now is 23] 
 |________ val = 23  + ('1' - 48) * 10power2       [val now is 123]

note: ascii of '1' means 49, '2' means 50 and so on

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.