2

I'm trying to make this program in assembly. It should just convert a string to a decimal

int main (int argc, char **argv)
{
    int result = 0; 
    char *c = argv[1];  
    while(*c != 0)
    { 
        result *= 10;           
        result += (*c - 48);
        c++;    
    }
return result;
}

but without getting argv from the stack... so I wrote a little code in asm that I think should do this but it does not work.

Can anyone point me to what I'm doing wrong? I commented the code so you will know what I think is going on, please correct me with anything.

section .bss
        buf resb 8  ; define an array of 8 uninitialised bytes
section .text

global _start
_start:
    mov rax, 3  ; system call number (sys_read)
    xor rbx, rbx    ; file descriptor 0 (stdin)
    mov rcx, buf    ; buffer to store data
    mov rdx, 8  ; Lenght of buffer
    int 0x80

    xor rax,rax ; rax = 0
    mov rbx, buf    ; rbx = &buf
    xor rcx, rcx    

StrToDec:
        mov cl, [rbx]   ; cl = *rbx 
        cmp rcx, 0      ; check for nul THIS IS WRONG
        cmp rcx, 10     ; we have to check for NL ascii code 
        je end          ; if rcx == 0 goto end
        imul rax, 10    ; rax *= 10
        sub rcx, 48     ; rcx -= 48 (48 is acii for '0')
        add rax, rcx    ; rax += rcx
        inc rbx         ; rbx++
        jmp StrToDec

end:
    mov rbx, rax    ; rbx = rax
    mov rax, 1      ; rax = 1
    int 0x80

When i run this program and type 100 for example and then type echo $? to the terminal it should print 100

Thanks.

11
  • What results are you getting? Commented Aug 1, 2011 at 17:58
  • What is "does not work"? Commented Aug 1, 2011 at 17:59
  • When i type 100 it returns 194, when i type 10 it returns 62 Commented Aug 1, 2011 at 18:03
  • Can you give a couple more examples? What happens when you type 543 or 1000? Commented Aug 1, 2011 at 18:11
  • 1
    related: What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code? Commented Mar 29, 2018 at 2:44

2 Answers 2

2
    mov rcx, [rbx]  ; rcx = *rbx 

That's wrong, it loads eight bytes from the buffer. You want to load only 1. Use mov cl,[rbx] or movzx ecx, byte [rbx]

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

1 Comment

I changed the above line to what you said but it still wont work returns exactly the same wrong results
0

FIXED:

I found out what was wrong with the program =D

First of all you need to check for value 10 so

cmp rcx, 0      ; check for nul 

is wrong because were looking for the new line ascii code not a null

cmp rcx, 10      ; check for NL

is right, I don't think it works if your getting the args from the stack, when getting args from stack you should check for 0.

Second: For numbers bigger than 255, echo $? would give me wrong results, but that's ok because echo $? can only show numbers up to 255, so even tho echo may show a wrong number the register rbx holds the right value.

I debugged it and it works fine now.

2 Comments

Or more generally, check for a non-digit character to stop the loop! Unless you don't mind "123xyz\n" turning into 1*10^5 + 2*10^4 + 3*10^3 + ('x'-'0')*10^2 + ('y'-'0')*10 + ('z'-'0') or something. Use movzx ecx, byte [rbx] / sub ecx, '0' / cmp ecx, 9 / ja .non_digit to convert from ASCII to integer and range-check all in one.
NASM Assembly convert input to integer? has working 64-bit code that stops at the first non-digit.

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.