A Horrible Conversion from Binary to Decimal in (ARM64) Assembly

This is not my finest code. It is the worst case of “just make it work” I’ve produced all week.

But it runs.

What does it do? It takes the first binary number in an array, and converts it to decimal. It assumes that the number is no more than 3 digits long.

It divides that number by 100 to get the 100s digit. Then it multiples that number by 100, assuming that it has gotten truncated. It subtracts that value from the original number to chop off the 100s digit, and divides the result by 10 to get the 10s digit.

Similar process to get the 1s digit.

It sticks these character by character into the Hello World Buffer, and calls the write system call.

 .data   Array: .word 503,87,61,908,170,897,709,901,271,528,834,154,231,303,435,707,424,861   ArrayLen = . - Array   msg: .ascii "Hello, World!\n" len = . - msg     .text   // app entry point   .globl _start _start: /*syscall write(int fd, const void *buf, size_t count) */ mov x0, #1 /* fd := STDOUT_FILENO */ ldr x1, =msg /* buf := msg */ ldr x2, =len /* count = len */   /* make a copy of the buffer pointer, as we are going to be writing to it character by character, and we need to advance the pointer. Yes, we could reuse x1 and just reset it at the end. That would be better. */ ldr x8,=msg   /*read the first value out of the array. In the final implementation, I need to be able to advance this pointer value by bvalue */   ldrsw x3, =Array ldrsw x4, [x3]   /* Divide by 100 to isolate the 100s digit */ mov x5, #100 sdiv x7, x4, x5 ADD w6, w7, #48 strb w6, [X8]   /*advance the write buffer pointer, so next time we write to the second character */ ADD X8, X8, #1   ldrsw x4, [x3]   /* restore the hundreds digit to the hundreds place so we can chop it off the original number */ mul x7, x7, x5 sub w4, w4, w7   /* divide the result by 10 to isolate just the 10s digit */ mov x5, #10 sdiv x6, x4, x5 ADD w6, w6, #48 strb w6, [X8]     ADD X8, X8, #1   ldrsw x4, [x3] /* if we remove the #48 we can reuse this register. Should have done this last time */ sub w6, w6, #48   /* get the 10s digit back into the 10s place */ mul x6, x6, x5 add x7, x7, x6   /*at this point, the x7 register has the original value without the 1s digit. */   sub w6, w4, w7 ADD w6, w6, #48 strb w6, [X8]     mov w8, #64 /* write is syscall #64 */ svc #0 /*invoke syscall */   /* syscall exit (int status) */ mov x0, #0 /* status := 0 */ mov w8, #93 /* exit is syscall #1 */ svc #0

Here is the output.

 \$ make shellsort ; ./shellsort as -g -o shellsort.o shellsort.s ld -o shellsort shellsort.o 503lo, World!

I promise I will clean this up.

Tomorrow.

This site uses Akismet to reduce spam. Learn how your comment data is processed.