Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux NASM detect EOF

I'm trying to learn the basics asm on linux and I can't find a very good reference. The NASM docs seem to assume you already know masm... I found no examples in the documentation of the cmp (outside the Intel instruction reference).

I'd written a program that reads a single byte from stdin and writes it to stdout. Below is my modification to try to detect EOF on stdin and exit when EOF is reached. The issue is it never exits. I just keeps printing the last char read from stdin. The issue is either in my EOF detection (cmp ecx, EOF) and/or my jump to the _exit label (je _exit) I think.

What am I doing wrong?

%define EOF     -1

section .bss
        char:   resb    1

section .text
        global  _start

_exit:
        mov     eax,    1       ; exit
        mov     ebx,    0       ; exit status
        int     80h

_start:
        mov     eax,    3       ; sys_read
        mov     ebx,    0       ; stdin
        mov     ecx,    char    ; buffer
        cmp     ecx,    EOF     ; EOF?
        je      _exit
        mov     edx,    1       ; read byte count
        int     80h

        mov     eax,    4       ; sys_write
        mov     ebx,    1       ; stdout
        mov     ecx,    char    ; buffer
        mov     edx,    1       ; write byte count
        int     80h

        jmp     _start

For the sake of sanity, I verified EOF is -1 with this C:

#include <stdio.h>
int main() { printf("%d\n", EOF); }
like image 842
tMC Avatar asked Feb 23 '12 16:02

tMC


1 Answers

You are comparing the address of the buffer to EOF (-1) instead of the character stored in the buffer.

Having said that, the read system call does not return the value of EOF when end of file is reached, but it returns zero and doesn't stick anything in the buffer (see man 2 read). To identify end of file, just check the value of eax after the call to read:

section .bss
    buf:   resb    1

section .text
    global  _start

_exit:
    mov     eax,    1       ; exit
    mov     ebx,    0       ; exit status
    int     80h

_start:
    mov     eax,    3       ; sys_read
    mov     ebx,    0       ; stdin
    mov     ecx,    buf    ; buffer
    mov     edx,    1       ; read byte count
    int     80h

    cmp     eax, 0
    je      _exit

    mov     eax,    4       ; sys_write
    mov     ebx,    1       ; stdout
    mov     ecx,    buf    ; buffer
    mov     edx,    1       ; write byte count
    int     80h

    jmp     _start

If you did want to properly compare the character to some value, use:

cmp byte [buf], VALUE

Also, I renamed char to buf. char is a basic C data type and a bad choice for a variable name.

like image 153
Mr. Shickadance Avatar answered Sep 24 '22 07:09

Mr. Shickadance