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?