This is essentially a duplicate of this C/C++ question because you're asking how to do it by calling C library functions. That's fine, no reason you can't do that in asm. I decided not to just close as a duplicate because there's enough to say about how to do it correctly that it's a bit long for just a comment.
C syntax is an easier way to express which functions you need to glue together, so I'll just basically answer in C. If you want to do any of the steps with a loop in asm, go for it. Converting a binary string to integer is very easy, you just shift in digits one at a time. (Or use SSE2 pmovmskb
).
Use a printf %o
conversion for output in base 8; that's directly supported by ISO C.
Base 2 isn't, though. But strtoul
converts strings->unsigned integers with your choice of radix. The only remaining problem is reading input as a string. There are lots of ways to do that, but if you want to avoid over-reading and consuming characters that aren't part of a base-2 number, you can use scanf
with a %[]
conversion that accepts only the characters 0 and 1.
So you can write asm that looks like this:
// 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
All of these C statements can be implemented with a short block of asm instructions, not loops. If you're not sure how, ask a compiler with gcc -O2 -S -masm=intel
.
Note the length limit in the scanf
format string, so you don't have a buffer overflow if the user holds down a key and your program reads 1000 bytes of 1
.
Also note the leading whitespace in the format string, to skip any whitespace currently in the stdin
buffer. (e.g. the newline at the end of the previous line, which scanf
won't normally consume). Conversions like %c
and %[
don't skip leading whitespace on their own.
If you want it to consume trailing non-digit characters, use %64s
. strtoul
will stop at the first non-digit character. (And store a pointer to that position if you pass a non-NULL char **
as the 2nd arg.)