AT&T-读取文件

时间:2018-11-24 15:43:16

标签: assembly att

我正在尝试(至少)读取文件的第一行。我正在使用syscalls打开和关闭文件,但似乎从文件读取内容时遇到了问题,因为结果只是一些未知的符号。

helm way

.data name: .string "temp.txt" fd: .byte 0 buf: .string "0" len: .long 512 .text .globl main .type main, @function main: # open file movl $5, %eax # sys_open movl $name, %ebx movl $0, %ecx # access: read-only movl $0777, %edx # read, write and execute by all int $0x80 # get file descriptor movl %eax, fd # read from file movl $3, %eax # sys_read movl $fd, %ebx movl $buf, %ecx movl $len, %edx int $0x80 # close file movl $6, %eax # sys_close movl $name, %ebx int $0x80 # print movl $4, %eax movl $1, %ebx movl $fd,%ecx movl $len, %edx int $0x80 # exit(0) movl $1, %eax movl $0, %ebx int $0x80 .size main, . - main 一样编译并运行gcc code.s -o code

1 个答案:

答案 0 :(得分:2)

有三个错误:

首先,将eax存储到fd就像fd的长度为4字节,但实际上只有1字节的长度。然后,将fd的地址放入ebx中,而不是从fd加载的值中。这给出了一些指向系统调用的随机指针,该指针当然是无效的文件描述符。

请注意,添加适当的错误处理至少可以避免第二个问题。


此外,正如Wumpus Q. Wumbley所说,您不应将文件描述符存储在单个字节中,因为其值可能会超过255。要解决这两个问题,请首先通过分配fd的大小来使其为4字节.int中的空格:

fd: .int 0

这立即解决了第一个问题。要解决第二个问题,请从ebx而不是fd加载$fd

mov fd, %ebx

最终的错误位于您执行movl $fd,%ecxmovl $len, %edx的“打印”块中。这等效于C,例如write(1, &fd, &len)。 (再次使用len的 address 作为长度,而不是从内存中加载)。并且您可能希望传递buf的地址(用于读取文件数据的地址),而不是传递存储整数(非ASCII)的fd的地址。因此,您需要write(1, buf, len),而不是write(1, &fd, len)

或者更好,如果不是错误代码,则应使用返回值read作为write的长度。您不想write()填充字节。但是,如果这样做,则可以使len为汇编时常量,而不是将其存储在内存中。使用.equ使汇编器在汇编时计算缓冲区长度,因此可以使用mov $len, %edx


请注意,在每个系统调用之后,您应该检查系统调用是否成功。您可以通过检查结果是否为负(严格来说是负,并且其绝对值小于4096)来实现。如果是,则发生错误,并且错误代码为否定结果。如果您处理了所有错误,则很容易看到程序在哪里以及为什么失败。

您还可以使用strace实用程序来跟踪程序执行的系统调用,并解码args。