x86在基数2中输入一个数字,并将其作为基数8的数字输出
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了x86在基数2中输入一个数字,并将其作为基数8的数字输出相关的知识,希望对你有一定的参考价值。
为了将基数10中的任何数字转换为基数16,一个好的实现将是:
segment data use32 class=data
number dd 0
format_input db "%d", 0
format_output db "%x", 0
segment code use32 class=code
start:
push dword number
push dword format_input
call [scanf]
add esp, 4*2
push dword [number]
push dword format_output
call [printf]
add esp, 4*2
将数字从基数2转换为基数8是否有类似的实现?
这是essentially a duplicate of this C/C++ question,因为您正在询问如何通过调用C库函数来完成它。那没关系,没理由你不能在asm那样做。我决定不把它作为副本关闭,因为有足够的说法如何正确地做到这一点只是一个评论有点长。
C语法是一种更简单的方式来表达你需要粘合在一起的函数,所以我基本上只用C语言回答。如果你想在asm中做一个循环的任何步骤,那就去吧。将二进制字符串转换为整数非常简单,您只需一次移位一个数字。 (或使用SSE2 pmovmskb
)。
使用printf %o
转换为基数8的输出;这是ISO C直接支持的。
Base 2 isn't, though。但是strtoul
会根据您选择的基数转换字符串 - >无符号整数。唯一剩下的问题是将输入作为字符串读取。有很多方法可以做到这一点,但是如果你想避免过度阅读和消费不属于base-2数字的字符,你可以使用scanf
和仅接受字符0和1的%[]
转换。
所以你可以编写看起来像这样的asm:
// optionally this buffer could be static like your `number`, but there's no reason to do that.
char buf[65]; // reserve 65 bytes on the stack with sub esp, 80 (rounded up to keep stack 16B-aligned)
buf[0] = 0; // NULL terminate our stack buffer to avoid crashing in strtoul if scanf doesn't convert anything.
int success = scanf(" %64[01]", buf); // skip optional whitespace and store up to 64 bytes + null terminator into buf
// optional: check the conversion.
unsigned long num = strtoul(buf, NULL, 2); // parse as base 2, returning a binary integer
printf("%lo\n", num); // print as octal
// or %o if int and long are the same width in 32-bit asm
所有这些C语句都可以使用一小段asm指令实现,而不是循环。如果你不确定如何,ask a compiler with gcc -O2 -S -masm=intel
。
请注意scanf
格式字符串中的长度限制,因此如果用户按住某个键并且您的程序读取1000字节的1
,则不会有缓冲区溢出。
还要注意格式字符串中的前导空格,以跳过stdin
缓冲区中当前的任何空格。 (例如,前一行末尾的换行符,scanf
通常不会消耗)。 Conversions like %c
and %[
don't skip leading whitespace on their own。
如果您希望它使用尾随的非数字字符,请使用%64s
。 strtoul
将停在第一个非数字字符处。 (如果你传递非NULL char **
作为第二个arg,则存储指向该位置的指针。)
以上是关于x86在基数2中输入一个数字,并将其作为基数8的数字输出的主要内容,如果未能解决你的问题,请参考以下文章
将基数为 10 的数字转换为 .NET 中任何基数的最快方法?