2012-11-07 64 views
0

我被困在一個實踐問題,我需要一個整數讀,把它加1,並打印出結果。關於這個問題:linux nasm assembly print all numbers from zero to 100,槍手用戶提到dwtoa。我假設這是一個可調用函數。那麼這個dwtoa函數是什麼?如果它實際上是一個可調用的函數,我可以在哪裏獲得它(通過獲取我的意思是如何在我的代碼中實現它?)?Linux的NASM彙編dwtoa

在此先感謝。

+0

http://www.dreamincode.net/forums/topic/202395-masm-adding-numbers/ –

+0

當我嘗試使用'nasm -f elf -g -F stabs'進行編譯時,它會顯示'error :符號dwtoa undefined'。那麼這個位於nasm的'dwtoa'在哪裏? – Progrmr

+0

http://forum.nasm.us/index.php?topic=1042.0 –

回答

2

嗯,啊,你必須把它寫...或借用一個有人在已經寫好。後者更容易(C庫具有這樣的功能,並且很容易從asm調用),但前者更「有趣」。 (如果你喜歡那種事 - 哎,有些人做填字遊戲)

div指令是很慢的。有一個更好的方法來實現它的基礎上乘以互惠和「後乘」。這很複雜。我們將等待div。 :)

div ebx

如果我們安排了我們的號碼,說1234,在ebxeax和10,我們現在有eax 123和4 edxebx保持不變)。其實,我們會想在divedx有0 ...

xor edx, edx

div ebx

如你所知,我們可以在4號轉換爲字符「4」通過增​​加字符'0'(或48小數或30h)。現在我們有一些我們可以打印的東西了!但我們還沒有準備好打印它 - 我們正在倒數字。有幾種方法可以解決這個問題。我認爲最簡單的方法是在正確的順序上將push'堆棧和pop'關閉。另一種方法是繼續前進,並將em放在緩衝區中,最後做一個「字符串反轉」。另一種方法是從緩衝區的「結尾​​」開始,向前移動(在每個字符之後將索引遞減到緩衝區,而不是遞增)。這可能意味着當數字用完時,您不在緩衝區的開頭。我們可以利用這個優勢 - 如果您打算在列中打印他們,則右對齊的數字看起來不錯。如果你覺得這看起來不錯(我不知道),你也可以填充前導零(字符'0',而不是數字0)。

在任何情況下,我們有「4」捲走安全。再次環回div(首先使edx爲零!)。現在我們在eax中有12個,在edx中有3個。對3做些什麼,然後再回到div。 1在eax和2在edx。同樣,和eax爲零(edx爲1) - 在這一點上,我們就大功告成了!如果我們將eax與9比較,我們可以跳過最後的div--如果它較少,我們可以從al而不是dl得到我們的最終(首先打印)數字。更簡單的做法,每次都以同樣的方式...

; mov eax, the number 
; mov edi, the buffer (at least resb 10, please) 
; call dwtoa 
; mov edx, eax ; count 
; mov ecx, buffer 
; print it 

dwtoa: 
    xor ecx, ecx ; for a counter 
    mov ebx, 10 
pushloop: 
    xor edx, edx ; or mov edx, 0 
    div ebx 
    add edx, '0' 
    push edx 
    inc ecx ; count it 
    test eax, eax ; or cmp eax, 0 
    jnz pushloop 
    mov eax, ecx ; we'll return the count in eax 
poploop: 
    pop edx 
    mov [edi], dl 
    inc edi 
    loop poploop 
    ret 

這是關閉我的頭頂(不剪切和粘貼),並可能有錯誤。這是相當馬虎 - 垃圾寄存器,C想保留 - 不會返回一個零終止的字符串,因爲C想...但我們不使用C,所以我們不在乎! :)

隨意提高它自己的口味,或嘗試不同的方法。

除非你有一個,否則你會想要一個「atoi」(或「atodw」使用相同的命名約定)將用戶輸入的文本轉換爲數字。同樣的想法,但我們從字符中減去'0',將「迄今爲止的結果」乘以10,並添加新的數字......直到完成。

;------------------- 
; atoi - converts string to (unsigned!) integer 
; expects: buffer in edx 
; returns: number in eax 
atoi: 
    xor eax, eax  ; clear "result" 
.top: 
    movzx ecx, byte [edx] 
    inc edx 

    cmp ecx, byte 0 
    jz .done 
    cmp ecx, byte 10 
    jz .done 

    cmp ecx, byte '0' 
    jb .invalid 
    cmp ecx, byte '9' 
    ja .invalid 

    ; we have a valid character - multiply 
    ; result-so-far by 10, subtract '0' 
    ; from the character to convert it to 
    ; a number, and add it to result. 

    lea eax, [eax + eax * 4] 
    lea eax, [eax * 2 + ecx - '0'] 

    jmp short .top 
.invalid: 
    stc 
.done: 
    ret 
;-------------- 

那個被剪貼的「應該」工作。它也可以得到改善。使用「有趣」的方式乘以10並添加轉換爲數字的新字符。在這一點上,你的程序的「工作」包括: add eax, 1 無論如何,應該給你一些工作。玩的開心! :)

+0

非常感謝弗蘭克。非常全面。 – Progrmr