2013-04-09 86 views
1

我尝试使用系统调用在Ubuntu 11.04的NASM中实现cat>filename命令。我的程序已成功编译并运行成功(看起来如此)。但每当我试图启动cat filename命令它显示“没有这样的文件或目录”,但我看到该文件驻留在目录中。如果我尝试通过双击打开文件,则会显示“您没有打开文件所需的权限”。你能帮我找到我的代码中的错误吗?在NASM中实现cat> fileName命令

的代码如下:

section .data 
    msg:  dd "%d",10,0  
    msg1: db "cat>",0 
    length: equ $-msg1 
section .bss 
    a resb 100 
     len1 equ $-a 
    b resd 1 
    c resb 100  
    len2 equ $-c 
section .txt 
    global main 
main: 
    mov eax,4 ;;it will print cat> 
    mov ebx,1 
    mov ecx,msg1 
    mov edx,length 
    int 80h 
start: 
    mov eax,3 ;;it will take the file name as input 
    mov ebx,0 
    mov ecx,a 
    mov edx,len1 
    int 80h 

    mov eax,5 ;;it will create the file by giving owner read/write/exec permission 
    mov ebx,a 
    mov ecx,0100 
    mov edx,1c0h 
    int 80h 

    cmp eax,0 
    jge inputAndWrite 
    jmp errorSegment 

inputAndWrite: 
    mov [b],eax 

    mov eax,3 ;;take the input lines 
    mov ebx,0 
    mov ecx,c 
    mov edx,len2 
    int 80h 

    mov edx,eax ;;write the input lines in the file 
    mov eax,4 
    mov ebx,[b] 
    mov ecx,c 
    int 80h 

    jmp done 
errorSegment: 
    jmp done 
done: 
    mov eax, 1 
    xor ebx, ebx 
    int 80h 

P.S.上述代码通过采用RageD的建议进行重新编辑。然而,我创建的文件没有包含从“inputAndWrite”段输入的任何行。我正在寻找你的建议。

+0

您是否试图重新实现'cat'(即连接文件并打印到STDOUT),或者只是创建一个程序来复制像'cp'这样的文件?无论哪种情况,在用'cat filename'测试你的程序之前,你有没有检查过'哪个猫'?在Debian Wheezy中'哪个猫'输出'/ bin/cat'。 – nrz 2013-04-09 22:55:40

+0

@nrz:我试图实现:cat> file1。在启动这个命令之后,file1将包含从命令行给出的输入行。但是在运行我的程序之后,file1被创建,但是当我尝试打开文件时,它显示“您没有打开文件所需的权限”。 – sabu 2013-04-09 23:03:30

回答

3

您的权限的主要问题是权限在octal,并且您已将它们列在decimal中。您正在寻找基地8中的0700,而不是基数10.因此,您可以尝试使用1c0h0700十六进制的八进制数)。所以下面的代码修复应该解决您的权限问题:

;; This is file creation 
mov eax, 5 
mov ebx, a 
mov ecx, 01h ; Edited here for completeness - forgot to update this initially (see edit) 
mov edx, 1c0h 

供您参考,快速指南(也许有些过时,但在大多数情况下是正确的)用于Linux系统调用是使用Linux System Call Table。这对于记忆如何设置寄存器非常有用,等等。

另一个关键问题是写入文件。我想你在几个问题上有点困惑。首先,小心你的长度变量。大会是“在线”完成的,也就是说,当你计算len1时,你计算了a加上alen1之间的所有内容之间的距离。这就是说,你的长度值应该是这样的:

.section bss 
a resb 100 
len1 equ $ - a 
b resd 1 
c resb 100 
len2 equ $ - c 

这样做应该确保你有适当的读取(虽然它注意到你的缓冲区大小这里输入您要限制是很重要的)。

我发现的另一个至关重要的问题是您如何尝试写入文件。您翻转了系统调用寄存器。

;; Write to file 
mov edx, eax ;; Amount of data to write 
mov eax, 4 ;; Write syscall 
mov ebx, [b] ;; File descriptor to write out to (I think this is where you stored this, I don't remember exactly) 
mov ecx, c ;; Buffer to write out 

从这里,我会做一些更多的调整。首先,要很好地结束(没有段错误),我会建议简单地使用exit。除非在另一个程序中,否则ret可能无法正常工作(特别是如果这是独立的x86程序)。在退出系统调用的代码如下:

;; Exit 
mov eax, 1 ;; Exit is syscall 1 
xor ebx, ebx ;; This is the return value 
int 80h ;; Interrupt 

此外,对于清洁,我假设你正在输入一个换行缓冲。如果是这种情况,我会建议在文件名后去掉换行符。做到这一点的最简单方法是在最后一个字符(这将是新行)后简单地进行空终止。所以,在阅读输入文件名后,我将使类似这样的代码:

;; Null-terminate the last character - this assumes it directly follows the read call 
;; and so the contents of eax are the amount of bytes read 
mov ebx, eax ;; How many bytes read (or offset to current null-terminator) 
sub ebx, 1 ;; Offset in array to the last valid character 
add ebx, a ;; Add the memory address (i.e. in C this looks like a[OFFSET]) 
mov BYTE [ebx], 0 ;; Null-terminated 

最后,在大型项目有礼貌,当你完成关闭您的文件描述符。它可能没有必要在这里,因为你马上退出,但看起来是这样的:

;; Close fd 
mov eax, 6 ;; close() is syscall 6 
mov ebx, [b] ;; File descriptor to close 
int 80h 

编辑

对不起,我错过了写作问题。您正在打开价值为100的文件。你想要的是1O_RDWR(读写功能)。此外,您可能需要考虑仅使用sync系统调用(系统调用号码0x24不带参数)以确保缓冲区正确刷新;然而,在我的测试中,这是没有必要的,因为我认为,输入数据的换行应该在技术上做到这一点。所以正确打开文件的代码的更新位应该看起来像这样:

; Open file 
mov eax, 5 
mov ebx, a 
mov ecx, 01h 
mov edx, 1c0h 
int 80h 

希望这有助于。祝你好运!

+0

非常感谢RageD。你解释得像我坐在你面前,像老师一样。再次感谢 – sabu 2013-04-10 05:22:40

+0

@ nrz @ RageD:完成所有更改后,新创建的文件不包含从命令行给出的输入行。我重新编辑我的代码以供您考虑。 – sabu 2013-04-10 05:45:52

+0

@SaugataBose:我已经更新了我的回复,对不起!我错过了这个微妙的问题。祝你好运。 – RageD 2013-04-11 00:10:00