2012-11-07 66 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