x86在基数2中输入一个数字,并将其作为基数8的数字输出

问题描述 投票:-2回答:1

为了将基数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是否有类似的实现?

c assembly x86 nasm standard-library
1个回答
1
投票

这是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

如果您希望它使用尾随的非数字字符,请使用%64sstrtoul将停在第一个非数字字符处。 (如果你传递非NULL char **作为第二个arg,则存储指向该位置的指针。)

© www.soinside.com 2019 - 2024. All rights reserved.