1

I have the following code:

section .data
    ;scans
    scan_epsilon:       db  "%*7s%*1s%lf", 0
    scan_order:         db  10,"%*5s%*1s%i", 0
    scan_coeff:         db  10,"%*5s%i%*1s%lf%lf\n", 0
    scan_initial:       db  10,"initial = %lf %lf", 0

    print_epsilon:      db  "epsilon = %lf", 10, 0
    print_order:        db  "order = %i", 10, 0
    print_complex:      db  "%lf + %lfi", 10, 0

SECTION .bss
    epsilon:        resq 1
    order:          resq 1
    initial:        resq 1
    arr_size:       resq 1
    poly_real:      resq 1
    poly_img:       resq 1
    loop_counter:   resq 1
    coeff_pos:      resq 1
    temp:           resq 2

section .text
    extern printf
    extern scanf
    extern malloc
    extern free

    global _start

_start:
    ;;epsilon
    mov     rdi, scan_epsilon
    mov     rsi, epsilon
    mov     rax, 0
    call    scanf

    mov     rdi, print_epsilon
    movsd   xmm0, qword[epsilon]
    mov     rax, 1
    call    printf

    ;order
    mov     rdi, scan_order
    mov     rsi, order
    mov     rax, 0
    call    scanf

    mov     rdi, print_order
    mov     rsi, qword[order]
    mov     rax, 1
    call    printf

    mov     r10, qword[order]
    mov     qword[arr_size], r10
    add     qword[arr_size], 1
    ;allocating memory for polyinomial
    pushad
    mov     rdi, qword[arr_size]
    call    malloc
    mov     qword[poly_real], rax

    mov     rdi, qword[arr_size]
    call    malloc
    mov     qword[poly_img], rax
    popad

    ;initializing the loop counter
    mov     qword[loop_counter], 0

    .coeff_loop:
        mov     r10, qword[arr_size]
        cmp     r10, qword[loop_counter]
        je      .continue

        ;reading the coeff
        mov     rsi, scan_coeff
        mov     rdi, coeff_pos
        mov     rdx, temp
        mov     rcx, temp + 8
        mov     rax, 0
        call    scanf

        mov     rdi, print_double
        movsd   xmm0, [temp]
        mov     rax, 1
        call    printf

        ;calculating the position of the given coeff
        mov     rax, qword[coeff_pos]
        mov     rbx, 8
        mul     rbx

        ;putting the coeff at coeff_pos at it's coresponding position
        mov     r10, qword[temp]
        mov     qword[poly_real + rax], r10
        mov     r10, qword[temp + 8]
        mov     qword[poly_img + rax], r10

        add     qword[loop_counter], 1
        jmp     .coeff_loop

    .continue:
    ;initial
    mov     rdi, scan_initial
    mov     rsi, initial        ;pointer to the real part of the initial number
    mov     rdx, initial + 8    ;pointer to rhe imaganary part of the initial number
    mov     rax, 0
    call    scanf

    mov     rdi, print_complex
    movsd   xmm0, [initial]
    movsd   xmm1, [initial + 8]
    mov     rax, 2
    call    printf

    ;freeing the allocating memory
    mov     rdi, qword[poly_real]
    call    free
    mov     rdi, qword[poly_img]
    call    free

    mov     rax, 60             ;exit
    syscall

The input should look something like this:

epsilon = 2

order = 1

coeff 0 = 1.1 2.1

coeff 1 = -1.1 2.1

initial = 1.1 1.1

But after i read the order the program exit. When i tried to see if i am entering the loop (by printing something in the loop) i found out that i am getting into it but scanf does not scanning for any coeff's values.

I am out of ideas why this could happens.

Snirka
  • 602
  • 1
  • 5
  • 19
  • 1
    Which part of your code is supposed to read the `'\n'` at the end of the first line of input? – melpomene Apr 21 '18 at 18:17
  • You don't seem to be checking `scanf`'s return value at all. – melpomene Apr 21 '18 at 18:21
  • ain't '\n or '10' before '0' at the end helped. When i tried to print the return value of scanf (i printed rax value) i got 0, i assume that this is the value that i putted in before calling scanf so i didn't get ant negative number which i guess mean that no error occured – Snirka Apr 21 '18 at 19:23
  • You need a *leading* space in the 2nd format string to skip a newline left after the previous `scanf` finished its conversions. Trailing whitespace in the format string would mean `scanf` doesn't return until it sees a non-whitespace character (which it doesn't consume), so you'd have the same problem as someone yesterday doing the same assignment: [scanf run twice instead of one time at assembly x86\_64](//stackoverflow.com/q/49923312) – Peter Cordes Apr 21 '18 at 19:55
  • @Snirka You need to read the manual for `scanf`. It returns the number of items successfully scanned, so 0 means it failed. – melpomene Apr 21 '18 at 20:06
  • @PeterCordes i used this site: https://www.tutorialspoint.com/c_standard_library/c_function_scanf.htm to get the idea of scanf, but i saw in your [other](https://stackoverflow.com/questions/5240789/scanf-leaves-the-new-line-char-in-the-buffer) post more informative [manual](http://pubs.opengroup.org/onlinepubs/9699919799/functions/scanf.html) that explained it better. I thought i understood what you mean with the whitespace but even if i lead the second format with space it didn't work. – Snirka Apr 22 '18 at 08:27
  • @PeterCordes i tried to write it in C: scanf("%*5s%*1s%i", &order); double poly[order + 1][2]; for (int i = 0 ; i <= order ; i++){ int pos; scanf("%*5s%i", &pos); scanf("%*1s%lf%lf", &poly[pos][0], &poly[pos][1]); } and it worked, i don't seem to understand why my assembly is different from this. – Snirka Apr 22 '18 at 08:29
  • The first sentence of the linked duplicate explains the different: The `scanf()` function **removes whitespace automatically before trying to parse conversions** other than characters. So `"%*5s..."` is equivalent to `" %*5s..."`, and consumes the newline left from the last conversion. Unlike `"order..."`. [Reading string from input with space character?](//stackoverflow.com/q/6282198) suggests using a `"%*c"` at the *end* of a format to consume the newline, but that seems hacky unless you're using it with a format that really does always grab whole lines (like there) – Peter Cordes Apr 22 '18 at 09:11
  • You could of course use those working format strings in asm, but it is a good idea to understand why things work. – Peter Cordes Apr 22 '18 at 09:12
  • BTW, why are you telling scanf to only convert a 32-bit signed integer, when your asm reserves a 64-bit qword for `order`, and you're using that width? Allocating it in the BSS means the upper bytes are zero, so it works for positive `order` but fails for negative (e.g. `order = -1` will give you `order = 0x00000000ffffffff`, because you're effectively zero-extending instead of sign-extending.) I'd just use `resd` and `dword` operand size, like `r10d`. Or actually, pick a register that `malloc` isn't allowed to clobber, like `ebx`. – Peter Cordes Apr 22 '18 at 09:17
  • Wait a minute, your code won't even assemble! `pushad` is only valid in 32-bit mode, and `pushaq` doesn't exit (x86-64 dropped `pusha` instead of extending it to push all 16 registers). Always copy/paste real code that you know actually does what you say it does. You might have more bugs than the first problem I dup-closed your question for. Use a debugger to single step. Or if you need more help, update your code to what you *actually* have. – Peter Cordes Apr 22 '18 at 09:21
  • @PeterCordes about the pushad and the popad i tried to make the code more readalbe so i didn't put things that i thought are irrelevant. The pushad and popad are macros that i wrote. – Snirka Apr 22 '18 at 09:32
  • Then you named them wrong, the `d` stands for dword as opposed to `pushaw` to push all the 16-bit regs. You want `pushaq`. And you could have solved that by just commenting those lines to say they were macros. (all-caps is often a good idea for macro names, too.) Anyway, go read [mcve] to learn it's important. – Peter Cordes Apr 22 '18 at 09:36
  • Anyway, are your scanfs working in asm now? Presumably you have other bugs, or else I was wrong about putting a leading space being enough to solve it. – Peter Cordes Apr 22 '18 at 09:39
  • @PeterCordes, i have updated the code above. i dont know why but only in the loop the scanf does not work, i put 10 at the begging of every format. All other input's get scaned except the coeff – Snirka Apr 23 '18 at 10:24
  • How did you check that it's `scanf` that "doesn't work"? What *does* happen? Does it return 0 (no conversions), indicating that it doesn't match what's in the buffer? If so, what *is* in the `stdin` buffer? Maybe call `fgets` from inside GDB to find out? Or put a block of code that runs `fgets` into your program, and use GDB to `jump` there when your loop gets stuck and you want it to run. – Peter Cordes Apr 23 '18 at 10:28
  • You could also try using `ltrace` to trace library function calls. – Peter Cordes Apr 23 '18 at 10:28
  • @PeterCordes what happend is the program required me to enter epsilon then order but when it got to the coeff's it was like it jumped over them and didn't require me to enter anything. In the loop of the coeff's i tried to print coeff_pos (which need to be the index of the coeff) but because the program didn't ask me to enter anything for the coeff's i got 0 printed order + 1 times. after the loop the program asked me to enter initial as it should be and printed it correctly. – Snirka Apr 23 '18 at 10:39
  • You have a literal backslash + `n` at the end of your `coeff` format. `ltrace` would have shown you that. NASM only processes C-style escapes inside backquotes, not double quotes. Also, whitespace at the *end* of a format string is not what you want anyway, so a `,10` at the end wouldn't be good either. – Peter Cordes Apr 23 '18 at 11:14

0 Answers0