2017-08-10 64 views
0

對不起,我不知道該怎麼問這個問題,但讓我看看能不能把它畫出來。我有這個程序:地址是在它之後還是之前執行?

section .data 
    s1 db "nice",10,0 

section .text 
    global _start 

_start: 
    mov rax, s1 
    call _print 
    call _exit 


_print: 
    push rax 
    mov rbx, 0 
_printLoop: 
    inc rax 
    inc rbx 
    mov cl, [rax] 
    cmp cl, 0 
    jne _printLoop 

    mov rax, 1 
    mov rdi, 1 
    pop rsi 
    mov rdx, rbx 
    syscall 
    ret 

_exit: 
    mov rax, 60 
    mov rdi, 0 
    syscall 

其中有一個子例程_print將打印一些空終止的字符串與地址存儲在rax中。我的問題是,我假設,如果我有記憶的指針一些字符串(如S1),那麼它會是這個樣子:

rax 
s1 
| 
[n][i][c][e][\n][\0] 

所以,在我的腦海,我想檢查存儲在s1中以確保第一個字符(「nice」中的'n')不是空終止符。但這不是這個程序的工作原理。它增加兵營和RBX(RBX存儲計)和S1 + 1首先檢查,像這樣:

s1 rax 
| | 
[n][i][c][e][\n][\0] 

所以,我能想到的唯一解釋,就是S1指針或者,在一開始,分在分配給字符串的字節之前,如下所示:

s1 
| 
[][n][i][c][e][\n][\0] 

,或者當從中讀取時,它向後讀取,而不是向前讀取。但我不確定它是如何工作的。我希望我已經足夠清楚,有人爲我解決這個問題。謝謝。這個x86-64

+0

你能詳細說明嗎?它似乎不像第一個字符比較 – Mauricio

+0

因此,事實上,「n」沒有得到比較? – Mauricio

+0

好,所以算法只是假設第一個字符是好的。謝謝 – Mauricio

回答

1

只要字符串至少有一個字符,寫入的代碼的長度就是正確的。 (這是一個合理的假設,因爲打印沒有字符的字符串會是什麼意思,但不幸的是它不健壯。)

修復它以正確處理空字符串的一個簡單方法是:

_print: 
    mov rsi, rax 
    mov rbx, 0 

    cmp byte [rax], 0 
    jz _printSkip 

_printLoop: 
    inc rax 
    inc rbx 
    mov cl, [rax] 
    cmp cl, 0 
    jne _printLoop 

    mov rax, 1 
    mov rdi, 1 
    mov rdx, rbx 
    syscall 

_printSkip: 
    ret 

除了在循環之前爲空字符串添加檢查之外,我將其更改爲將指針直接放入rsi而不是堆棧中。通過不使用堆棧來節省rax,它可以避免在跳過系統調用的情況下需要堆棧清理。

0

在我的其他答案中,我儘可能地做了少量更改以清楚地顯示修復問題所需的更改。在這個答案中,我展示了我將如何寫它:

_print: 
    cmp byte [rax], 0 
    jz _printSkip 

    mov rsi, rax 
    xor edx, edx 
_printLoop: 
    inc edx 
    cmp byte [rsi+rdx], 0 
    jnz _printLoop 

    mov eax, 1 
    mov edi, 1 
    syscall 

_printSkip: 
    ret 
相關問題