## converting decimal into binary string

The place for codemasters or beginners to talk about programming any language for the Spectrum.
777
Manic Miner
Posts: 501
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

### converting decimal into binary string

so like the opposite of the bin function. in basic if possible. it only needs to be an 8 bit number. like a dec\$ function?
Last edited by 777 on Fri Dec 11, 2020 5:26 pm, edited 1 time in total.
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
PeterJ
Posts: 6746
Joined: Thu Nov 09, 2017 7:19 pm
Location: Surrey, UK

### Re: converting decimal into binary

You would need to code it @777

An easy method of converting decimal to binary number equivalents is to write down the decimal number and to continually divide-by-2 (two) to give a result and a remainder of either a “1” or a “0” until the final result equals zero
777
Manic Miner
Posts: 501
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

### Re: converting decimal into binary

PeterJ wrote: Fri Dec 11, 2020 5:05 pm You would need to code it @777

An easy method of converting decimal to binary number equivalents is to write down the decimal number and to continually divide-by-2 (two) to give a result and a remainder of either a “1” or a “0” until the final result equals zero
i wouldnt know where to begin
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
PeterJ
Posts: 6746
Joined: Thu Nov 09, 2017 7:19 pm
Location: Surrey, UK

### Re: converting decimal into binary string

Try this [mention]777[/mention]

T contains the number you want to convert (between 0 and 255)

[mention]TMD2003[/mention] has encouraged me to explore BASIC more. I had forgotten much of what I had learnt as a child!

There is an SZX snapshot here (128K format):

https://gofile.io/d/YYNLVC
uglifruit
Manic Miner
Posts: 675
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

### Re: converting decimal into binary string

It's quite possible that this is a worse way of doing it, but it might prove useful:

Code: Select all

``````10 INPUT x:PRINT x,
20 GOSUB 200:PRINT b\$
30 GOTO 10

199 REM DEC to BIN.  Input X, Output B\$, corrupts C,X
200 LET b\$="":LET c=128							; sets up a blank string, and a counter.
; counter=128 gives an 8 bit number, 32768 would be 16 bit
210 LET b\$=b\$+str\$ (x>=c)						; if x is greater or equal to counter, then add a "1" to the string, otherwise add "0"
220 LET x=x-(x>=c)*c							; reduce x by the counter value, if x is >= counter (i.e. if the bit was set)
230 LET c=c/2								; halve the counter
240 IF c>=1 THEN GOTO 210						; if the counter is 1 or more, then move to the next bit
250 RETURN
``````
CLEAR 23855
uglifruit
Manic Miner
Posts: 675
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

### Re: converting decimal into binary string

Actually a bit easier to understand, and a slightly quicker, I think:

Code: Select all

``````10 INPUT X:PRINT X,
20 GOSUB 200:PRINT B\$
30 GOTO 10

199 REM DEC TO BIN.  INPUT X, OUTPUT B\$, CORRUPTS C,X
200 LET B\$="":LET C=128							; b\$ set as blank string.  counter c gives number of bits
; c=128 8 bit number, c=32768 16 bit number
210 IF X>=C THEN LET B\$=B\$+"1":LET X=X-C:GOTO 230	; Set the string and adds a "1" if it's greater than counter
; and reduces X by the current counter value
220 LET B\$=B\$+"0"								; Otherwise adds a "0" to the output string
230 LET C=C/2:IF C>=1 THEN GOTO 210				; Halves the counter, and sees if there is more bits to do!
250 RETURN
``````
CLEAR 23855
TMD2003
Dynamite Dan
Posts: 1930
Joined: Fri Apr 10, 2020 9:23 am
Location: Airstrip One
Contact:

### Re: converting decimal into binary string

[mention]777[/mention]: I started programming the Spectrum when I was 8 as well (and the ZX81 at 4 - you can imagine what that looked like). I started programming the Spectrum in machine code at... 41. I might not be fast, but I get there in the end!

This is one of those problems that's an ideal opportunity to solve along the course of my machine code quest. Only thing is, I've not yet reached the point where I can read BASIC-assigned variables with machine code - but I can do most of it, just POKE one value, define an empty string b\$, and execute the code. I've taken 64 bytes, which are assembled from 65000 to 65064 in this routine. As it stands, with the fixed numbers in the DATA lines, this has to stay at 65000, but the assembler code I've posted below the BASIC listing can be pasted into SPIN and assembled anywhere, and it'll work out all the new addresses to pick the values from and JR Z to.

Essentially, assemble to ad, POKE the value v to be converted into ad+65, and LET l=USR ad. The machine code will initially poke the value 48 into addresses ad+66 to ad+73, then analyse the value v and for every 1 in the binary value, it will increase the corresponding address from 48 to 49. All the BASIC then has to do is PEEK the addresses and add CHR\$ of the CODE stored at that address to b\$.

I've made this loop v from 0 to 255 so it displays all the values and shows how fast the routine is. You can paste this into a text editor, get shot of the REMs, bunch multiple statements into fewer lines, and cut out anything extraneous. Then paste that into BASin, renumber it as required, and save it as a Z80 snapshot. The code can saved and reloaded, just don't forget to CLEAR one less than the start address.

Code: Select all

``````  10 REM decimal to binary with machine code
20 CLEAR 64999
40 GO SUB 9000
50 FOR v=0 TO 255
60 LET b\$=""
100 LET b\$=b\$+CHR\$ (PEEK n)
110 NEXT n
120 POKE 23692,255
130 PRINT v;TAB 4;b\$
140 NEXT v
999 STOP
9000 REM machine code
9010 RESTORE 9900
9040 POKE n,byte
9050 NEXT n
9060 RETURN
9900 DATA 33,42,254,6,8,54,48,35,16,251
9910 DATA 58,41,254,33,42,254,203,127,40,1,52,35,203,119,40,1,52,35,203,111,40,1,52,35,203,103,40,1,52
9920 DATA 35,203,95,40,1,52,35,203,87,40,1,52,35,203,79,40,1,52,35,203,71,40,2,52,35,201
``````
Meanwhile, here's what I wrote in SPIN's assembler to make it work, with annotations as to what the DATA lines correspond to...

Code: Select all

``````; 9900 DATA...

init:	ld hl,b7	; put address "b7" into HL
ld b,8		; loop 8 times
loop1:	ld (hl),48	; POKE address held in HL with 48
inc hl		; point HL to next address
djnz loop1	; DEC B and loop until B=0
; eight addresses after STORE are loaded with the CODE for "0"

; 9910 DATA...

main:	ld a,(store)	; put the stored value into accumulator
ch7:	ld hl,b7	; put HL back to address "b7" again
bit 7,a		; check bit 7 of A
jr z,ch6	; if bit 7 is 0, skip the next lines
inc (hl)	; if bit 7 is 1, increase value held in "b7" by 1, i.e it is now CODE "1"
ch6:	inc hl		; first now increase the address HL points to, to "b6"
bit 6,a		; and so on...
jr z,ch5
inc (hl)
ch5:	inc hl
bit 5,a
jr z,ch4
inc (hl)
ch4:	inc hl
bit 4,a
jr z,ch3
inc (hl)

; 9920 DATA...

ch3:	inc hl
bit 3,a
jr z,ch2
inc (hl)
ch2:	inc hl
bit 2,a
jr z,ch1
inc (hl)
ch1:	inc hl
bit 1,a
jr z,ch0
inc (hl)
ch0:	inc hl
bit 0,a
jr z,finale
inc (hl)
inc hl
finale:	ret

; these aren't in the DATA statements - you POKE the value shown, the machine code works out the other eight bytes

store:	defb 0	; start address + 65 - POKE value to convert here
b7:	defb 0	; these will be 48 (CODE "0") or 49 (CODE "1") at end of routine.
b6:	defb 0
b5:	defb 0
b4:	defb 0
b3:	defb 0
b2:	defb 0
b1:	defb 0
b0:	defb 0``````
Spectribution: Dr. Jim's Sinclair computing pages.
Features my own programs, modified type-ins, RZXs, character sets & UDGs, and QL type-ins... so far!
Manu128k
Dizzy
Posts: 80
Joined: Tue Aug 13, 2019 9:45 pm
Location: Spain
Contact:

### Re: converting decimal into binary string

If the number would always be between 0 and 255 and you can spare a single square of the screen for a moment, then there is a much simpler way IMHO, maybe faster too. Just POKE it to the screen, and read 1 bit each time with point(). No divisions and you got your number in binary format. If you think this approach could be of some use for you, I can elaborate further.
uglifruit
Manic Miner
Posts: 675
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

### Re: converting decimal into binary string

Completely stealing [mention]TMD2003[/mention]'s the idea of doing it in hybrid m/c and BASIC

I thought, why not modify the BASIC program itself?
I wrote a quick assembly routine to that modfies LINE 1 of the program from LET b\$="FAKETEXT" to LET b\$="00101100" (or whatever the required string is).
Very quick in operation, just one POKE required with the input variable, then just RANDOMIZE USR address of routine, followed by GOSUB 1 to get the result in b\$.

Code: Select all

`````` ;                                              ; DEC to BIN
; LINE 1 of BASIC should be    1 LET b\$="12345678":RETURN

; This is a RELOCATABLE routine

org     65000

ld      a,0                     ;  ADDRESS of this routine + 1 is POKED with number to be BIN'd

ld      hl,(23635)              ;  Address Of The System Variable pointing at the BASIC Program (PROG)
ld      de,8                    ;  first line of BASIC should be LET b\$="12345678" starts at that System Variable + 9
add     hl,de                   ;  HL now points at the first byte of the string

ld      b,8                     ; counter 8 times
fill_loop:
inc     hl
djnz    fill_loop               ; do it again if counter is not zero

; HL currently points at address of last character in string

ld      b,8                     ; counter
; A still contains the number
change_loop:
rra                             ; rotate bitwise right.  Leftmost bit becomes carry flag
jr      nc,dont_change          ; if carry flag isn't set, then don't do anything
ld      (hl),"1"                ; but if it IS set, then make the string character a '1'
dont_change:
dec     hl                      ; move to the previous string address
djnz    change_loop             ; do this 8 times in total

ret                             ; back to BASIC
``````
If you'd like it in the BASIC program itself, then it's only 27 bytes long.
(defb 62,0,42,83,92,17,8,0,25,6,8,35,54,48,16,251,6,8,31,48,2,54,49,43,16,248,201)

For example:

.z80 file of the above, to have a play:
https://1drv.ms/u/s!AmvYCHV8PMQkhCZLASR ... 4?e=ghfoU3

And here it is doing all the numbers from 0-255, very rapidly, from BASIC

.z80 file of that just here
https://1drv.ms/u/s!AmvYCHV8PMQkhCfnN_d ... W?e=xTBs18

I can't seem to post pics at a useful size. Apologies.
edited: because I'm an idiot.
CLEAR 23855
uglifruit
Manic Miner
Posts: 675
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

### Re: converting decimal into binary string

I wasn't happy about the GOSUB to the first line to call the m/code routine. The RETURN statement got in the way, when running.

I realised that if I made the first line a DEF FN statement :
1. it'll be skipped when the program is RUN
2. didn't require an ugly RETURN statement
3. it can be made to run the m/code routine, that modifies itself.

So a more elegant BASIC version would be;

Code: Select all

``````1 DEF FN b\$()=("" AND USR 65000)+"XXXXXXXX"     ; this XXXXXXXX text string is changed when the routine at 65000 is called.
; The bracketed section will be interpreted and the routine at 65000 called
; *before* the rest of the string (that is changed) is appended
10 FOR A=0 TO 255
20 POKE 65001,A
30 PRINT AT 10,0;A,FN B\$()
40 NEXT A
50 STOP

99 REM SET UP THE MACHINE CODE ROUTINE AT 65000
100 CLEAR 64999:FOR Z=65000 TO 65026:READ X:POKE Z,X:NEXT Z
110  DATA 62,0,42,83,92,17,28,0,25,6,8,35,54,48,16,251,6,8,31,48,2,54,49,43,16,248,201
``````
.z80 Snapshot here: https://1drv.ms/u/s!AmvYCHV8PMQkhChkkXL ... i?e=glTlPM

The only change to the assembly routine is where the text string is now located with respect to the start of the basic program. It is now 29 bytes in, assuming the 1st line is as written.

Code: Select all

``````               org     65000
ld      a,0                       ; ADDRESS_of_this_routine + 1 is POKED with number to be converted to a BIN string
ld      hl,(23635)             ; Address Of The System Variable pointing at the BASIC Program (PROG)
ld      de,28                ; the first line of BASIC should be 1 DEF FN b\$=("" AND USR 65000)+"XXXXXXXX"
; meaning the text string starts at that System Variable + 29
add     hl,de                   ;  HL now points at the first byte of the string

ld      b,8                     ; counter 8 times
fill_loop:
inc     hl
djnz    fill_loop               ; do it again if counter is not zero

; HL currently points at address of last character in string

ld      b,8                     ; counter
; A still contains the number
change_loop:
rra                             ; rotate bitwise right.  Leftmost bit becomes carry flag
jr      nc,dont_change          ; if carry flag isn't set, then don't do anything
ld      (hl),"1"                ; but if it IS set, then make the string character a '1'
dont_change:
dec     hl                      ; move to the previous string address
djnz    change_loop             ; do this 8 times in total

ret                             ; back to BASIC``````
CLEAR 23855