2013-04-09 67 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