converting decimal into binary string
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
1 plot rnd*255,rnd*175
2 goto 1
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
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
Re: converting decimal into binary
i wouldnt know where to beginPeterJ 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 started programming the spectrum when i was 8 :-
1 plot rnd*255,rnd*175
2 goto 1
1 plot rnd*255,rnd*175
2 goto 1
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
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
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
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
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.
Meanwhile, here's what I wrote in SPIN's assembler to make it work, with annotations as to what the DATA lines correspond to...
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
30 LET ad=65000
40 GO SUB 9000
50 FOR v=0 TO 255
60 LET b$=""
70 POKE ad+65,v
80 LET l=USR ad
90 FOR n=ad+66 TO ad+73
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
9020 FOR n=ad TO ad+64
9030 READ byte
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
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!
Features my own programs, modified type-ins, RZXs, character sets & UDGs, and QL type-ins... so far!
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.
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$.
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.
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
ld (hl),"0" ; fill the string with "0"s to start with
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
(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
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;
.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.
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
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
ld (hl),"0" ; fill the string with "0"s to start with
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