2013-03-16 55 views
5

所以我有大部分的代碼工作,但我不知道如何處理輸入句子是未知長度的事實。我是裝配新手,這有點令人困惑。如何處理x86 ASM中未知長度的輸入?

(現在我把它設置爲如果長度被稱爲是三個字符,但顯然我需要改變。)

.data  
input_msg: .ascii "Enter a random sentence: " 
input_msg_len: .long 25 
input_str: .ascii "???" # 3rd should get newline 
count:  .long 0 
newline: .long 10  

.text    
.global _start   
_start:    

# prompt for input 
    mov $4, %eax # prompt for input 
    mov $1, %ebx 
    mov $input_msg, %ecx 
    mov input_msg_len, %edx 
    int $0x80 
# get input 
    mov $3, %eax # 3 to request "read" 
    mov $0, %ebx # 0 is "console" (keyboard) 
    mov $input_str, %ecx # input buffer addr 
    mov $3, %edx # number of symbols typed in 
    int $0x80  # Go do the service! 

again1: 
    mov $input_str, %ecx  
    add count, %ecx # count is offset from input_str beginning 

    mov $4, %eax # to write 
    mov $1, %ebx # to console display 
    mov $1, %edx # 1 byte to write 
    int $0x80 # Do it! 

    push %ecx  # push onto stack 

    incl count # increment count 

    cmp $3, count # compare lengths 
    jnz again1  # jmp again if not 0 (no difference) 

    mov $0, %edi # use edi as loop counter 

    mov $4, %eax # print out msg 
    mov $1, %ebx # etc. 
    mov $1, %edx # length 
    int $0x80  # OS, serve! 

again2:  
    pop %ecx  

    mov $4, %eax # print out msg 
    mov $1, %ebx # etc. 
    mov $1, %edx # length 
    int $0x80  # OS, serve!   

    inc %edi # increment edi 
    cmp count, %edi # compare lengths 
    jnz again2 # jmp again if not 0 (no difference) 

# print newline 
    mov $4, %eax # print out msg 
    mov $1, %ebx # etc. 
    mov $newline, %ecx # addr 
    mov $1, %edx # length 
    int $0x80  # OS, serve! 
# exit 
    mov $1, %eax # exit 
    int $0x80  # OS, serve!  

基本上,我想知道的是我怎麼讓代碼適用於任何句子,而不僅僅是一個3個字符?

+0

空終止字符串。或者你需要在某處存儲長度。 – nhahtdh 2013-03-16 04:33:45

+1

什麼是中斷$ 80?我認爲這是ROM基本保留的。在任何人都可以幫忙之前,你必須告訴你的環境編程。 – Gene 2013-03-16 04:42:25

+0

@Gene Int 80h由類Unix系統用於系統調用。它有點像MS-DOS/Windows下的Int 21h。 – mjv 2013-03-16 04:45:01

回答

1

您只需爲input_str分配一個較長的緩衝區,並讀取在讀取系統調用後在eax中找到的有效讀入的文本量。

換句話說,你需要在最大長度決定你會接受和代碼更改爲類似如下:
注:這是確定分配短字符串這樣,靜態,當然如果你需要一個大緩衝區(比如說從文件中獲取數據),你可以改爲動態分配緩衝區)。再次,對於鍵盤輸入132可能是足夠的。

... 
input_str: db 132 dup(?) # 132 bytes buffer for input string 
input_str_len: .long  # length of the string effectively read from user 
... 
# get input 
    mov $3, %eax # 3 to request "read" 
    mov $0, %ebx # 0 is "console" (keyboard) 
    mov $input_str, %ecx # input buffer addr 
    mov $131, %edx # _Max_ number of bytes accepted in input_str 
    int $0x80  # Go do the service! 

    move %eax, $input_str_len # save nb of bytes effectively read 
... 
    #you can then use input_str_len to control when to exit processing loop etc. 
+0

我該怎麼做呢?如果我不知道這句話有多長時間,我能做多久? – Cat 2013-03-16 05:01:25

+0

我無法獲得「db 132 dup(?)」部分的工作,但它確實幫助我實現瞭如何計算字節數,所以謝謝! – Cat 2013-03-16 23:33:50

+0

noob問題,英特爾語法中表示的'mov%rax,$ input_str_len'?當我編寫'mov input_str_len,rax'時,我得到消息_「操作碼和操作數的無效組合_」 – akst 2016-07-27 13:14:16

0

嗯...你可以做%ebx = 0,這是你原來的「破」 sys_brk - 保存它。再次將4k的倍數添加到該值和sys_brk。讓你的sys_read進入該緩衝區。如果你讀完4k(在sys_read之後的%eax),再添加一些到你當前的「break」和sys_brk,然後再讀一些...直到完成。這「應該」給你在一個連續的緩衝區中的一切...

只是決定一些「最大」,不要讓他們進入任何更多的更容易哎呀!你可能想要「沖洗緩衝區」。如您所知,sys_read(從鍵盤)將不會返回,直到它看到一個換行符(0xA)。如果討厭的用戶輸入了多於%edx個字符,則其餘部分保留在OS的緩衝區中。你可以在你的3字節緩衝區代碼中看到它。輸入「abcls」。我想你會發現退出後,你的shell提示符會讀取「ls」,並給你一個目錄列表。沒問題,但它可能是「rm」或有害的東西!當您的sys_read返回時,如果%eax小於%edx,則表示完成。如果%eax = %edx(它不會更多),如果緩衝區中的最後一個字符是LF(0xA),則表示完成。如果沒有,sys_read放入一個虛擬緩衝區,直到獲得該LF。這個複雜的代碼了很多,但它的「安全」 ...

我可以嘗試在NASM語法的例子,但我不認爲我最好的嘗試AT &的... :)

+0

對不起,我對你描述的內容有點困惑(我的教授沒有解釋任何代碼真的代表了什麼)。我的意思是通過做出最大值來得到你的意思,但我認爲我們不應該有最大值。然後再次說明我要做什麼的唯一的描述是「這需要在一個循環中重複讀取單個字符,並將它推到內存棧上,直到按下」回車「鍵(換行符)爲止。循環,一個計數器(可以使用edi寄存器)記錄到目前爲止輸入的字母數。「我不太確定他的意思。 – Cat 2013-03-16 20:12:59

+0

我得到的LF(0xA)是「輸入」換行符。雖然這給我一個錯誤說「分段錯誤(核心轉儲)」。 – Cat 2013-03-16 20:42:17