0

I have made a program that takes a string as a input from user and then calculates its length and display it. But I am getting an error Segmentation fault (core dumped) when I run the program. My code is shown below

str_len:                    ;Procedure to calculate length of String
    xor rdx,rdx
    xor rcx,rcx             ;I want to store length in rcx
    mov rdx,[string]        ;string contains the input taken from the user
    mov rsi,rdx
    mov rcx,'0'             ;By default rcx will contain '0' decimal

up: cmp byte[rsi],0         ;Compare if end of string
    je str_o                ;If yes then jump to str_o

    inc rcx                 ;Increment rcx i.e., length
    inc rsi                 ;Point to next location of rdx i.e.,string
    jmp up                  ;Repeat till end of string

str_o:  mov rax,1           ;Print final length
        mov rdi,1
        mov rsi,rcx
        mov rdx,1
        syscall
ret

I can guarantee that rest of my program is correct. The error will be in the above part of the code. What is probably the error ?

Paras
  • 210
  • 3
  • 12
  • 2
    sys_write syscall writes strings, not numbers (or a single character in a register). You'll need to convert your number to a string and pass the buffers address (containing the converted number) to sys_write. In your case you'll have to move your value in `rcx` to a temporary buffer and then pass that buffer's address to sys_write. – Michael Petch Feb 06 '16 at 16:45
  • Thanks I will try that – Paras Feb 06 '16 at 16:49
  • I tried what you said but still same error – Paras Feb 06 '16 at 16:50
  • The other issue will be that the address of the string is being loaded incorrectly. `mov rdx,[string]` is moving the 8 bytes starting at the label string and moving them into the reigster. You want the address of `string`. – Michael Petch Feb 06 '16 at 16:56
  • I see someone has now made an answer that points that out although you might have to do it this way `lea rdx, [rel string]` where you have `mov rdx,[string]`. This forces the referencing of `string` using RIP relative addressing. – Michael Petch Feb 06 '16 at 16:56
  • Sorry mate but it didn't help. – Paras Feb 06 '16 at 17:13
  • We can't see your code, so we don;t know exactly what all the changes you made. – Michael Petch Feb 06 '16 at 17:14
  • 2
    _I can guarantee that rest of my program is correct._ if we got a dollar everytime we have heard that, we would all be rich :) – Jester Feb 06 '16 at 19:48

1 Answers1

2

The error is here:

mov rdx,[string] ; string contains the input taken from the user

You are loading RDX with the first 8 bytes of the string content and not the address of the string. So better use

lea rdx, string  ; LEA = Load Effective Address

Another problem is that your output routine tries to print a number that is not converted to ASCII with

mov rax,1      ; SYS_WRITE - Print final length
mov rdi,1      ; STDOUT handle
mov rsi,rcx    ; RSI should point to buffer
mov rdx,1      ; length of buffer - a value of one prints only one char
syscall

This doesn't work that way. You'd have to convert the qword number in RCX to an ASCII string before and then pass the address of this string in RSI. Search Stack Overflow for questions like this.

zx485
  • 28,498
  • 28
  • 50
  • 59
  • The problem with `lea rdx,string` is that it is giving an error `invalid combination of opcode and operands`. So I tried `lea rdx,[string]` but again the error `segmentation fault` – Paras Feb 06 '16 at 17:04
  • I have also converted the result into ASCII as `add byte[rcx],30h` and also used buffer to print it as `mov [strlen],rcx` but not getting the output. – Paras Feb 06 '16 at 17:06
  • @Paras: Well, no. Converting the number in RCX to a string is not that easy as adding a value of `30h` to CL. You try to use RCX as an address, too - which is not correct. [Here](http://stackoverflow.com/a/19312503/3857942) you'll find an algorithm in 32-bit assembly for doing this, which, of course, should be modified for 64-bit. – zx485 Feb 06 '16 at 17:16
  • 1
    @Paras: `lea rdx, [rel string]` is correct. (Or use the `DEFAULT REL` directive so you don't need the `rel` to get RIP-relative addressing). Learn to use a debugger so you can find what instruction is segfaulting. Then look at what register is being dereferenced, and check that it contains an address. Or at least tell us where the segfault is. – Peter Cordes Feb 06 '16 at 17:17