简体   繁体   English

Linux nasm汇编dwtoa

[英]linux nasm assembly dwtoa

I am stuck on a practice problem where I need to read in an integer, add 1 to it and print out the result. 我遇到了一个实际问题,我需要读取一个整数,将其加1并打印出结果。 On this question: linux nasm assembly print all numbers from zero to 100 , user Gunner mentioned dwtoa. 关于这个问题: linux nasm程序集打印从零到100的所有数字 ,用户Gunner提到了dwtoa。 I'm assuming that that is a callable function. 我假设这是一个可调用的函数。 So what is this dwtoa function? 那么,这个dwtoa函数是什么? And if it is in fact a callable function, where can I get it (by get I mean how can I implement it in my code?)? 如果它实际上是一个可调用的函数,那么我在哪里可以得到它(我的意思是我该如何在我的代码中实现它?)?

Thanks in advance. 提前致谢。

Well, ya gotta write it... or borrow one somebody's already written. 好吧,你得写...或借用别人已经写好的东西。 The latter is easier (the C library has functions like this, and it's easy to call from asm), but the former is more "fun". 后者更容易(C库具有这样的功能,并且很容易从asm调用),但是前者更“有趣”。 (if you like that kind of thing - hey, some people do crossword puzzles) (如果您喜欢这种东西-嘿,有些人会填字游戏)

The div instruction is very slow. div指令非常慢。 There's a better way to do it based on multiplying by the reciprocal and "back multiplying". 有一种更好的方法是基于乘以倒数和“反向乘积”。 It's quite complicated. 这很复杂。 We'll wait for div . 我们将等待div :) :)

div ebx

If we had arranged to have our number, say 1234, in eax and 10 in ebx , we would now have 123 in eax and 4 in edx ( ebx remains unchanged). 如果我们安排在eax数字,例如1234,在ebx 10,则现在eax中将使用123, edx 4( ebx保持不变)。 Actually, we'd want to have 0 in edx before the div ... 实际上,我们想在div之前在edx设置0 ...

xor edx, edx

div ebx

As you know, we can convert the number 4 to the character '4' by adding the character '0' (or 48 decimal or 30h). 如您所知,我们可以通过添加字符“ 0”(或48个十进制或30h)将数字4转换为字符“ 4”。 Now we've got something we can print! 现在我们有了可以打印的东西! But we're not quite ready to print it yet - we're getting the digits backwards. 但是我们还没有准备好打印它-我们正在使数字倒退。 There are several ways to deal with this. 有几种方法可以解决此问题。 I think the simplest is to push 'em on the stack and pop 'em off in the correct order. 我认为最简单的方法是将它们push堆栈,然后以正确的顺序pop Another way is to go ahead and put 'em in the buffer backwards and do a "string reverse" at the end. 另一种方法是继续将它们放回缓冲区中,并在末尾进行“字符串反转”。 Another way is to start at the "end" of the buffer and work toward the front (decrement your index into the buffer after each character instead of incrementing it). 另一种方法是从缓冲区的“末端”开始并朝前工作(在每个字符之后将索引减少到缓冲区中而不是递增)。 This can mean that you're not quite at the beginning of the buffer when you run out of digits. 这可能意味着当数字用完时,您还不太处于缓冲区的开头。 We can use that to our advantage - right justified numbers look good if you're going to print 'em in a column. 我们可以利用它来发挥优势-如果您要在列中打印'em',则正确的对正数字看起来会很好。 You could fill with leading zeros, too (the character '0', not the number 0) if you think that looks good (I don't). 如果您认为看起来不错(我也不喜欢),也可以用前导零填充(字符“ 0”,而不是数字0)。

In any case, we've got '4' stashed away safely. 无论如何,我们都会安全地藏匿“ 4”。 Loop back and div again (making edx zero first!). 循环并再次div (首先使edx为零!)。 Now we've got 12 in eax and 3 in edx . 现在我们在eax有12个,在edx 3个。 Do something with the 3 and go back to div again. 对3进行处理,然后再次返回div 1 in eax and 2 in edx . eax 1,在edx 2。 Again, and eax is zero ( edx is 1) - at that point we're done! 同样, eax为零( edx为1)-至此,我们完成了! We can skip the last div if we compare eax to 9 - if it's less, we can get our final (first to be printed) digit from al instead of dl . 我们可以跳过最后div如果我们比较eax 9 -如果是少,我们可以从得到我们最终的(第一个将打印的)数字al代替dl Simpler to do it the same way every time... 每次都以相同的方式进行操作更简单...

 ; 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 

That's off the top of my head (not cut-and-pasted), and may have errors. 那是我的头顶(不是剪切粘贴的),并且可能有错误。 It's pretty sloppy - trashes registers that C would like preserved - doesn't return a zero-terminated string as C would like... but we're not using C so we don't care! 这很草率-丢弃C希望保留的寄存器-不会像C那样返回零结尾的字符串...但是我们不使用C,所以我们不在乎! :) :)

Feel free to improve it to your taste, or try a different method. 随意将其改进为您的口味,或尝试其他方法。

Unless you've got one, you'll want a "atoi" (or "atodw" to use the same naming convention), to convert the text the user enters to a number. 除非您有一个,否则您将需要一个“ atoi”(或“ atodw”使用相同的命名约定)将用户输入的文本转换为数字。 Same idea, but we subtract '0' from the character, multiply the "result so far" by ten, and add in the new digit... until done. 同样的想法,但是我们从字符中减去“ 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 ;-------------- 

That one's cut-and-pasted so "should" work. 那个被剪切粘贴的“应该”工作。 It, too, could be improved. 它也可以改进。 Uses an "interesting" way to multiply by ten and add in the new character converted to a number. 使用一种“有趣的”方式乘以十,然后添加转换为数字的新字符。 At this point, the "work" of your program consists of: add eax, 1 Should give you something to work with, anyway. 此时,程序的“工作”包括: add eax, 1无论如何应给您一些add eax, 1东西。 Have fun! 玩得开心! :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM