-1

I want to write a program which returns the string you write. But it always prints it without the first character. Also, it doesn't return anything past the first space.

Example:

IN: test
OUT: est

Code:

extern printf, scanf, exit
global main

section .text
main:
    push rbp
                            ;input of string
    mov rdi, format
    mov rsi, string
    mov rax, 0
    call scanf

                            ;output of string
    mov rdi, format_out
    mov rsi, qword [string]
    mov rax, 0
    call printf
_exit:                        ;end of program
    pop rbp
    call exit

section .data
  format     db "%s", 0
  string     db 0
  format_out db "You wrote: %s", 0

I noticed that if I change string db 0 to string db", it shows an error, but the program works correctly, printing the entire sentence to the first space. Unfortunately I don't have any clue what to do with that info. Thanks for the answer.

zx485
  • 28,498
  • 28
  • 50
  • 59
Zumalo
  • 3
  • 2
  • I guess `string` is the variable where you store the string entered by the user. How many chars do you expect the user to enter? What is the size of variable `string`? – Jose Manuel Abarca Rodríguez Nov 17 '16 at 21:59
  • Well I don't know. Let''s say that 20 is the max number of characters. What do I do now? – Zumalo Nov 17 '16 at 22:00
  • 3
    Then you should allocate more than 1 byte for the string, enough for your 20 max – Michael Petch Nov 17 '16 at 22:01
  • 2
    I don't know this syntax but why do `mov rsi, string` and `mov rsi, qword [string]` look different? The calls should be the same. – melpomene Nov 17 '16 at 22:06
  • Well I tried 'string dd 0' but this isn't the way to go :/ – Zumalo Nov 17 '16 at 22:06
  • 3
    Zumalo, your string is too small, it's one byte. You need something like `string times 21 db 0`. – Jose Manuel Abarca Rodríguez Nov 17 '16 at 22:10
  • Why with the exact same code I now get Segmentation fault? – Zumalo Nov 17 '16 at 22:15
  • Restart computer and try again. – Jose Manuel Abarca Rodríguez Nov 17 '16 at 22:16
  • I restarted, but it's still the same. "Segmentatnion fault (core dumped)" – Zumalo Nov 17 '16 at 22:30
  • Check first part of this answer (does apply to 32b too): http://stackoverflow.com/questions/40575898/how-to-use-strings-in-emu8086/40580889#40580889 .. Also you didn't even notice that not only it does print it without first character, but the `"You wrote: "` is completely missing :) (as it's overwritten by the user input). If you would put this into debugger, you would see the `format_out` string is damaged (upon memory inspection just ahead of `printf` call). – Ped7g Nov 18 '16 at 12:43

1 Answers1

2

printf("%s", ...) takes a pointer arg, but you're passing it the first 8 bytes of the contents of your string. Use mov rsi, string to get a mov-immediate instead of mov rsi, [string] (which is a load).

(Or to save 2 code bytes, mov esi, string since static addresses are guaranteed to fit in 32 bits in the default code model.)


As pointed out in comments, your static buffer is too small. Since your format string has no size limit, you need an infinite-size buffer to avoid any risk of a long input line overflowing it.

But let's pretend that a 1024B buffer is safe enough. Or better, use %1023s so it is guaranteed to be enough. We don't want 1024B of zeros in our executable; that would be silly. So we should instead reserve 1024B in the BSS:

section .rodata
  format:     db "%1023s", 0         # actually set a size limit, leaving room for the \0
  format_out: db "You wrote: %s", 0

section .bss
  string:     resb 1024              # RESERVE 1024 bytes.  Only works in .bss

There's no reason to omit the : after label names on data, and good reason not to.

Community
  • 1
  • 1
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847