-1

It does not generate the intended randomness.

I thought starting with a seed like $66 and xoring the two last lower bit and ror would give me the next random number and so on but it only shows $B3 and does not change at all.

How am I meant to feed? The line above random displays the number on portc as I want two numbers displayed after each other.

I am only using avr studio 4 for atmega 8535 at 1Mhz.

> ;Program to random numbers  on port C
> 
> ;Stack and Stack Pointer Addresses  .equ     SPH    =$3E             
> ;High Byte Stack Pointer Address   .equ     SPL    =$3D             
> ;Low Byte Stack Pointer Address 
> 
> .equ     RAMEND =$25F             ;Stack Address 
> 
> ;Port Addresses 
> 
> .equ     PORTC  =$15              ;Port C Output Address 
> 
> .equ     DDRC   =$14              ;Port C Data Direction Register
> Address 
> 
> .equ     numberoneddr=DDRC
> 
> .equ     numberoneport=portc
> 
> .equ     numbertwoddr=DDRC
> 
> .equ     numbertwoport=portc
> 
> .equ     delayCount=21
> 
> .equ    random1 =$66
> 
> ;Register Definitions 
> 
> .def    numberone   =r1               ;Register to store data pointed
> to by Z 
> 
> .def    numbertwo   =r2
> 
> .def     temp   =r16              ;Temporary storage register 
> 
> 
> 
> reset:
> 
> ; initialize stack pointer. Done automatically at reset on many AVRs
> 
>   ldi temp, low  (RAMEND)
> 
>   out spl, temp
> 
>   ldi temp, high (RAMEND)
> 
>   out sph, temp
> 
> 
> 
> 
> ;port initialisation
> 
> ldi temp,$FF
> 
> out numberoneddr,temp
> 
> out numberoneport,temp
> 
> out numbertwoddr,temp
> 
> out numbertwoport,temp
> 
> 
> 
> ;Program Initialisation 
> 
> ldi temp,$66
> 
> rcall random
> 
> mov   numberone, temp
> 
> out numberoneport,numberone
> 
> rcall random
> 
> mov   numbertwo, temp
> 
> out numberoneport,numbertwo
> 
> 
> 
> 
> random: mov r19,temp
> 
> ldi r17, 0x01
> 
> eor r19,r17
> 
> ror r19
> 
> mov temp,r19
> 
> ret
> 
> 
> 
> delay:
>         clr r20
> 
>       clr r21
> 
>       ldi r22, delayCount
> 
> loopDelay:
> 
>       dec r20
> 
>       brne loopDelay
> 
>       dec r21
> 
>       brne loopDelay
> 
>       dec r22
> 
>       brne loopDelay
> 
>         ret
Community
  • 1
  • 1
alex
  • 7
  • 5
  • use code block (or intend by 4 spaces) for source code, add more info like what MCU, what exactly is wrong, ... is your code working on PC? if not try to trace it what is wrong ... and port to MCU asm when it is working. If you have breakpoint/trace capabilities on your MCU then you can skip the PC part. Right now your question is really just why is this code not working which is off-topic so voting to Close for now – Spektre Mar 27 '15 at 07:26
  • it does not generate the intended randomness, i taught starting with a seed like $66 and xoring the two last lower bit and ror would give me the next random number and so on but it only shows $B3 and does not change at all any help would be appreciated by the way i am only using avr studio 4 for atmega 8535 at 1Mhz – alex Mar 27 '15 at 07:31
  • you are feeding `temp=$66` each random call so the result is always the same ... you should feed the temp only once. also I would add a swap of bits (not just `ror`) it usually leads for better randomness. also what are the 3 lines above `random:` label do ... they are not executed on `call random` !!! – Spektre Mar 27 '15 at 07:36
  • i am a bit confuse on the seeding bit please could you please help explain how i am meant to feed without using temp. the line above random displays the number on portc as i want two numbers displayed after each other – alex Mar 27 '15 at 07:39
  • execute `ldi temp,$66` at program init and remove it from random subroutine. Also temp is a bad name for this ... when your program grows try to rename it to `random_tmp` for example – Spektre Mar 27 '15 at 07:41
  • i have just added the whole code i tried moving temp, $66 out the random subroutine but it still does the same – alex Mar 27 '15 at 08:08
  • i really need an insight on this please please any help will be appreciated, i am new to assembly thank you in advance. – alex Mar 27 '15 at 08:21
  • when you edit select whole part of text that should be source code and click on the icon `{ }` it will auto intend it to proper format the output. but you need be at level0 of text if you are not (under bullet or something) then add line like `here the code:` without intendation add empty line and then the code ... then it will work as it should – Spektre Mar 27 '15 at 08:56
  • thank you i will try an see how it will work. – alex Mar 27 '15 at 09:08
  • i appreciate the help but i am really new to assembly and my knowledge on the matter is limited, the syntax command on your code is quite complex to the one i am using, by the way i am using avr atmega 8535 – alex Mar 27 '15 at 09:20
  • syntax is the same but on x86 the instructions have a bit different names for example you have `mov,ldi` on x86 is only `mov` for both ... look here http://home.myfairpoint.net/fbkotler/nasmdocc.html and just search the unknown instruction, ... `[]` means memory access, stosw is the same as `mov [es:di],ax` and `inc di` and `dec cx` ... – Spektre Mar 27 '15 at 09:24
  • btw why are you not using C/C++ ? with bigger programs is asm useless ... inside C/C++ you can still use asm for speed ... – Spektre Mar 27 '15 at 09:28
  • its a project and the instructions are to be in assembly – alex Mar 27 '15 at 16:51
  • just a silly but important question you need random or pseudo-random generator ? – Spektre Mar 28 '15 at 09:49
  • sorry been really busy with this project haven`t come around but yes i real do and my deadline is tomorrow, i need to generate a random number and display it on a multiplex seven segment display. – alex Mar 29 '15 at 14:17
  • what will be the source of randomness? (you can not get random numbers by program, you can get only pseudo random numbers) so for true random generator you need some sort of random input like antena receiving noise, or some sensor measuring random enough process but to build that is far more complex then would one think ... – Spektre Mar 29 '15 at 18:47
  • yeah it is a pseudo random numbers – alex Mar 29 '15 at 19:14
  • what's the "intended randomness"? If you're building the hardware then I think it's much easier to read random noise from the ADC to feed the random generator – phuclv Mar 05 '18 at 16:59

1 Answers1

1

After some searching through ancient asm source code archives of mine I found this for x86 MSDOS NASM platform I was using back in the days:

;.rnd       ;al=rnd num <0,ah>;

.rnd:   pusha
    mov cx,ax

.rnd0:  mov bx,[cs:.rnddat]

    mov ax,[cs:.rndtim]
    xor al,bh
    add ah,bh
    rcr ax,3
    xor al,bl
    rcl ax,2

.rnd2:  cmp al,ch
    jbe .rnde
    sub al,ch
    or  ch,ch
    jnz .rnd2
    sub al,al

.rnde:  mov ah,bl
    mov [cs:.rnddat],ax
    or  al,1

    xor ax,[fs:046Ch]
    add [cs:.rndtim],ax
    popa
    mov al,[cs:.rnddat]
    ret
.rnddat:db  0,0
.rndtim:dw  0

The idea is to have some stored number do some basic ALU operations like +,*,/,<<,>>,&,^ but ensure that no saturation occurs and usually swap of H,L of some value to keep the randomness in check. So port this to your asm but I strongly recommend to code it and try on PC first to see if the randomness is OK for your task.

BTW you can use also the program memory or any ROM content as base for randomness ... this is also exploiting the internal RTC block so you have to omit that part or add a timer or just loop through bunch of non empty data instead.

[0000:046C] are 4 Bytes master clock count (long integer) 0 = midnight and increments until a 24 hour equiv.

I found even older demo of mine called NoSignal (from 1997 in TASM) which have rnd inside:

    .386P
    IDEAL
    MODEL TINY

    CODESEG
    STARTUPCODE
main:   mov ax,19   ;320*200*256
    int 16
    push 0A000h ;Video segment
    pop es      ;keyboard test,speaker delay v si=256

l0: ror ax,cl       ;rnd...ax
    add ax,di
    stosw       ;plot...
    loop r1     ;speaker delay...
    mov cx,si
    out 61h,al
r1: or di,di
    jnz l0
    push ax
    mov ah,1    ;test keyboard
    int 16h
    pop ax
    jz l0

ende:   sub ax,ax   ;turn off speaker and exit
    out 61h,al
    int 16h
    mov ax,3
    int 16
    ret
    END

It fill screen and speaker with white noise as if no antenna cable in analog TV. This version is 44 Bytes long, pseudo random generator starts at label l0:

  • ax is the generated number (and also the prevvious generated number like you temp)
  • di is incrementing (something like actual time)...
  • cl is decrementing

so if I look at it right it should be enough:

    rnd:ror ax,cl       ;rnd...ax
        add ax,di
        inc di
        dec cl
        ret

and add push/pop store the registers/values if needed. If you need something more sophisticated then use modulo prime arithmetics.

[edit1] simple C++ pseudo random generator

WORD rnd_d0=0x66; // these are seed numbers if not selected right then the randomness is not good
WORD rnd_d1=0x5A; // these give fairly good results
WORD rnd_d2=0xC3;
WORD rnd()
    {
    rnd_d0^=rnd_d1|rnd_d2; // xor
    rnd_d1*=rnd_d2; // mul
    rnd_d2+=rnd_d1; // add
    rnd_d0=(rnd_d0<<8)|(rnd_d0>>8); // 8bit halves swap
    return rnd_d0;
    }

The above random generators was tighted to DOS environment time or special usage. This one is not ... the randomness is like this:

randomness graph

when I use it to fill NoSignal image window the result is this:

NoSignal

and here Gif animation:

NoSignal 320x240x3

The NoSignal fill code is as this:

 for (int y=0;y<ys;y++)
  for (int x=0;x<xs;x++)
   pyx[y][x]=0x00010101*int(rnd()>>8);

So just high 8bit from the 16bit pseudo random number is used the multiplication just converts this 8bit number to gray-scale color.

  • xs,ys is image size
  • pyx is the direct image pointer to its lines

Do not change the seed numbers without proper testing with this on PC

Wrongly selected seeds leads to no randomness at all. If you want to safely seed (without testing) then seed with provided constants and then call rnd() as much times as the new seed number of yours is. Busted this right now so there may be better seeds for this, these are just the first ones I found that gives fairly good results

These seeds are also good:

    WORD rnd_d0=0x37A6;
    WORD rnd_d1=0x377A;
    WORD rnd_d2=0x3BC3;
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • @alex had a bit time for this so I tested mine old random generators and without MSDOS time or special way of usage there are not that good so i created something that is platform and usage independent see [edit1] it uses 16 bit ALU so if do not have any code some from 8bit ALU source is in C++ so there should not be any problems with porting to asm. If you need something better then specify the randomness properties you need – Spektre Mar 28 '15 at 09:26
  • Rotate-through-carry (`rcr`/ `rcl`) with count > 1 is quite slow on modern x86: 8 uops on Intel Haswell for example, or 15 m-ops on AMD Steamroller. This is I guess optimized for code-size, not speed, and/or for much older CPUs. (even early P6 CPUs like PII had faster rcr). – Peter Cordes Jun 27 '16 at 17:59
  • @PeterCordes that was more like for AMD 80386 up to AMD K5... and yes it was optimized for code length – Spektre Jan 06 '17 at 10:41