【问题标题】:Linux NASM detect EOFLinux NASM 检测 EOF
【发布时间】:2012-03-14 02:40:47
【问题描述】:

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

我编写了一个程序,它从标准输入读取单个字节并将其写入标准输出。以下是我尝试在标准输入上检测 EOF 并在达到 EOF 时退出的修改。问题是它永远不会退出。我只是不断打印从标准输入读取的最后一个字符。我认为问题出在我的 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

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

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

【问题讨论】:

  • 我不熟悉 NASM,但是char 是指向单个字符的指针吗?看起来您可能正在将字符的指针地址与 EOF 值进行比较。如果是这种情况,您需要取消引用指针然后进行比较。 readwrite 系统调用将指向缓冲区的指针作为参数,而不是单个字符。另外,我会将 char 重命名为基本 C 类型名称以外的名称。

标签: linux assembly stdin nasm eof


【解决方案1】:

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

话虽如此,read 系统调用在到达文件末尾时不会返回 EOF 的值,但它会返回零并且不会在缓冲区中粘贴任何内容(请参阅man 2 read)。要识别文件结尾,只需在调用read 后检查eax 的值:

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

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

cmp byte [buf], VALUE

另外,我将char 重命名为bufchar 是一种基本的 C 数据类型,是变量名的错误选择。

【讨论】:

  • 我尝试通过gdb 单步执行程序,ecx 中的内容似乎从未改变。我似乎保持不变(0x80490c0
  • 我在意识到一些事情后更新了我的答案。但是,这是正确的,因为您将缓冲区的地址存储在 ecx 中,在这种情况下,该地址存储在内存中的 0x80490c0 中。 sys_read 调用读取的值存储在该内存位置。即使您更改了缓冲区的内容,它在内存中的位置仍然保持不变。要取消引用指针并将其与另一个字节进行比较,请使用cmp byte [buf], VALUE
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
相关资源
最近更新 更多