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?