Incorrect result in custom assembly function (converting str to long) [duplicate]

Incorrect result in custom assembly function (converting str to long) [duplicate]
typescript
Ethan Jackson

I wanted to rewrite some functions from C to assembly in my project, one of them is converting a string to long long integer.

It looks like this: if, for example, the rdi register points to the address of a string containing the value "123\n", then this string should be converted to a long int with the value 123 ( currently in the best case it is converted to 1230, but now this is not the main problem, see below: )

I encountered a problem that my function gives an incorrect result on line 106: while debugging, I noticed that with the value of rсх == 2 and the function argument (rdi register) == 300, before multiplying rax by 10 (rbx == 10), the value of rax is fine: it is equal to 30, and after multiplication, for some reason, it becomes equal to 44.

Code part of declaration of func:

strtoint: mov ebx, 0xa ; множитель xor edx, edx ; сумма xor eax, eax ; хранение промежуточных результатов xor ecx, ecx jmp .L2 .L1: mov rax, rdx xor edx, edx mul rbx mov rdx, rax .L2: mov al, [rdi + rcx] cmp al, 10 je .L3 sub al, "0" add rdx, rax inc rcx jmp .L1 .L3: mov rax, rdx ret

In fact, this function declaration corresponds to the following example (in linux) in C language:

long strtoint(char* str) { int i = 0; long num; while (str[i] != 10) { num += str[i] - '0'; i++; num *= 10; } return num; }

The fact that the result is multiplied by 10 (like, if input was str "300" and the output will be long int with value '3000') in the end does not matter to me in this case, the correctness of the result itself is important to me, that is, the correct algorithm itself, the rest I will correct (rewrite the conditional jumps, reorganize the program according to suitable conditions).

Main code part:

global _start section .data nl: db 10, 0 str1: db "Enter your number: ", 0 str2: db "Your number: ", 0 section .text _start: push rbp mov rbp, rsp sub rsp, 0x400 mov byte [rbp-0x1], 0 mov rdi, str1 call printstr lea rdi, [rbp-0x400] mov rsi, 0x3ff call inputstr mov rdi, str2 call printstr lea rdi, [rbp-0x400] call strtoint mov rdi, rax call printint add rsp, 0x400 jmp exit

I don't understand the reason for such a result. I checked the rdx register after multiplication, before multiplication, although there is a reset to zero of rdx before each multiplication, nothing worked. I count on your help.

I can provide other function declarations if needed.

All what I found from answers on questions like mine, is:

text, which firstly is written in TASM syntax, and secondly don't answers on my question.

Answer

Sorry no review of the assembly.


C code is broken:

long strtoint(char* str) { int i = 0; long num; // Later code uses num uninitialized. // If ASM code omitted initialization, then this is BAD. // No support for a sign character like '-'. while (str[i] != 10) // C strings end with a '\0'. Any non-digit should end conversion. { num += str[i] - '0'; i++; num *= 10; // Final result is always a multiple of 10, overflow possible. } return num; }

A partially repaired version

long strtoint(const char* str) { size_t i = 0; long num = 0; while (str[i] >= '0' && str[i] <= '9') { num = num * 10 + (str[i] - '0'); i++; } return num; }

Related Articles