0
votes

I'm learning assmebler by myself at the moment and I finally managed to read input from the terminal and calculate with it.

I use sys_read for that and it works perfectly fine but when I use it the terminal acts like I pressed enter after runnning the program (one line with root@kali:~/ASM$). This does not happen when using scanf.

Here is my code:

sys_read  equ 3
sys_write equ 4
stdout    equ 1
stdin     equ 2

section .data
    prompt db "Enter two 1-digit numbers for an integer division.", 10, 0
    result db 10, "%i / %i = %i.", 10, 0

section .bss
    a resb 4
    b resb 4
    c resb 4

section .text
    extern printf
    global main

main:
    push ebp
    mov ebp, esp
    push ebx
    push esi
    push edi

    push prompt
    call printf

    mov eax, sys_read
    mov ebx, stdin
    mov ecx, a
    mov edx, 1
    int 80h

    sub dword [a], 0x30

    mov eax, sys_read
    mov ebx, stdin
    mov ecx, b
    mov edx, 1
    int 80h

    mov eax, sys_read
    mov ebx, stdin
    mov ecx, b
    mov edx, 1
    int 80h

    sub dword [b], 0x30

    mov dx, 0
    mov ax, [a]
    div dword [b]
    mov [c], ax
    push dword [c]
    push dword [b]
    push dword [a]
    push result
    call printf

    add esp, 40

    pop edi
    pop esi
    pop ebx
    mov esp, ebp
    pop ebp
    ret

And here is the output I get:

root@kali:~/ASM$ ./div
Enter two 1-digit numbers for an integer division.
1 1

1 / 1 = 1.
root@kali:~/ASM$ 
root@kali:~/ASM$

I don't understand why this extra line appears.

1
What is happening is that Linux console by default is usually set to Line Buffered mode. The characters remain in the buffer until processed. You do 3 reads of 1 byte each which consumes the 1 1 but that leaves the actual new line in the buffer. You don't do anything with it in your program so it gets processed by the shell after. You could flush stdin after reading the 3 character or change the last sys_read to read 2 characters instead of 1. That would consume the newline.Michael Petch
Thank you, that fixed it!cmdj13
No problem. One other observation is that stdin is file descriptor 0 and stdout is file descriptor 1. You seem to use the wrong values.Michael Petch
Hang on, you're running as root? But your prompt is using $ instead of the usual # to indicate UID=0? Experimenting with asm development is not a smart thing to do on a privileged account.Peter Cordes
I'm sorry to answer that late, but I only saw it today. Michael: The ones I use work fine, why should I change them? Peter: Do you know what Kali Linux is? You always are logged in as root.cmdj13

1 Answers

1
votes

Your result data contains an extra newline character (10) before the string to be printed:

result db 10, "%i / %i = %i.", 10, 0
          ^^

Removing this will remove the extra newline in the output.

You can remove the extra shell line by consuming more characters from stdin, either by flushing the buffer, or by reading more than three characters from the buffer. The newline that you press to enter the data will also be stored in the line's buffer, and, if not read by your code, will be read by the shell as an empty line. (i.e. it will exhibit the same behavior as the shell would if you just pressed enter in the shell without typing anything else.)

Also, I would advise using extended 32-bit registers for the math instead of 16-bit registers, since your variables are 32-bit.