-2

For converting any number in the base 10 to the base 16, a good implementation would be:

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

Is there an implementation alike for converting a number from the base 2 to the base 8?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 3
    That's just calling C library functions, that's not "implementation" of the conversion. If that is enough for you, for octal there's formatter `%o`. For binary .. surprisingly I don't see any, so you will have to check your `scanf` documentation, whether it has some, or write your own. But nevertheless, this is quite elementary stuff, you should be able to convert any base to any base on paper+pen easily, if you understand the math behind numeral systems. Then to write such math in assembly is usually trivial, especially if powers of two bases are involved, you need just rearrange bit values. – Ped7g Dec 15 '17 at 11:39
  • I.e. input in base 2 has 1 important bit per input element (if it's ASCII string like "010101", then you can drop from each char all bits except the lowest, and that's your binary input, ASCII `'0'` is `0011_0000` and `'1'` is `0011_0001`, so last bits of such string input will be 0, 1, 0, 1, 0, 1 ...) .. and output in octal needs 3 bits per digit, so you need just to group that into `010`, `101` and output those two values, i.e. "25". ... no division/multiplication needed (on contrary to the base 10 formatting, where some kind of multiplication/division will happen). `0b010101 == 0o25` – Ped7g Dec 15 '17 at 11:45
  • 2
    @Ped7g: ISO C scanf/printf [don't have base 2 conversion specifiers](https://stackoverflow.com/questions/11597863/why-does-scanfi-a-not-take-binary-like-0b101), and it's not a standard extension, [not even in glibc](https://stackoverflow.com/a/112947/224132). For input, though, `strtol` takes a radix as an arg. – Peter Cordes Dec 15 '17 at 12:05
  • Hi and welcome! I want to give some sense of why this question isn't getting a good reception. The ideal SO question isolates an issue and asks an question that (likely) has an objectively best answer. From your question, it's not clear if the issue is base conversion algorithms in general, serialization and deserialization using the C standard library, or writing x86 assembly. Also, each topic has been separately covered extensively so we get the impression that you want us to write code for you. Please don't get discouraged! We all had to learn the culture here at some point. – Praxeolitic Jan 06 '18 at 02:52

1 Answers1

1

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.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847