Re: Question about jumps
- From: Frank Kotler <fbkotler@xxxxxxxxxxx>
- Date: Mon, 28 Aug 2006 22:16:39 -0400
Markus Pitha wrote:
....
OTOH, if you had kept reading through AoA, you probably would have
learned that you can call one of several nifty little random number
generators that are present in the HLA Standard Library.
That's exactly what I don't want. It's like in C, including any libraries,
but I want to know what these little gremlins in the background do.
Precisely! When I was trying to teach myself C, I found it somewhat "unsatisfying". It seemed like the library routines were having all the fun, and I was relegated to "data entry clerk". Turns out, it's always that way. There's always a black box at the end, and all our programming is just "setting up" for it. But we can get into a lower ("better") class of black boxes...
Randy's right that a lot of this stuff is "algorithmic", and not strictly "assembly language", and that "call the library routine" is a perfectly good algorithm. Still, some of us around here are interested in learning how these things are done - in x86 assembly language.
This particular little gremlin...
----------------------------
push cx
push dx
shl ax,4
mov cx,ax ;cycle 16 bits [randomness] times
get_true_rnd_loop:
mov al,06h ;latch counter 0 for word read
cli
out 43h,al ;post request to timer control port
jmp $+2 ;IO delay (JMP to next instruction)
in al,40h ;read LSB of timer count
xor dl,al ;XOR-on LSB
jmp $+2 ;IO delay (JMP to next instruction)
in al,40h ;read MSB of timer count
sti
xor dl,al ;XOR-on MSB
rol dx,1 ;scroll rnd # for uniform randomness
dec cx
jnz short get_true_rnd_loop ;DEC CX+JNZ is usually faster than LOOP
mov ax,dx ;return ax: true random number
pop dx
pop cx
ret
(I found that "random number generator" on the net, but it doesn't work
yet due to an out of memory error. Maybe I'll find the error out soon)
-------------------------
I don't see why you should get an out of memory error, but as Randy points out, it won't run in Linux without considerable modification (if that's what you're trying to do). I doubt if it's worth it - another method would probably be more appropriate. But we can *look* at it...
push cx
push dx
Save caller's regs... obvious enough...
shl ax,4
Effectively multiplies by 16.
mov cx,ax ;cycle 16 bits [randomness] times
Apparently, we've been called with some number in ax that we're going to use as a "rounds" counter.
get_true_rnd_loop:
Badly named label. I'm no expert on Random Number Generators, but I'm pretty sure this isn't a "true" one! :)
mov al,06h ;latch counter 0 for word read
Okay... we'll want to remember that that's 00000110 binary - we'll have to consult Ralf to see what it means...
cli
Disable interrupts... Linux isn't going to let us do that! I don't see why it's necessary.
out 43h,al ;post request to timer control port
To access the ports in Linux, we'd have to get "permission" first. This range of ports goes to the Programmable Interrupt Timer, and this one is the control port. (after writing a command, we must immediately perform the corresponding action, or the system may hang, Ralf warns us!) We're selecting counter 0 - produces the 18.2/sec "tick" in dos, I immagine Linux reprograms it(?). I don't think we care how fast it's going...
jmp $+2 ;IO delay (JMP to next instruction)
This no longer produces a reliable delay - and I don't think it's necessary with modern hardware. If we *do* need an "IO delay", a read from a "dummy" port might be better...
in al,40h ;read LSB of timer count
Okay, we read whatever the timer has counted down to at this moment (least significant byte first, then most significant byte). There's a "gotcha" with the "in" and "out" instructions - the "immediate" form is only available for an immediate *byte*. For ports over 0FFh, you need to have the port in dx.
xor dl,al ;XOR-on LSB
Scramble some bits... starting with... whatever was in dl, I guess. Perhaps a "seed" was passed to us in dl?
jmp $+2 ;IO delay (JMP to next instruction)
Yeah, yeah...
in al,40h ;read MSB of timer count
Okay...
sti
Enable interrupts. We're not going to disable 'em in Linux, so this can go, too.
xor dl,al ;XOR-on MSB
rol dx,1 ;scroll rnd # for uniform randomness
Scramble 'em some more...
dec cx
jnz short get_true_rnd_loop ;DEC CX+JNZ is usually faster than LOOP
After introducing IO delays, now we wanna go fast. :) Okay, so we do all of the above 16 times for for every "count" passed in ax. If someone passes zero, we're going to do it a long time. :)
mov ax,dx ;return ax: true random number
Mmmm... well-scrambled, anyway. Anything based on a timer is less than ideal. Good enough for deciding which monster attacks next. Probably good enough for dealing cards. If you're trying to protect crypto from serious attackers, you might look for something better.
pop dx
pop cx
Restore caller's regs...
ret
And go home...
If you really want to "port" that to Linux, we can get into that, but I think a more "appropriate" method could be found... (FWIW, Randy's code merges the bits from rdtsc with bits from sys_gettimeofday, and scrambles 'em up to get a "seed" (and an array of seeds), the does a linear congruential generator on a "per use" basis - looks quite good, to my untrained eye)
Best,
Frank
.
- References:
- Question about jumps
- From: Markus Pitha
- Re: Question about jumps
- From: rhyde
- Re: Question about jumps
- From: Markus Pitha
- Re: Question about jumps
- From: rhyde
- Re: Question about jumps
- From: Markus Pitha
- Re: Question about jumps
- From: randyhyde@xxxxxxxxxxxxx
- Re: Question about jumps
- From: Markus Pitha
- Question about jumps
- Prev by Date: Re: Question about jumps
- Next by Date: Re: Question about jumps
- Previous by thread: Re: Question about jumps
- Next by thread: Re: Question about jumps
- Index(es):
Relevant Pages
|