Skip to content
Advertisement

Convert from ascii to integer in AT&T Assembly

How can I convert from ascii to integer?

    data

asd: 
    .int 32

.text

.globl _start

_start:

    movl $4, %eax
    movl $1, %ebx
    movl $1,(asd)
    add $48,(asd)
    movl $asd, %ecx
    movl $4, %edx
    int $0x80

    # Exit the program
    movl $1, %eax
    movl $0, %ebx
    int $0x80

The code is writing an ascii value, and I think that if I can add 48 to value. I can write, but I can’t print, a two-stage number “for example 53 or 156”. How can I print?

Advertisement

Answer

It’s usually best to think about a high level language version first. If the number has n digits and is stored in array a, then we’d want:

char *p = a;
unsigned val = 0;
while (n > 0) {
  n--;
  val = 10 * val + (*p++ - '0');
}

So let’s say %esi is p above %eax is val, and %ecx is n. Translate line by line to keep it as simplistic and literal as possible:

  movl $n, %ecx
  movl $a, %esi
  xorl %eax, %eax     # val = 0
eval_while_cond:
  testl %ecx, %ecx    # if (n <= 0) 
  jle done            #   goto done
  subl $1, %ecx       # n--
  movl %eax, %ebx     # tmp1 = val
  imul $10, %ebx      # tmp1 = 10 * tmp1
  movzbl (%esi), %eax # tmp2 = *p
  addl $1, %esi       # p++
  subl $'0, %eax      # tmp2 = tmp2 - '0'
  addl %eax, %ebx     # val = tmp2 + tmp1
  jmp eval_while_cond
done:
  # result is now in %eax

Note this is just a general methodology for getting functional assembly language. This isn’t optimized in any way. The tricks needed to get optimal performance are a whole other topic.

The other options is to use a compiler (e.g. https://godbolt.org/z/WzGYjePzx) with light optimization like -O1, -Og, or -Os to get somewhat-readable asm (although in this case they use not-totally-obvious tricks with LEA to multiply by 10 and subtract '0' (48), or they make a mess with weird loop conditions.) See also How to remove “noise” from GCC/clang assembly output?

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement