Linux NASM检测EOF

tMC*_*tMC 6 linux assembly stdin nasm eof

我正在尝试在linux上学习基础知识,我找不到一个很好的参考.NASM文档似乎假设您已经知道masm ...我在cmp(英特尔指令参考之外)的文档中找不到任何示例.

我编写了一个从stdin读取单个字节并将其写入stdout的程序.下面是我的修改,尝试在stdin上检测EOF并在达到EOF时退出.问题是它永远不会退出.我只是继续打印从stdin读取的最后一个char.问题是在我的EOF检测(cmp ecx, EOF)和/或我跳到_exit标签(je _exit)我认为.

我究竟做错了什么?

%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
Run Code Online (Sandbox Code Playgroud)

为了理智,我用这个C验证EOF是-1:

#include <stdio.h>
int main() { printf("%d\n", EOF); }
Run Code Online (Sandbox Code Playgroud)

Mr.*_*nce 6

您正在将缓冲区的地址与EOF(-1)进行比较,而不是存储在缓冲区中的字符.

话虽如此,read系统调用在达到文件结尾时不会返回EOF的值,但它返回零并且不会在缓冲区中粘贴任何内容(请参阅参考资料man 2 read).要识别文件结尾,只需检查eax调用后的值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
Run Code Online (Sandbox Code Playgroud)

如果您确实想要将字符与某个值进行正确比较,请使用:

cmp byte [buf], VALUE
Run Code Online (Sandbox Code Playgroud)

另外,我改名charbuf.char是基本的C数据类型,是变量名称的错误选择.

  • 我在意识到某些事情后更新了我的答案.但是,这是正确的,因为您将缓冲区的地址存储在ecx中,在这种情况下,存储在"0x80490c0"的内存中.`sys_read`调用读入的值存储在该内存位置.即使您更改缓冲区的内容,它在内存中的位置也保持不变.要取消引用指针并将其与另一个字节进行比较,请使用`cmp byte [buf],VALUE`. (2认同)