The MASM Forum

Miscellaneous => Miscellaneous Projects => Topic started by: ahsat on March 31, 2024, 04:37:00 AM

Title: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 04:37:00 AM
I am new here and I don't know the current state of things in the world. I have an algorithm I may want to share, if it is not already been invented elsewhere. I came up with the algorithm in the late 70s.

What is the current state of the art in converting binary to a null terminated string of any base, ie binary to hex, to decimal, or binary?

For example, given a number in rax, the base in rbx, the address of the target string in edi, and a table of digits, ie "0123456789abcdef". Where can I find the best example of assembler code that would convert the value in rax into displayable text.

I am not looking for code that will simply do the function, I already know how to do that. I want to see if I know a better way of doing it. Remember this is converting binary to any base, lets say base 2 to base 60. Base 60 is what the Sumerian's used.
Title: Re: Binary to displayable text, any base
Post by: Vortex on March 31, 2024, 05:53:00 AM
Hi ahset,

It depends on your expectations, well-optimized routines will require extra work. As a beginning, you can start by studying the functions from masm32.lib :

\masm32\help\masmlib.chm :

QuoteConversions

atodw Convert ascii number to DWORD
htodw Convert HEX string to DWORD
dwtoa Convert DWORD to ascii string
.
.
.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on March 31, 2024, 06:45:19 AM
Quote from: ahsat on March 31, 2024, 04:37:00 AMWhat is the current state of the art in converting binary to a null terminated string of any base, ie binary to hex, to decimal, or binary?

In addition to what Vortex wrote, there are these number to string macros, part of the Masm32 SDK:
ubyte$() Unsigned BYTE input
sbyte$() Signed BYTE input
xbyte$() Hex notation output BYTE
uword$() Unsigned WORD input
sword$() Signed WORD input
xword$() Hex notation output WORD
udword$() Unsigned DWORD input
sdword$() Signed DWORD input
xdword$() Hex notation output DWORD
uqword$() Unsigned QWORD input
sqword$() Signed QWORD input
xqword$() Hex notation output QWORD
real4$() 32 bit FLOAT input
real8$() 64 bit FLOAT input
real10$() 80 bit FLOAT input

MasmBasic offers
Str$ (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1186)()     input automatically detected (reg32, xmm*, dword, word, byte, ST(0))
Hex$ (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1198)()   input automatically detected (...)
Bin$ (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1199)()    input reg32, dword variable, immediate
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 07:16:48 AM
Quote from: Vortex on March 31, 2024, 05:53:00 AMatodw Convert ascii number to DWORD
htodw Convert HEX string to DWORD
dwtoa Convert DWORD to ascii string

I am sorry at being so new here, but where can I locate those?
Title: Re: Binary to displayable text, any base
Post by: Vortex on March 31, 2024, 07:47:37 AM
Hi ahsat,

QuoteI am sorry at being so new here, but where can I locate those?

The location of the source code :

\masm32\m32lib
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on March 31, 2024, 08:21:39 AM
Remember, those (most of them) are all 32-bit code.

I'm sure your binary-to-ASCII routine could easily be rewritten in X86/X64 assembly language. Care to post it here?
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 08:26:04 AM
Quote from: Vortex on March 31, 2024, 07:47:37 AMThe location of the source code :

I have \masm64\m64lib and it seems not to be there. I will get the 32 bit version.
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 08:30:04 AM
Quote from: NoCforMe on March 31, 2024, 08:21:39 AMI'm sure your binary-to-ASCII routine could easily be rewritten in X86/X64 assembly language. Care to post it here?

If my code is a good as I think it is, I will. But I have been out of the coding world for so long, I don't want to look foolish. I want to see the best that is out there first.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on March 31, 2024, 08:43:46 AM
Quote from: ahsat on March 31, 2024, 08:30:04 AMI want to see the best that is out there first

Go to forum search (http://masm32.com/board/index.php?action=search;advanced;search=) and try e.g. fast hex

Btw instead of chasing the fastest bintostring algo, you might simply use them for some more ambitious project of yours.
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 09:20:49 AM
Quote from: jj2007 on March 31, 2024, 08:43:46 AMsome more ambitious project of yours

I'm too old for anything ambitious.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on March 31, 2024, 09:45:05 AM
Quote from: ahsat on March 31, 2024, 09:20:49 AMI'm too old for anything ambitious.

Beating the algos in the Laboratory is extremely ambitious :biggrin:
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on March 31, 2024, 10:10:38 AM
Quote from: ahsat on March 31, 2024, 08:30:04 AM
Quote from: NoCforMe on March 31, 2024, 08:21:39 AMI'm sure your binary-to-ASCII routine could easily be rewritten in X86/X64 assembly language. Care to post it here?

If my code is a good as I think it is, I will. But I have been out of the coding world for so long, I don't want to look foolish. I want to see the best that is out there first.

I, for one, would be curious to see what you have. No need to worry about looking foolish: we're not judgemental like that here. (If there are obvious flaws in your code someone might point them out.) Always interesting to see someone's take on how to perform some function, especially if it was conceived some number of years ago.

And so far as performance goes, I've been driving the same nail here for some time: it really doesn't make any difference how fast such routines are, at least in most applications. Let's say you're using such a routine to convert display user output in a Windows console program: the time it takes to actually display the text completely swamps whatever time it takes to do the conversion.

Now if your code is super-adaptable, can produce output in any radix (base), then that would be something ...
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 11:06:32 AM
Quote from: NoCforMe on March 31, 2024, 10:10:38 AMoutput in any radix (base), then that would be something

The code can produce output in any base, I currently have a test program that supports base 2 to base 60. The only thing that limits the base is the characters available to represent the digits. I am currently using

'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkylmnopqrstuvw'

as the digits. Does that meet your definition of a radix (base)?

I also understand you to be saying that you know of nothing like this existing now, is that correct.
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 11:18:16 AM
Quote from: jj2007 on March 31, 2024, 09:45:05 AMBeating the algos in the Laboratory is extremely ambitious

I think I have been doing that all my life.  :biggrin:
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on March 31, 2024, 11:18:43 AM
Yes, radix == base.

Base 60: how would that even work? Wouldn't you need 60 unique "digits" for representation? Never dealt with any higher base than 16 (hex).

I don't know of any routine that does such universal conversion, but that certainly doesn't mean it doesn't exist.

I'd still like to see your code if possible.
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 11:31:53 AM
Quote from: NoCforMe on March 31, 2024, 11:18:43 AMWouldn't you need 60 unique "digits" for representation?

I gave you the digits I am using. Again they are:
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkylmnopqrstuvw'
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 11:33:25 AM
Quote from: NoCforMe on March 31, 2024, 11:18:43 AMWouldn't you need 60 unique "digits" for representation?

I gave you the digits I am using. Again they are:
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkylmnopqrstuvw'
Title: Re: Binary to displayable text, any base
Post by: jj2007 on March 31, 2024, 11:37:22 AM
Quote from: NoCforMe on March 31, 2024, 11:18:43 AMWouldn't you need 60 unique "digits" for representation?

As an alternative to the 0...z scheme (10+2*26=62 digits), you could use A0...A9, B0...B9, ... F0...F9: 60 "digits". The Unicode universe is also quite big, but a base-60 number composed of lots of emojis would be difficult to read.
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 11:41:45 AM
I posted the code, now it seems to have disappeared.
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 11:44:31 AM
This algorithm is not the fastest power of 2 bases like binary, octal and hex. But from looking around a bit, I think AnyToAny and ctAnyToAny are unique. Few programmers ever think about recursion.

I would like to know if any of you will use the routines. The routines can be converted to macros.

The program was linked using:
polink.exe /SUBSYSTEM:CONSOLE /LARGEADDRESSAWARE:NO /ENTRY:main /OUT:AnyBase.exe AnyBase.obj

TITLE AnyBase

OPTION PROC:PRIVATE                ;Don't automatically make procs public

include \masm64\include64\masm64rt.inc

.data

result    db      65 dup (?)        ;max should be 64, plus a null     
newLine   db      0dh, 0ah, 0
numb      qword   ?                 ;holds the number being converted

.CODE

;Got to keep the Sumerian happy, base 60 is the max here.
digits    db      '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkylmnopqrstuvw'
maxBase   equ     $-digits          ;Max base number, should be 60

AnyToAny proc
;----------------------------------------------------------------------------
;          Original by Ray Gwinn
; Any number to any base.
; Parameters:
;   eax    The number to convert
;   ebx    The desired base
;   edi    Where to place the converted string
;----------------------------------------------------------------------------
;
    push  rdx                       ;save rdx, or a digit
    xor   rdx, rdx                  ;zero rdx
    div   rbx                       ;generate next digit in rdx
    test  rax, rax                  ;test if done
    jz    @f                        ;br if done

    invoke AnyToAny                 ;generate next digit
@@: mov   al, digits[rdx]           ;get the ascii value
    stosb                           ;save it
    pop   rdx                       ;restore rdx, or get next digit
    ret
AnyToAny endp

ctAnyToAny proc
;----------------------------------------------------------------------------
;          Original by Ray Gwinn
; Any number to any base with a specified digit length, will pad leading zeros.
; Parameters:
;   eax    The number to convert
;   ebx    The desired base
;   ecx    The desired digit count
;   edi    Where to place the converted string
;----------------------------------------------------------------------------
;
    push  rdx                       ;save rdx, or a digit
    xor   rdx, rdx                  ;zero rdx
    div   rbx                       ;generate next digit in rdx
    dec   ecx                       ;decrement digit count
    jecxz @f                        ;br if done

    invoke ctAnyToAny               ;generate next digit
@@: mov   al, digits[rdx]           ;get the ascii value
    stosb                           ;save it
    pop   rdx                       ;restore rdx, or get next digit
    ret
ctAnyToAny endp

main proc  Public
;----------------------------------------------------------------------------
; Program to demo any number to any base, bases 2 to 60.
;----------------------------------------------------------------------------
;
    mov   numb, 123456789           ;convert this number, over and over
    jmp   @f

m00 db    13, 10, 'This is the number we will be converting', 13, 10, 0
@@: mov   rax, numb                 ;the number to rax
    mov   ebx, 10                   ;the base to rbx
    mov   edi, offset result        ;the destination addr to edi
    invoke AnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m00
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m01 db    13, 10, 'This is the low byte of the number in hex', 13, 10, 0
@@: mov   ecx,2
    mov   rax, numb                 ;the number to rax
    mov   ebx, 16                   ;the base to rbx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m01
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m02 db    13, 10, 'This is the 16 bit number, in hex', 13, 10, 0
@@: mov   ecx,4
    mov   rax, numb                 ;the number to rax
    mov   ebx, 16                   ;the base to rbx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m02
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m03 db    13, 10, 'This is the 32 bit number, in hex', 13, 10, 0
@@: mov   ecx,8
    mov   rax, numb                 ;the number to rax
    mov   ebx, 16                   ;the base to rbx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m03
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m04 db    13, 10, 'This is the 64 bit number, in hex', 13, 10, 0
@@: mov   ecx,16
    mov   rax, numb                 ;the number to rax
    mov   ebx, 16                   ;the base to rbx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m04
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m05 db    13, 10, 'This is the 64 bit number, in binary', 13, 10, 0
@@: mov   ecx,64
    mov   rax, numb                 ;the number to rax
    mov   ebx, 2                    ;the base to rbx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m05
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m06 db    13, 10, 'And in Sumerian Sexagesimal, base 60', 13, 10, 0
@@: mov   ecx,10
    mov   rax, numb                 ;the number to rax
    mov   ebx, 60                   ;the base to rbx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m06
    invoke StdOut, addr result
    invoke StdOut, addr newLine

    invoke ExitProcess, 0           ;Error code 0
    ret
main ENDP

end
Title: Re: Binary to displayable text, any base
Post by: jj2007 on March 31, 2024, 11:54:45 AM
It works :thumbsup:

This is the number we will be converting
123456789

This is the low byte of the number in hex
15

This is the 16 bit number, in hex
CD15

This is the 32 bit number, in hex
075BCD15

This is the 64 bit number, in hex
00000000075BCD15

This is the 64 bit number, in binary
0000000000000000000000000000000000000111010110111100110100010101

And in Sumerian Sexagesimal, base 60
000009VXX9
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on March 31, 2024, 12:13:07 PM
Quote from: ahsat on March 31, 2024, 11:33:25 AM
Quote from: NoCforMe on March 31, 2024, 11:18:43 AMWouldn't you need 60 unique "digits" for representation?

I gave you the digits I am using. Again they are:
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkylmnopqrstuvw'

Yes, sorry, I miscounted (I missed that you put kyl in there). Pretty kewl ... like the recursion, too.
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 12:20:23 PM
Quote from: jj2007 on March 31, 2024, 11:54:45 AMIt works :thumbsup:

Not bad for an 81 year old, right?
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 12:23:44 PM
Quote from: NoCforMe on March 31, 2024, 12:13:07 PMlike the recursion, too.

My first program was a plug board. Recursion was common then.
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on March 31, 2024, 12:36:13 PM
Quote from: ahsat on March 31, 2024, 12:23:44 PM
Quote from: NoCforMe on March 31, 2024, 12:13:07 PMlike the recursion, too.
My first program was a plug board.
You mean like this (http://www.righto.com/2017/04/1950s-tax-preparation-plugboard.html)? Wow.
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 12:48:39 PM
Quote from: NoCforMe on March 31, 2024, 12:36:13 PMYou mean like this (http://www.righto.com/2017/04/1950s-tax-preparation-plugboard.html)?

No, but you had to use recursion.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on March 31, 2024, 12:58:43 PM
Quote from: ahsat on March 31, 2024, 11:44:31 AMThis algorithm is not the fastest power of 2 bases like binary, octal and hex. But from looking around a bit, I think AnyToAny and ctAnyToAny are unique. Few programmers ever think about recursion.

I like the idea. I made some quick tests: 10 Million numbertohex conversions run in about 900 milliseconds on my AMD Athlon Gold 3150U. For comparison, Hex$ does it in less than a quarter of the time, but since it's 32-bit code, it's limited to DWORDs.

Compliments, that's really good, even for somebody who is only 14 years older than I am ;-)
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on March 31, 2024, 01:00:44 PM
Quote from: ahsat on March 31, 2024, 12:48:39 PM
Quote from: NoCforMe on March 31, 2024, 12:36:13 PMYou mean like this (http://www.righto.com/2017/04/1950s-tax-preparation-plugboard.html)?
No, but you had to use recursion.
So what is "plug board" programming then?
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 01:11:40 PM
Quote from: NoCforMe on March 31, 2024, 01:00:44 PMSo what is "plug board" programming then?

Some of the original computers used wiring boards. Instructions were plugging wires from one hole in the board to another hole. You then added wires to tell that instruction what registers to use. The one I programmed had only registers, no memory. I can't remember all the details, but the registers were very large, probably 128 bits or more. I also can't remember how many registers it had, probably 16 or 32.
Title: Re: Binary to displayable text, any base
Post by: ahsat on March 31, 2024, 01:38:32 PM
Quote from: jj2007 on March 31, 2024, 12:58:43 PM10 Million numbertohex conversions run in about 900 milliseconds

I think the algorithms will hold their own, speed wise, on bases like base 10. You are obviously faster than I am. You are probably active, and I have been inactive since around 2000.

I would be very interested in a speed test of base 10. Also, it should be simple and quick to convert to 32 bit. Since coming alive again, I have only been fooling around with 64 bit. It would probably take me a day or so to setup a 32 bit version.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on March 31, 2024, 09:01:26 PM
Quote from: ahsat on March 31, 2024, 01:38:32 PMI would be very interested in a speed test of base 10. Also, it should be simple and quick to convert to 32 bit.

Here are timings for your algo, base 16 and base 10:
This program was assembled with UAsm64 in 64-bit format.
AMD Athlon Gold 3150U with Radeon Graphics
500 milliseconds
485 milliseconds
484 milliseconds
484 milliseconds
485 milliseconds
The number is 075BCD15
500 milliseconds
516 milliseconds
516 milliseconds
484 milliseconds
500 milliseconds
The number is 123456789

With base 10, it's 30% faster than my Str$() algo. I attach both sources and executables.

Note I have modified your algo a bit, not in its content but instead of xx proc I used xx:, i.e. a label, to make sure the assembler doesn't create any overhead.
Title: Re: Binary to displayable text, any base
Post by: sinsi on March 31, 2024, 09:26:54 PM
AnyToAnyRay.zip > AnyToAny.exe > oops
(1f00.30e0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=000000b4 ebx=00000010 ecx=89ab5db4 edx=000000b5 esi=000000b4 edi=000000b4
eip=7758343a esp=0019ff3c ebp=0019ff64 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
KERNELBASE!lstrlenA+0x1a:
7758343a 8a08            mov     cl,byte ptr [eax]          ds:002b:000000b4=??




This program was assembled with UAsm64 in 32-bit format.
This is the 64 bit number, in hex:
bye

Title: Re: Binary to displayable text, any base
Post by: jj2007 on March 31, 2024, 10:02:06 PM
Quote from: sinsi on March 31, 2024, 09:26:54 PMAnyToAnyRay.zip > AnyToAny.exe > oops

Oops indeed - wrong exe attached, sorry. ^^^ Corrected ^^^
Title: Re: Binary to displayable text, any base
Post by: sinsi on March 31, 2024, 10:05:38 PM
Nice
This program was assembled with UAsm64 in 64-bit format.
13th Gen Intel(R) Core(TM) i9-13900KF
156 milliseconds
140 milliseconds
141 milliseconds
141 milliseconds
140 milliseconds
The number is 075BCD15
157 milliseconds
156 milliseconds
172 milliseconds
156 milliseconds
156 milliseconds
The number is 123456789
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 01, 2024, 12:30:35 AM
Quote from: jj2007 on March 31, 2024, 09:01:26 PMWith base 10, it's 30% faster than my Str$() algo.

I don't understand the code or the results you posted, but I think you are saying that base 10, it did beat the algos in the Laboratory.

How did you attach files to your post?
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 01, 2024, 01:15:21 AM
Quote from: ahsat on April 01, 2024, 12:30:35 AMI don't understand the code or the results you posted, but I think you are saying that base 10, it did beat the algos in the Laboratory.

The code is basically some wrappers for measuring time with a GetTickCount pair, plus your original two algos. The only modification was to use AnyToAny: instead of AnyToAny proc, i.e. a simple label instead of the proc macro. The latter may trigger certain things that could slow down your code, such as creating a stack frame.

Quote from: ahsat on April 01, 2024, 12:30:35 AMHow did you attach files to your post?

There are two modes to respond:
1. Quick edit
2. Reply

Both show Add image to post at the bottom.
Only the Reply mode shows Click or drag files here to attach them.

Zip your code and attach the archive, using the Reply mode.
If you accidentally already posted in Quick edit mode, use More... Modify in the lower right corner.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 01, 2024, 01:18:49 AM
Quote from: jj2007 on April 01, 2024, 01:15:21 AMIf you accidentally already posted in Quick edit mode, use

I think the last part of the text in your post was cut off.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 01, 2024, 01:28:17 AM
Quote from: ahsat on April 01, 2024, 01:18:49 AMI think the last part of the text in your post was cut off.

Just hit F5 or Ctrl F5.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 01, 2024, 03:46:04 AM
I posted a testbed (https://masm32.com/board/index.php?topic=11820.0) in the Laboratory. It's 32-bit code, so if you can convert your algo to 32-bit, I can add it to the testbed.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 01, 2024, 04:57:06 AM
Quote from: jj2007 on April 01, 2024, 03:46:04 AMif you can convert your algo to 32-bit, I can add it to the testbed.

Do you mean to convert just the to ten instruction routines (AnyToAny and ctAnyToAny) or the whole program Anybase?

Remember, I am very new in the modern development environments. The MASM32 STK does not like something on my computer and will not install. I will have to research why, so converting the whole program may take me awhile.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 01, 2024, 06:56:37 AM
Quote from: ahsat on April 01, 2024, 04:57:06 AMDo you mean to convert just the to ten instruction routines

Have a look (https://masm32.com/board/index.php?msg=128381) :cool:
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 01, 2024, 07:37:32 AM
Quote from: jj2007 on April 01, 2024, 06:56:37 AMHave a look

I did, and made a comment.

Perhaps you would be so kind as to help me with the MASM32 SDK. I am getting an error that has me stumped. I have reduced the code to this:
.386
.model flat
.data
      db      0dh, 0ah, 0
end
I then get the following:
d:\masm32\AnyBase32>D:\masm32\bin\ml.exe /c AnyBase.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

 Assembling: AnyBase.asm

d:\masm32\AnyBase32>D:\masm32\bin\polink.exe /SUBSYSTEM:CONSOLE /OUT:AnyBase32.exe AnyBase.obj
POLINK: fatal error: Invalid machine type in object 'AnyBase.obj'.
Note that I am using egerything from the SDK, but still getting the POLINK error.
Title: Re: Binary to displayable text, any base
Post by: TimoVJL on April 01, 2024, 08:01:00 AM
ml /c /coff
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on April 01, 2024, 08:22:48 AM
You might want to create a batch file to do your assembling and linking, rather than typing it every time at the command line as you apparently did. Here's mine, lifted from [somewhere in] the MASM32 SDK and modified:

@echo off

ml /c /coff /Fl /Sg /Sn %1.asm
:ml /c /coff /Fl /Sn /Zi %1.asm
if errorlevel 1 goto errasm

link /SUBSYSTEM:WINDOWS %1
:link /SUBSYSTEM:WINDOWS /debug %1
if errorlevel 1 goto errlink
goto TheEnd

:errlink
echo _
echo Link error
goto TheEnd

:errasm
echo _
echo Assembly Error
goto TheEnd

:TheEnd

It's got all those command-line switches that are needed, plus there is a "debug" flavor (commented out here) for when you need to look at your code using OllyDbug or some other debugger.

This version creates a regular Windows GUI application. To create a console app, replace SUBSYSTEM:WINDOWS with SUBSYSTEM:CONSOLE.

Invoke it without the ".asm" in the filename (or you can modify it to accept the full root filename).
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 01, 2024, 09:14:46 AM
I have the program entry named entry_point.

Now the linker or assembler is adding a leading underscore to my public procs. Can anyone help with this one?
d:\masm32\AnyBase32>D:\masm32\bin\ml.exe /c /coff /Fl /Sg /Sn AnyBase.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

 Assembling: AnyBase.asm

***********
ASCII build
***********


d:\masm32\AnyBase32>D:\masm32\bin\polink.exe /SUBSYSTEM:CONSOLE /ENTRY:entry_point /OUT:AnyBase32.exe AnyBase.obj
POLINK: error: Unresolved external symbol '_entry_point'.
Title: Re: Binary to displayable text, any base
Post by: sinsi on April 01, 2024, 09:37:54 AM
You might need this at the end of your source code for 32-bit
end entry_point
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on April 01, 2024, 09:40:24 AM
Quote from: sinsi on April 01, 2024, 09:37:54 AMYou might need this at the end of your source code for 32-bit
end entry_point
Yes! You definitely do need that. (But I know nothing about polink; I just use good old ml.exe.)
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 01, 2024, 10:06:18 AM
Quote from: sinsi on April 01, 2024, 09:37:54 AMend entry_point
The entry_point on the end statement did it. Forever, that has been the way the entry point was defined, but they changed that for the 64bit assembled.

Thank you guys so much for this help. The 32 bit version now links and seems to work. I will see if it needs any clean up.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 02, 2024, 05:46:03 AM
Below is the 32 bit version of Anybase32.exe. It was linked using:

polink.exe /SUBSYSTEM:CONSOLE /OUT:AnyBase32.exe AnyBase.obj

In my day, an algorithms worth was based on how powerful it was, not just its speed. All the routines you guys are comparing it to, will only convert a single base. The algorithm I released will do any base, and is faster for most bases.

So, which is better, code a routine for each base that you will ever use, or have one routine that will do any base you need? With this algorithm you only need one choice, leading zeors or not.

TITLE AnyBase

OPTION PROC:PRIVATE                ;Don't automatically make procs public

include \masm32\include\masm32rt.inc

.data

result    db      33 dup (?)        ;max should be 32, plus a null     
newLine   db      0dh, 0ah, 0
numb      dword   ?                 ;holds the number being converted

.CODE

;Got to keep the Sumerian happy, base 60 is the max here.
digits    db      '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkylmnopqrstuvw'
maxBase   equ     $-digits          ;Max base number, should be 60

AnyToAny proc
;----------------------------------------------------------------------------
;          Original by Ray Gwinn
; Any number to any base.
; Parameters:
;   eax    The number to convert
;   ebx    The desired base
;   edi    Where to place the converted string
;----------------------------------------------------------------------------
;
    push  edx                       ;save edx, or a digit
    xor   edx, edx                  ;zero edx
    div   ebx                       ;generate next digit in edx
    test  eax, eax                  ;test if done
    jz    @f                        ;br if done

    invoke AnyToAny                 ;generate next digit
@@: mov   al, digits[edx]           ;get the ascii value
    stosb                           ;save it
    pop   edx                       ;restore edx, or get next digit
    ret
AnyToAny endp

ctAnyToAny proc
;----------------------------------------------------------------------------
;          Original by Ray Gwinn
; Any number to any base with a specified digit length, will pad leading zeros.
; Parameters:
;   eax    The number to convert
;   ebx    The desired base
;   ecx    The desired digit count
;   edi    Where to place the converted string
;----------------------------------------------------------------------------
;
    push  edx                       ;save edx, or a digit
    xor   edx, edx                  ;zero edx
    div   ebx                       ;generate next digit in edx
    dec   ecx                       ;decrement digit count
    jcxz  @f                        ;br if done

    invoke ctAnyToAny               ;generate next digit
@@: mov   al, digits[edx]           ;get the ascii value
    stosb                           ;save it
    pop   edx                       ;restore edx, or get next digit
    ret
ctAnyToAny endp

entry_point proc public
;----------------------------------------------------------------------------
; Program to demo any number to any base, bases 2 to 60.
;----------------------------------------------------------------------------
;
    mov   numb, 123456789           ;convert this number, over and over
    jmp   @f

m00 db    13, 10, 'This is the number we will be converting', 13, 10, 0
@@: mov   eax, numb                 ;the number to eax
    mov   ebx, 10                   ;the base to ebx
    mov   edi, offset result        ;the destination addr to edi
    invoke AnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m00
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m01 db    13, 10, 'This is the low byte of the number in hex', 13, 10, 0
@@: mov   ecx,2
    mov   eax, numb                 ;the number to eax
    mov   ebx, 16                   ;the base to ebx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m01
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m02 db    13, 10, 'This is the 16 bit number, in hex', 13, 10, 0
@@: mov   ecx,4
    mov   eax, numb                 ;the number to eax
    mov   ebx, 16                   ;the base to ebx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m02
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m03 db    13, 10, 'This is the 32 bit number, in hex', 13, 10, 0
@@: mov   ecx,8
    mov   eax, numb                 ;the number to eax
    mov   ebx, 16                   ;the base to ebx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m03
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m05 db    13, 10, 'This is the 32 bit number, in binary', 13, 10, 0
@@: mov   ecx,32
    mov   eax, numb                 ;the number to eax
    mov   ebx, 2                    ;the base to ebx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m05
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m06 db    13, 10, 'And in Sumerian Sexagesimal, base 60', 13, 10, 0
@@: mov   ecx,10
    mov   eax, numb                 ;the number to eax
    mov   ebx, 60                   ;the base to ebx
    mov   edi, offset result        ;the destination to edi
    invoke ctAnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m06
    invoke StdOut, addr result
    invoke StdOut, addr newLine

    invoke ExitProcess, 0           ;Error code 0
    ret
entry_point ENDP

end entry_point
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on April 02, 2024, 06:05:30 AM
Welll, so far in my assembly-coding career I've only ever needed 2 bases: decimal and hex. Well, maybe binary once or twice. So the "any base" thing is a meh in my book; just one more annoying parameter to forget to place properly.

And really, when in the world would you ever use base 60? or really anything except 2, 10 or 16? (If you're a really old Unix coot I guess you could add octal.)

Still, kewl algo.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 02, 2024, 06:23:33 AM
Quote from: ahsat on April 02, 2024, 05:46:03 AMBelow is the 32 bit version of Anybase32.exe

Thanks, Ray. I've added it to the testbed as "Ray II", see attachment. Timings:

AMD Athlon Gold 3150U with Radeon Graphics      (SSE4)
...
Averages:
5348    cycles for dwtoa
3646    cycles for dw2str
22575   cycles for MasmBasic Str$()
16554   cycles for Ray's algo I
15138   cycles for Ray's algo II

20      bytes for dwtoa
74      bytes for dw2str
16      bytes for MasmBasic Str$()
110     bytes for Ray's algo I
129     bytes for Ray's algo II

dwtoa                                   12345678
dw2a                                    12345678
dw2str                                  12345678
MasmBasic Str$()                        12345678
Ray's algo I                            012345678
Ray's algo II                           123456788

It is certainly faster than my own Str$(), but dw2str is a tick faster. You may also need to care for a zero delimiter: 123456788
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 02, 2024, 07:03:53 AM
Quote from: jj2007 on April 02, 2024, 06:23:33 AMIt is certainly faster than my own Str$(), but dw2str is a tick faster
Yes, but my point is that you need two routines to do that.

Even in your timing test you had to use three different programs to compare to one. The one can do what takes three others to do, just for you to test it.

If one assembler can do the combined things that three other assemblers can do, which one are you going to use on a normal basis? And I suspect you would not care if it was a little slower.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 02, 2024, 07:28:53 AM
Ray,

Your solution is certainly very elegant, and I think we all agree that you got an extremely good start as an "old newbie" in this forum. It's nice to have you with us :thup:

Jochen
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 02, 2024, 11:01:01 AM
I got the mult version working, at least partially:

Averages:
4372    cycles for dwtoa
2816    cycles for dw2str
16560   cycles for MasmBasic Str$()
12337   cycles for Ray's algo I
4289    cycles for Ray+mul
12338   cycles for Ray's algo II

20      bytes for dwtoa
82      bytes for dw2str
16      bytes for MasmBasic Str$()
110     bytes for Ray's algo I
64      bytes for Ray+mul
129     bytes for Ray's algo II

dwtoa                                   123456789
dw2a                                    123456789
dw2str                                  123456789
MasmBasic Str$()                        123456789
Ray's algo I                            123456789
Ray+mul                                 123456789
Ray's algo II                           123456789

.DATA?
result2 db 40 dup(?)
.CODE
_xmul dd 0CCCCCCCDh
ctAnyToAnyMul:
  push ecx ; save edx, or a digit
  mov ecx, eax
  mul _xmul ; something is wrong here
  shr edx, 3
  mov eax, edx
  add edx, edx
  lea edx, [edx*4+edx]
  sub ecx, edx
  neg edx
  test eax, eax
  .if !Zero? ; br if done
call ctAnyToAnyMul ; generate next digit
  .endif
  mov al, @digits[edx] ; get the ascii value
  stosb ; save it
  pop edx ; restore edx, or get next digit
  ret

NameF equ Ray+mul
TestF proc
  mov esi, AlgoLoops-1 ; loop e.g. 100x
  align 4
  .Repeat
mov eax, TheNumber
mov edi, offset result2
call ctAnyToAnyMul
dec esi
  .Until Sign?
  mov eax, offset result
  ret
TestF endp
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 04, 2024, 03:32:46 PM
A forum member, jimg, managed to eliminate the recursion and I have incorporated his changes.

I will do the 32 bit version tomorrow, a new 64 bit version of AnyToAny is below. It can be linked with:

polink.exe /SUBSYSTEM:CONSOLE /LARGEADDRESSAWARE:NO /ENTRY:main /OUT:AnyBase.exe AnyBase.obj
TITLE AnyBase

OPTION PROC:PRIVATE                ;Don't automatically make procs public

include \masm64\include64\masm64rt.inc

.data

result    db      65 dup (?)        ;max should be 64, plus a null     
newLine   db      0dh, 0ah, 0
numb      qword   ?                 ;holds the number being converted

.CODE

;Got to keep the Sumerian happy, base 60 is the max here.
digits    db      '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkylmnopqrstuvw'
maxBase   equ     $-digits          ;Max base number, should be 60

AnyToAny proc
;----------------------------------------------------------------------------
;          Original by Ray Gwinn
; Any number to any base.
; Parameters:
;   eax    The number to convert
;   ebx    The desired base
;   edi    Where to place the converted string
;----------------------------------------------------------------------------
;
    xor   rcx, rcx                  ;zero rcx
agn:
    push  rdx                       ;save rdx, or a digit
    inc   rcx                       ;bump counts in loop
    xor   rdx, rdx                  ;zero rdx
    div   rbx                       ;generate next digit in rdx
    test  rax, rax                  ;test if done
    jnz   agn                       ;br if done

@@: mov   al, digits[rdx]           ;get the ascii value
    stosb                           ;save it
    pop   rdx                       ;restore rdx, or get next digit
    loop  @b                        ;loop till all digits processed

    ret
AnyToAny endp

main proc  Public
;----------------------------------------------------------------------------
; Program to demo any number to any base, bases 2 to 60.
;----------------------------------------------------------------------------
;
    xor   rsi, rsi
    mov   rax, 123456789            ;convert this number, over and over
    mov   numb, rax                 ;save it in numb
    jmp   @f

m00 db    13, 10, 'This is the number we will be converting', 13, 10, 0
@@: mov   rax, numb                 ;the number to rax
    mov   ebx, 10                   ;the base to rbx
    mov   edi, offset result        ;the destination addr to edi
    invoke AnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m00
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m04 db    13, 10, 'This is the 64 bit number, in hex', 13, 10, 0
@@: mov   rax, numb                 ;the number to rax
    mov   ebx, 16                   ;the base to rbx
    mov   edi, offset result        ;the destination to edi
    invoke AnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m04
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m05 db    13, 10, 'This is the 64 bit number, in binary', 13, 10, 0
@@: mov   rax, numb                 ;the number to rax
    mov   ebx, 2                    ;the base to rbx
    mov   edi, offset result        ;the destination to edi
    invoke AnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m05
    invoke StdOut, addr result
    invoke StdOut, addr newLine
    jmp   @f

m06 db    13, 10, 'And in Sumerian Sexagesimal, base 60', 13, 10, 0
@@: mov   rax, numb                 ;the number to rax
    mov   ebx, 60                   ;the base to rbx
    mov   edi, offset result        ;the destination to edi
    invoke AnyToAny
    mov   byte ptr [edi], 0         ;null terminate the result string
    invoke StdOut, addr m06
    invoke StdOut, addr result
    invoke StdOut, addr newLine

done:
    invoke ExitProcess, 0           ;Error code 0
    ret
main ENDP

end
Title: Re: Binary to displayable text, any base
Post by: sinsi on April 04, 2024, 05:14:09 PM
mov   edi, offset resultUnless you want a write access violation, that should be RDI

mov   al, digits[rdx]You might get a link error about fixups, try this
lea   r9,digits
...
mov   al,[r9][rdx]
If you use lea instead of offset then ML uses a RIP-relative instruction which has two benefits - code is smaller by 4(?) bytes and you will have proper position-independent code

One last niggle
xor   rsi,rsi
;the same but 1 byte smaller
xor   esi,esi
An instruction (all? not sure) that changes the low 32-bit part of a 64-bit register will zero the top 32-bits.
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on April 04, 2024, 06:28:40 PM
Quote from: sinsi on April 04, 2024, 05:14:09 PMOne last niggle
xor  rsi,rsi
;the same but 1 byte smaller
xor  esi,esi
An instruction (all? not sure) that changes the low 32-bit part of a 64-bit register will zero the top 32-bits.
Interesting. Is that a totally reliable (IOW, documented and all) side effect?
Title: Re: Binary to displayable text, any base
Post by: sinsi on April 04, 2024, 06:39:26 PM
Quote from: NoCforMe on April 04, 2024, 06:28:40 PM
Quote from: sinsi on April 04, 2024, 05:14:09 PMOne last niggle
xor  rsi,rsi
;the same but 1 byte smaller
xor  esi,esi
An instruction (all? not sure) that changes the low 32-bit part of a 64-bit register will zero the top 32-bits.
Interesting. Is that a totally reliable (IOW, documented and all) side effect?
It's in the Intel docs
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 05:23:26 AM
Quote from: sinsi on April 04, 2024, 05:14:09 PMmov   edi, offset result
One last niggle
xor   rsi,rsi
;the same but 1 byte smaller
xor   esi,esi
An instruction (all? not sure) that changes the low 32-bit part of a 64-bit register will zero the top 32-bits.

That is really good information. However, I am not going to use it until I become more comfortable with 64 bit code.

I am going to post yet another 64 bit version, then I will get to work on a 32 bit version.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 05, 2024, 05:55:38 AM
Quote from: ahsat on March 31, 2024, 11:44:31 AMThe program was linked using:
polink.exe /SUBSYSTEM:CONSOLE /LARGEADDRESSAWARE:NO

With that option, you can use mov edi, offset somestring. /LARGEADDRESSAWARE:NO means "stick to the 32-bit world, even in 64-bit code". A dangerous road, because you lose the only real advantage that the 64-bit world offers: a large address space.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 06:53:54 AM
Quote from: jj2007 on April 05, 2024, 05:55:38 AMWith that option, you can use mov edi, offset somestring. /LARGEADDRESSAWARE:NO means "stick to the 32-bit world, even in 64-bit code".
I don't know. But I came here to learn 64 bit, so I am stuck with whatever exists.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 07:06:14 AM
Thanks to jimg, I have a new routine, that is universally callable. It now checks the paramaters, saves and restores registers. The program now uses tabs instead of spaces.

I used the following link command to create the program:
polink.exe /SUBSYSTEM:CONSOLE /LARGEADDRESSAWARE:NO /ENTRY:main /OUT:AnyBase.exe AnyBase.obj


TITLE AnyBase

OPTION PROC:PRIVATE ;Don't automatically make procs public

include \masm64\include64\masm64rt.inc

cr equ 13
lf equ 10

.data

result db 65 dup (?) ;max should be 64, plus a null     
newLine db cr, lf, 0 ;cr and lf
numb qword ? ;holds the number being converted

.CODE

;Got to keep the Sumerian happy, base 60 is the max here.
digits db '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx'
maxBase equ $-digits ;Max base number, should be 60

bin2any proc theNumber:qword,
theBase:qword,
theDestination:qword
;----------------------------------------------------------------------------
; Original by Ray Gwinn
; Any binary number to any base.
;----------------------------------------------------------------------------
;
push rbx ;save regs, still can't get uses to work
push rcx
push rdi

mov rdi, theDestination ;destination addr to rdi
mov rbx, theBase ;the desired base to rbx
mov rax, 1 ;rax=1
cmp rbx, rax ;test if valid base
jbe short bin30 ;br if invalid base

cmp rbx, maxBase ;test if base too large
ja short bin30 ;br if base too large

mov rax, theNumber ;get the number to rax
xor ecx, ecx ;zero rcx

@@: push rdx ;save rdx, or a digit
inc rcx ;bump count of loops
xor edx, edx ;zero rdx
div rbx ;generate next digit in rdx
test rax, rax ;test if done
jnz @b ;loop if not done

@@: mov al, digits[rdx] ;get the ascii value
stosb ;save it
pop rdx ;restore rdx, or get next digit
loop @b ;loop till all digits processed

xor eax, eax ;no error
bin30: mov byte ptr [rdi], 0 ;null terminate the string
pop rdi ;restore regs, need for uses to work
pop rcx
pop rbx
ret
bin2any endp

main proc  Public
;----------------------------------------------------------------------------
; Program to demo any number to any base, bases 2 to 60.
;----------------------------------------------------------------------------
;
mov rax, 123456789 ;the number to display
mov numb, rax ;save it in numb
jmp @f

m00 db cr, lf, 'This is the number we will be converting', cr, lf, 0
@@: invoke bin2any, numb, 10, addr result

invoke StdOut, addr m00
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m04 db cr, lf, 'This is the 64 bit number, in hex', cr, lf, 0
@@: invoke bin2any, numb, 16, addr result

invoke StdOut, addr m04
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m05 db    cr, lf, 'This is the 64 bit number, in binary', cr, lf, 0
@@: invoke bin2any, numb, 2, addr result

invoke StdOut, addr m05
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m06 db cr, lf, 'In Sumerian Sexagesimal, base 60', cr, lf, 0
@@: invoke bin2any, numb, 60, addr result

invoke StdOut, addr m06
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m07 db cr, lf, 'In Aztec, Myan and Kaktovik, base 20', cr, lf, 0
@@: invoke bin2any, numb, 20, addr result

invoke StdOut, addr m07
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m08 db cr, lf, 'In Kaktovik, base 5', cr, lf, 0
@@: invoke bin2any, numb, 5, addr result

invoke StdOut, addr m08
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m09 db cr, lf, 'In Ternary, base 3', cr, lf, 0
@@: invoke bin2any, numb, 3, addr result

invoke StdOut, addr m09
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m10 db cr, lf, 'In Quaternary, base 4', cr, lf, 0
@@: invoke bin2any, numb, 4, addr result

invoke StdOut, addr m10
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m11 db cr, lf, 'In Undecimal, base 11', cr, lf, 0
@@: invoke bin2any, numb, 11, addr result

invoke StdOut, addr m11
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

@@: invoke ExitProcess, 0 ;Error code 0
ret

main endp

end
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on April 05, 2024, 08:10:02 AM
Nice.

Still curious why you chose to use "abcdefghijkylmnop" as your Sumerian digits. Wouldn't that be confusing to any Sumerians trying to interpret your results?
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 08:32:49 AM
Quote from: NoCforMe on April 05, 2024, 08:10:02 AMStill curious why you chose to use "abcdefghijkylmnop"
Its a typo, I will correct it. It has been corrected in the post. Thank you, sometimes its hard to get my attention.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 08:49:22 AM
The 32 bit version of Anybase, and uses works there.

I used the following link command:
polink.exe /SUBSYSTEM:CONSOLE /OUT:AnyBase32.exe AnyBase.obj

TITLE AnyBase

OPTION PROC:PRIVATE ;Don't automatically make procs public

include \masm32\include\masm32rt.inc

cr equ 13
lf equ 10

.data

result db 33 dup (?) ;max should be 32, plus a null     
newLine db cr, lf, 0 ;cr and lf
numb dword ? ;holds the number being converted

.CODE

;Got to keep the Sumerian happy, base 60 is the max here.
digits db '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx'
maxBase equ $-digits ;Max base number, should be 60

bin2any proc public uses ebx ecx edi,
theNumber:dword,
theBase:dword,
theDestination:dword
;----------------------------------------------------------------------------
; Original by Ray Gwinn
; Any binary number to any base.
;----------------------------------------------------------------------------
;
mov edi, theDestination ;destination addr to edi
mov ebx, theBase ;the desired base to ebx
mov eax, 1 ;eax=1
cmp ebx, eax ;test if valid base
jbe short bin30 ;br if invalid base

cmp ebx, maxBase ;test if base too large
ja short bin30 ;br if base too large

mov eax, theNumber ;get the number to eax
xor ecx, ecx ;zero ecx

@@: push edx ;save edx, or a digit
inc ecx ;bump count of loops
xor edx, edx ;zero edx
div ebx ;generate next digit in edx
test eax, eax ;test if done
jnz @b ;loop if not done

@@: mov al, digits[edx] ;get the ascii value
stosb ;save it
pop edx ;restore edx, or get next digit
loop @b ;loop till all digits processed

xor eax, eax ;no error
bin30: mov byte ptr [edi], 0 ;null terminate the string
ret
bin2any endp

entry_point proc public
;----------------------------------------------------------------------------
; Program to demo any number to any base, bases 2 to 60.
;----------------------------------------------------------------------------
;
mov eax, 123456789 ;the number to display
mov numb, eax ;save it in numb
jmp @f

m00 db cr, lf, 'This is the number we will be converting', cr, lf, 0
@@: invoke bin2any, numb, 10, addr result

invoke StdOut, addr m00
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m04 db cr, lf, 'This is the 32 bit number, in hex', cr, lf, 0
@@: invoke bin2any, numb, 16, addr result

invoke StdOut, addr m04
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m06 db cr, lf, 'In Sumerian Sexagesimal, base 60', cr, lf, 0
@@: invoke bin2any, numb, 60, addr result

invoke StdOut, addr m06
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m07 db cr, lf, 'In Aztec, Myan and Kaktovik, base 20', cr, lf, 0
@@: invoke bin2any, numb, 20, addr result

invoke StdOut, addr m07
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m08 db cr, lf, 'In Kaktovik, base 5', cr, lf, 0
@@: invoke bin2any, numb, 5, addr result

invoke StdOut, addr m08
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m09 db cr, lf, 'In Ternary, base 3', cr, lf, 0
@@: invoke bin2any, numb, 3, addr result

invoke StdOut, addr m09
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m10 db cr, lf, 'In Quaternary, base 4', cr, lf, 0
@@: invoke bin2any, numb, 4, addr result

invoke StdOut, addr m10
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

m11 db cr, lf, 'In Undecimal, base 11', cr, lf, 0
@@: invoke bin2any, numb, 11, addr result

invoke StdOut, addr m11
invoke StdOut, addr result
invoke StdOut, addr newLine
jmp @f

@@: invoke ExitProcess, 0 ;Error code 0
ret

entry_point endp

end entry_point
Title: Re: Binary to displayable text, any base
Post by: sinsi on April 05, 2024, 09:16:02 AM
USES still works with ML64 but only with the default prologue/epilogue. I guess that MASM64's prologue doesn't bother.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 10:00:10 AM
Quote from: sinsi on April 05, 2024, 09:16:02 AMuses still works with ML64 but only with the default prologue/epilogue.
Can you show me in an example with code? I am sorry to be so behind and slow.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 05, 2024, 10:21:25 AM
Quote from: ahsat on April 05, 2024, 10:00:10 AMI am sorry to be so behind and slow

You are remarkably fast for your age, Ray. Truth is that 64-bit code is a can of worms. The PROLOGUE macro determines what happens when you write e.g. MyAlgo proc param1, the EPILOGUE macro specifies what the "instruction" ret does (it is a macro, yeah).

In 32-bit land, uses esi simply pushes esi on entry into the proc and pops it before the ret.

I bet that 90% of our members here (sinsi excluded) don't know what uses rsi does in 64-bit code. I had to set up a 64-bit test with ml64 and launch the debugger to find out. Here is the code:
include \masm64\include64\masm64rt.inc
.code
MyAlgo proc uses rsi arg1, arg2
  ret
MyAlgo endp
entry_point proc
Local pContent:QWORD, ticks:QWORD        ; OPT_Assembler ml64
  lea rax, entry_point
  conout "The entry point is at ", hex$(rax), lf
  int 3
  invoke MyAlgo, 123h, 456h
  invoke ExitProcess, 0                        ; terminate process
entry_point endp
end

The int 3 makes the debugger stop there. When hitting F7, you see the following on entry to MyAlgo:
0000000140001069     | 48:C7C1 23010000                | mov rcx,123               |
0000000140001070     | 48:C7C2 56040000                | mov rdx,456               |
0000000140001077     | E8 84FFFFFF                     | call <sub_140001000>      |
...
0000000140001000 <su | C8 8000 00                      | enter 80,0                |
0000000140001004     | 48:83EC 60                      | sub rsp,60                |
0000000140001008     | 48:894D 10                      | mov [rbp+10],rcx          |
000000014000100C     | 48:8955 18                      | mov [rbp+18],rdx          |
0000000140001010     | C9                              | leave                     |
0000000140001011     | C3                              | ret                       |

Do you see any attempt to save rsi? I don't.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 10:39:07 AM
Quote from: jj2007 on April 05, 2024, 10:21:25 AMI would have to set up a 64-bit test with ml64 and launch the debugger to find out.
I have, and it does nothing, zip. No pushes or pops of anything with "uses esi".

I understand what you guys are saying about 32 bit is still better to write programs with. But I want to know what Intel is selling in their 64 bit products, as well as possibility developing a few programs. So, I want to use 64 bit, if for nothing else, to learn what it does.
Title: Re: Binary to displayable text, any base
Post by: sinsi on April 05, 2024, 10:45:21 AM
Previously... (https://masm32.com/board/index.php?msg=128262)

I'm pretty sure that include \masm64\include64\masm64rt.inc also includes a custom prologue.
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on April 05, 2024, 11:08:33 AM
Quote from: jj2007 on April 05, 2024, 10:21:25 AMinclude \masm64\include64\masm64rt.inc
.code
MyAlgo proc uses rsi arg1, arg2
  ret
MyAlgo endp
entry_point proc
Local pContent:QWORD, ticks:QWORD        ; OPT_Assembler ml64
  lea rax, entry_point
  conout "The entry point is at ", hex$(rax), lf
  int 3
  invoke MyAlgo, 123h, 456h
  invoke ExitProcess, 0                        ; terminate process
entry_point endp
end

0000000140001069    | 48:C7C1 23010000                | mov rcx,123              |
0000000140001070    | 48:C7C2 56040000                | mov rdx,456              |
0000000140001077    | E8 84FFFFFF                    | call <sub_140001000>      |
...
0000000140001000 <su | C8 8000 00                      | enter 80,0                |
0000000140001004    | 48:83EC 60                      | sub rsp,60                |
0000000140001008    | 48:894D 10                      | mov [rbp+10],rcx          |
000000014000100C    | 48:8955 18                      | mov [rbp+18],rdx          |
0000000140001010    | C9                              | leave                    |
0000000140001011    | C3                              | ret                      |

Do you see any attempt to save rsi? I don't.

It's AI,man; the assembler is so smart it knows you haven't touched RSI so it doesn't bother saving and restoring it. It's a mind reader.
Title: Re: Binary to displayable text, any base
Post by: zedd on April 05, 2024, 11:21:35 AM
masm64 uses "USING" (not uses) reg... and the SaveRegs/RestoreRegs  macros for saving and restoring registers.

 64 bit Stackframe register preservation macros (https://masm32.com/board/index.php?topic=7285.0)
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 11:30:58 AM
Quote from: sinsi on April 05, 2024, 10:45:21 AMI'm pretty sure that include \masm64\include64\masm64rt.inc also includes a custom prologue.
Okay, that's great. Can you show me how to use it with code? It does not seem to work for me in Anybase.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 11:50:31 AM
Quote from: NoCforMe on April 05, 2024, 11:08:33 AMIt's AI,man; the assembler is so smart it knows you haven't touched RSI so it doesn't bother saving and restoring it. It's a mind reader.
I just made sure for myself, and that is not true.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 11:57:34 AM
Quote from: sudoku on April 05, 2024, 11:21:35 AMmasm64 uses "USING" (not uses)
Using seems to be an in line macro.
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on April 05, 2024, 12:14:14 PM
Quote from: ahsat on April 05, 2024, 11:50:31 AM
Quote from: NoCforMe on April 05, 2024, 11:08:33 AMIt's AI,man; the assembler is so smart it knows you haven't touched RSI so it doesn't bother saving and restoring it. It's a mind reader.
I just made sure for myself, and that is not true.

Are you sure?

Hint: I don't use smileys or emojis. Context, man, context.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 05, 2024, 12:35:12 PM
Quote from: NoCforMe on April 05, 2024, 12:14:14 PMAre you sure?
Yes, I am sure.
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 05, 2024, 07:29:38 PM
Quote from: NoCforMe on April 05, 2024, 11:08:33 AMthe assembler is so smart it knows you haven't touched RSI so it doesn't bother saving and restoring it. It's a mind reader

I know that was irony, but being a curious guy, I tried it:

option prologue:prologuedef
option epilogue:epiloguedef
MyAlgo proc uses rsi arg1, arg2
  mov rsi, 789h
  invoke GetTickCount
  ret
MyAlgo endp

0000000140001000 <su | 55                              | push rbp                  |
0000000140001001     | 48:8BEC                         | mov rbp,rsp               |
0000000140001004     | 56                              | push rsi                  |
0000000140001005     | 48:C7C6 89070000                | mov rsi,789               |
000000014000100C     | FF15 BE110000                   | call [<GetTickCount>]     |
0000000140001012     | 5E                              | pop rsi                   |
0000000140001013     | C9                              | leave                     |
0000000140001014     | C3                              | ret                       |

That's lovely: ML64.exe performs an API call with a misaligned stack! Compliments, Microsoft :thumbsup:

So ML64 is indeed a mind reader, but a very dumb one :cool:
Title: Re: Binary to displayable text, any base
Post by: sinsi on April 05, 2024, 08:05:22 PM
ML64 does what you tell it to do.
It doesn't know about the MS x64 ABI, or the Intel x64 ABI, or even the Linux x64 ABI  :biggrin:

Nothing to get in your way of pure ASM code.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 06, 2024, 01:00:09 AM
What version of ml64.exe are you using? I get the following with your code. No "push esi" or "pop esi".

    22: .CODE
    23:
C8 80 00 00          enter       80h,0 
48 83 EC 60          sub         rsp,60h 
48 89 4D 10          mov         qword ptr [arg1],rcx 
48 89 55 18          mov         qword ptr [arg2],rdx 
    25:   mov rsi, 789h
48 C7 C6 89 07 00 00 mov         rsi,789h 
    26:   invoke GetTickCount
FF 15 B3 3F 00 00    call        qword ptr [__imp_GetTickCount (0D95000h)] 
C9                   leave 
C3                   ret 
    27:   ret
    28: MyAlgo endp
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 06, 2024, 01:14:06 AM
Quote from: ahsat on April 06, 2024, 01:00:09 AMWhat version of ml64.exe are you using?

Microsoft (R) Macro Assembler (x64) Version 14.30.30705.0
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 06, 2024, 02:03:44 AM
Quote from: jj2007 on April 06, 2024, 01:14:06 AMMicrosoft (R) Macro Assembler (x64) Version 14.30.30705.0
Microsoft (R) Macro Assembler (x64) Version 14.39.33522.0

The above is my version of my version of ML64.exe. There is obviously a big difference. Mine never produces any code for "uses" no matter what I do. I will look for an older copy of ml64.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 06, 2024, 03:20:25 AM
Quote from: jj2007 on April 05, 2024, 07:29:38 PMThat's lovely: ML64.exe performs an API call with a misaligned stack!
What are you talking about here? What is wrong with the stack?
Title: Re: Binary to displayable text, any base
Post by: zedd on April 06, 2024, 04:11:49 AM
Quote from: ahsat on April 06, 2024, 03:20:25 AMWhat are you talking about here? What is wrong with the stack?
The stack must be aligned to 16 for ml64. Pushing a single 64 bit register misaligns the stack by 8. Two 64 bit registers may be pushed to keep the 16 byte alignment, but don't forget to pop two in that case.
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on April 06, 2024, 04:39:20 AM
In my book, yet another reason to just avoid 64-bit programming altogether ...
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 06, 2024, 07:32:22 AM
Quote from: sudoku on April 06, 2024, 04:11:49 AM
Quote from: ahsat on April 06, 2024, 03:20:25 AMWhat are you talking about here? What is wrong with the stack?
The stack must be aligned to 16 for ml64. Pushing a single 64 bit register misaligns the stack by 8. Two 64 bit registers may be pushed to keep the 16 byte alignment, but don't forget to pop two in that case.
Thank you. That seems odd, do you know why?
Title: Re: Binary to displayable text, any base
Post by: zedd on April 06, 2024, 07:37:26 AM
It's a requirement for the intel win64 abi.
When you call a function, it requires the 16 byte stack alignment.

Do a google search for "win64 abi stack alignment" for better explanation... I can get a link later, I'm on my iPad at the moment. (Hard to copy and paste links from the iPad)

Later:

 info on 64 bit stack alignment from Microsoft  (https://learn.microsoft.com/en-us/cpp/build/stack-usage?view=msvc-170)
Title: Re: Binary to displayable text, any base
Post by: jj2007 on April 06, 2024, 07:47:13 AM
Quote from: ahsat on April 06, 2024, 07:32:22 AMThat seems odd, do you know why?

The 16-byte alignment is required by Windows. Why exactly is not well documented (to my knowledge), but there are many SIMD instructions like movaps which fail miserably if the address is not aligned to 16 bytes; that could be the underlying reason.
Title: Re: Binary to displayable text, any base
Post by: sinsi on April 06, 2024, 08:35:10 AM
Quote from: ahsat on April 06, 2024, 01:00:09 AMWhat version of ml64.exe are you using? I get the following with your code. No "push esi" or "pop esi".

    22: .CODE
    23:
C8 80 00 00          enter      80h,0 
48 83 EC 60          sub        rsp,60h 
48 89 4D 10          mov        qword ptr [arg1],rcx 
48 89 55 18          mov        qword ptr [arg2],rdx 
    25:  mov rsi, 789h
48 C7 C6 89 07 00 00 mov        rsi,789h 
    26:  invoke GetTickCount
FF 15 B3 3F 00 00    call        qword ptr [__imp_GetTickCount (0D95000h)] 
C9                  leave 
C3                  ret 
    27:  ret
    28: MyAlgo endp
You can tell that's hutch's prologue, and as I've said numerous times, his prologue doesn't use USES.
To see how ML64 does it, use the default prologue
option prologue:prologuedef
option epilogue:epiloguedef
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 06, 2024, 12:12:01 PM
Quote from: sinsi on April 06, 2024, 08:35:10 AM
Quote from: ahsat on April 06, 2024, 01:00:09 AMWhat version of ml64.exe are you using? I get the following with your code. No "push esi" or "pop esi".

    22: .CODE
    23:
C8 80 00 00          enter      80h,0 
48 83 EC 60          sub        rsp,60h 
48 89 4D 10          mov        qword ptr [arg1],rcx 
48 89 55 18          mov        qword ptr [arg2],rdx 
    25:  mov rsi, 789h
48 C7 C6 89 07 00 00 mov        rsi,789h 
    26:  invoke GetTickCount
FF 15 B3 3F 00 00    call        qword ptr [__imp_GetTickCount (0D95000h)] 
C9                  leave 
C3                  ret 
    27:  ret
    28: MyAlgo endp
You can tell that's hutch's prologue, and as I've said numerous times, his prologue doesn't use USES.
To see how ML64 does it, use the default prologue
option prologue:prologuedef
option epilogue:epiloguedef


Finally, something that I understand, thank you. I am sorry I didn't understand if/when you told me previously. I will try to find the masm64 SDK docs to see what else hutch is doing for me.
Title: Re: Binary to displayable text, any base
Post by: sinsi on April 06, 2024, 01:18:29 PM
Quote from: ahsat on April 06, 2024, 12:12:01 PMI will try to find the masm64 SDK docs to see what else hutch is doing for me.

:badgrin:  :badgrin:  :badgrin:
Good luck with that. I've been forced to write my own prologue/epilogue and invoke macros.
Maybe I'll clean them up and post them here. They don't play well with hutch's masm64 stuff though...
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 06, 2024, 02:54:27 PM
Quote from: sinsi on April 06, 2024, 01:18:29 PM
Quote from: ahsat on April 06, 2024, 12:12:01 PMI will try to find the masm64 SDK docs to see what else hutch is doing for me.

:badgrin:  :badgrin:  :badgrin:
Good luck with that. I've been forced to write my own prologue/epilogue and invoke macros.
Maybe I'll clean them up and post them here. They don't play well with hutch's masm64 stuff though...

I thought the masm 64 SDK was largely just the inc files, defining the equates and prototypes needed to call the Windows APIs. I didn't realize he was trying to make ml64 as complete an assembler as the 32 bit version. I now understand why Microsoft tries to stop people from downloading the SDK. I assume that Hutch has moved on, or passed away, and that development on the SDK has slowed.

I would like to see your prologue/epilogue macros if you ever decide to release them. I haven't done much macro coding, so I wouldn't even try.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 06, 2024, 04:27:17 PM
Go to ebay, search "masm assembler", then hit the end key. The last Masm, 6.11 I think, sells for $300+. One guy is asking for $600 for a copy still in shrink wrap.
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on April 07, 2024, 06:48:02 AM
Quote from: ahsat on April 06, 2024, 02:54:27 PMI assume that Hutch has moved on, or passed away [...]
The latter. And yes, MASM64 development has basically stalled here.
Title: Re: Binary to displayable text, any base
Post by: ahsat on April 07, 2024, 09:13:49 AM
Quote from: NoCforMe on April 07, 2024, 06:48:02 AMThe latter. And yes, MASM64 development has basically stalled here.
What country did Hutch live in?
Title: Re: Binary to displayable text, any base
Post by: NoCforMe on April 07, 2024, 09:25:57 AM
Australia.