I am trying to write a very strange and confusing program for school...
I am supposed to have a main program and two subprograms, random and reseed. Random has a 'seed' defined in it that needs to be accessed by the other two programs. Main should set BL and AX and call reseed.If BL = 0, reseed will decide to use random to generate a random number and store it as 'seed.' If BL = 1, reseed will decide that 'seed' is 555H. Main should do this once with BL = 0, then main will go into a loop that calls random 100 times and prints out the random numbers generated. Then, main sets BL = 1 and calls reseed again and goes into the loop to print again. Main also counts the instances of odd, even, low (<5000), and high numbers generated to print at the end.
Here it is so far:
;===================================================================
; MAIN.ASM
; sets BL =1, AX = 555H
; calls Reseed
; Calls Rand 100 times w/ lower=0 upper = 9999
; Prints values 10 numbers/line and 6 ch/number and right justify
; Counts low values (0-4999) and high values (5000-9999)
; Counts evens and odds
; Sets BL=0
; Calls Reseed
; Calls Rand 100 times w/ lower=0 upper = 9999
; Prints values 10 numbers/line and 6 ch/number and right justify
; Counts low values (0-4999) and high values (5000-9999)
; Counts evens and odds
; Prints statistics (#/200)
;
;===================================================================
EXTRN GETDEC:FAR
EXTRN NEWLINE:FAR
EXTRN PUTDEC:FAR
EXTRN PUTSTRNG:FAR
;==================================================================
.MODEL SMALL,BASIC
;===================================================================
.STACK 256
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA MAIN_DATA
UPPER DW 9999
LOWER DW 0
HIGHCOUNT DW 0
LOWCOUNT DW 0
EVENCOUNT DW 0
ODDCOUNT DW 0
HIGHHEADER DB 'High numbers: '
LOWHEADER DB 'Low numbers: '
ODDHEADER DB 'Odd numbers: '
EVENHEADER DB 'Even numbers: '
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
;
.CODE
EXTERN RANDOM : NEAR, RESEED : NEAR
ASSUME DS:NOTHING,ES:MAIN_DATA
MAIN PROC
MOV AX,DGROUP ;SET ES-REGISTER TO POINT TO
MOV ES,AX ;CONSTANT DATA SEGMENT
MOV BL,1
CALL RESEED
MOV CX,100 ; LOOP_COUNT = 100
NUM_LOOP: ; REPEAT
PUSH CX ; PUSH LOOP_COUNT
PUSH LOWER
PUSH UPPER
CALL RANDOM
CALL PUTDEC
CALL NEWLINE ; DISPLAY NEWLINE CHAR.
CMP AX, 5000
JGE HIGH_SEQUENCE
INC LOWCOUNT
HIGH_SEQUENCE:
INC HIGHCOUNT
SUB DX, DX
MOV BX, 2
DIV BX
CMP DX, 0
JNE ODDS
INC EVENCOUNT
ODDS:
INC ODDCOUNT
POP CX ; POP LOOP_COUNT
INC AX ; NUMBER = NUMBER + 1
LOOP NUM_LOOP ; DECREMENT LOOP_COUNT
; UNTIL LOOP_COUNT = 0
;MOV 0,BL
;CALL RESEED
LEA DI, HIGHHEADER
MOV CX, 18
CALL PUTSTRNG
CALL NEWLINE
MAIN ENDP
END MAIN
;===================================================================
; RANDOM.ASM
; r a n d o m n u m b e r g e n e r a t o r
;
; GENERATES PSEUDO-RANDOM INTEGERS IN THE RANGE LOWER TO UPPER
; INPUT: TWO STACK PARAMETERS - LOWER AND UPPER ENDS OF RANGE
; OUTPUT: AX-REG CONTAINS RANDOM INTEGER
; CALLING SEQUENCE: PUSH <LOWER END OF RANGE>
; PUSH <UPPER END OF RANGE>
; CALL RANDOM
;===================================================================
.MODEL SMALL,BASIC
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA RAND_DATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849 ;ADDEND FOR MIXED
;LINEAR CONGRUENTIAL METHOD
PUBLIC SEED
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
;
.CODE
ASSUME DS:RAND_DATA
PUBLIC RANDOM
;
RANDOM PROC FAR PUBLIC USES CX DX DS,
LOWER:WORD, UPPER:WORD
;FUNCTION RANDOM(LOWER,UPPER)
;SAVE REGISTERS (USES LIST)
PUSHF ;SAVE FLAGS
MOV AX,SEG RAND_DATA ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO LOCAL DATA SEGMENT
;
MOV AH,0 ; SEED = LOWER HALF OF
INT 1AH ; TIME OF DAY CLOCK
MOV SEED,DX
MOV AX,SEED ;X = SEED * MULTIPLIER mod
MUL MULTIPLIER ; 65536
ADD AX,ADDEND ;SEED = (X + ADDEND) mod 65536
MOV SEED,AX
MOV CX,UPPER ;RANGE = UPPER - LOWER + 1
SUB CX,LOWER
INC CX
MUL CX ;RANDOM = (SEED*RANGE)/65536
ADD DX,LOWER ; + LOWER
MOV AX,DX
POPF ;RESTORE FLAGS
;RESTORE REGISTERS (ASSEMBLER
; GENERATES INSTRUCTIONS TO
; RESTORE REGISTERS - USES)
RET ;RETURN (RANDOM)
RANDOM ENDP ;END RAND
END
;===================================================================
; RESEED.ASM
; if BL = 0, uses clock for seed
; else, uses AX
;===================================================================
.MODEL SMALL,BASIC
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
EXTERN SEED : WORD
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
;
.CODE
EXTERN RANDOM : NEAR
;
PUBLIC RESEED
RESEED PROC FAR PUBLIC USES CX DX DS,
LOWER:WORD, UPPER:WORD
;FUNCTION RANDOM(LOWER,UPPER)
;SAVE REGISTERS (USES LIST)
PUSHF ;SAVE FLAGS
ASSUME DS: RAND_DATA
MOV DS, AX
MOV AX, RAND_DATA
MOV DS, AX
CMP BL,0
JNE NOTZERO
PUSH LOWER
PUSH UPPER
CALL RANDOM
NOTZERO:
MOV SEED,555H
POPF ;RESTORE FLAGS
;RESTORE REGISTERS (ASSEMBLER
;GENERATES INSTRUCTIONS TO
;RESTORE REGISTERS - USES)
RET ;RETURN
RESEED ENDP
END
Assembling gives these errros:
reseed line 17 error A2006: undefined symbol rand_data
reseed line 19 error A2006: undefined symbol rand_data
How can reseed access the data in random? The instructor told us to stick
ASSUME DS: RAND_DATA
MOV DS, AX
MOV AX, RAND_DATA
MOV DS, AX
in reseed to get access, but it doesn't seem to work. Please help!
i see a mixture of EXTRN and EXTERN - i think EXTRN is outdated - check the masm manual
.FARDATA uses a default segment name of FAR_DATA
i think you have to open that segment with a SEGMENT directive
RAND_DATA SEGMENT WORD PUBLIC "FAR_DATA"
RAND_DATA ENDS
or something like that
the parameters should match the segment as it is defined in the other source
I replaced the extrns, but I don't really understand the rest. I tried using 'FAR_DATA' rather than 'RAND_DATA,' but I don't think that's what you meant. Could you please explain a little more? I am very new to this.
Thanks!
well, you are using
.fardata RAND_DATA
i think the RAND_DATA part is being ignored
the .fardata directive always uses a segment named FAR_DATA
you want a segment named RAND_DATA, which is the FAR_DATA type (different than the name)
so, instad of this...
.FARDATA RAND_DATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849 ;ADDEND FOR MIXED
try this
RAND_DATA SEGMENT WORD PUBLIC "FAR_DATA"
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849 ;ADDEND FOR MIXED
RAND_DATA ENDS
the only thing i am not sure about is the parameters for the SEGMENT directive:
RAND_DATA SEGMENT WORD PUBLIC "FAR_DATA"
it has been a while since i wrote any 16-bit code and i don't remember all this stuff - lol
also, when i did write 16-bit code, i used MASM version 5.10
the newer versions of MASM have more (and different) parameters
what you need is the MASM manual
here it is in HTML form
http://doc.ddart.net/asm/Microsoft_MASM_Programmers_Guide_v6.1/
here it is in PDF form
http://faculty.kfupm.edu.sa/COE/mudawar/coe205/manuals/MASMProgrGuide/MASMProgGuide.pdf
I don't have time to do any testing, but I see multiple problems with your code.
When you use the MODEL directive the assembler automatically defines DGROUP for your near data segment, but I don't seen anywhere where you actually created a near data segment.
For the SMALL memory model data and code default to NEAR, but all of your data and all of your code is FAR. Your declarations are mixing NEAR and FAR, for example in MAIN this declaration:
EXTERN RANDOM : NEAR, RESEED : NEAR
Causes MAIN to call RESEED with a NEAR CALL, but since RESEED is a FAR procedure it will attempt to return with a FAR RET.
And there are other problems that I don't have time to deal with ATM.
You can get around the assembly errors for RESEED.ASM with code like this:
MOV AX, SEG SEED
MOV DS, AX
ASSUME DS: SEG SEED
When you assemble, if you use a command line like this:
ml /Fl /Sa /Sc /c RESEED.ASM
Then you will get a listing file where you can see the code that is being generated.
And if you create a MAP file when you link, you will be able to see a map of the segment structure. You can do so with a command line like this:
link16 main.obj reseed.obj random.obj,,main.map;
ah yes - Michaels suggestion is much easier
and here is the problem in your code...
RANDOM PROC FAR PUBLIC USES CX DX DS,
LOWER:WORD, UPPER:WORD
;FUNCTION RANDOM(LOWER,UPPER)
;SAVE REGISTERS (USES LIST)
PUSHF ;SAVE FLAGS
MOV AX,SEG RAND_DATA ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO LOCAL DATA SEGMENT
when you use SEG, you want to name a variable in that segment, not the segment
Hi Dave,
Using the SEG directive (or whatever it is called) with the segment
name works.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set up the code definitions the operating system wants. Data segment:
DATASG SEGMENT PUBLIC
ASSUME DS:DATASG, SS:STCKSG, CS:CODE
; Snipped.
DATASG ENDS
PAGE
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set up the code definitions the operating system wants. Code segment
CODE SEGMENT PUBLIC
START PROC
ASSUME CS:CODE,DS:DATASG,ES:NOTHING,SS:STCKSG
MOV AX,SEG DATASG ; Set DS for rest of code ...
MOV DS,AX
MOV ES,AX ; Change the ASSUME?
; And snip to end.
I've just used this style, or similar, and copied it to each new program
until recently.
Regards,
Steve
very cool Steve
i think SEG is an "operator" - not sure - lol
she is using all these far data segments - i am not sure it is neccessary
perhaps it is what the assignment requires, though
Hi Dave,
Quoteshe is using all these far data segments - i am not sure it is nesseccary
Yeah, using FAR and NEAR have bitten me way too often (with my
own code). Declaring code to be used in a library may have advantages
as FAR. But for a beginner? Why muddy the water?
Cheers,
Steve N.
you got me on bad spelling, Steve - lol
i am guilty :P
Thanks for all the answers.
I am using all the far data segments because that is what we were instructed to do in the previous program, and I have never seen any other way. We never even discussed what that means.
I modified the program to combine rand and reseed in one file, so here is what I've got now...
;===================================================================
; MAIN.ASM
; sets BL =1, AX = 555H
; calls Reseed
; Calls Rand 100 times w/ lower=0 upper = 9999
; Prints values 10 numbers/line and 6 ch/number and right justify
; Counts low values (0-4999) and high values (5000-9999)
; Counts evens and odds
; Sets BL=0
; Calls Reseed
; Calls Rand 100 times w/ lower=0 upper = 9999
; Prints values 10 numbers/line and 6 ch/number and right justify
; Counts low values (0-4999) and high values (5000-9999)
; Counts evens and odds
; Prints statistics (#/200)
;
;===================================================================
EXTERN GETDEC:FAR
EXTERN NEWLINE:FAR
EXTERN PUTDEC:FAR
EXTERN PUTSTRNG:FAR
;==================================================================
.MODEL SMALL,BASIC
;===================================================================
.STACK 256
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA MAIN_DATA
HIGHCOUNT DW 0
LOWCOUNT DW 0
EVENCOUNT DW 0
ODDCOUNT DW 0
HIGHHEADER DB 'High numbers: '
LOWHEADER DB 'Low numbers: '
ODDHEADER DB 'Odd numbers: '
EVENHEADER DB 'Even numbers: '
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
;
.CODE
EXTERN RANDOM : FAR, RESEED : FAR
ASSUME DS:NOTHING,ES:MAIN_DATA
MAIN PROC
MOV AX,DGROUP ;SET ES-REGISTER TO POINT TO
MOV ES,AX ;CONSTANT DATA SEGMENT
MOV BL,1
CALL RESEED
MOV CX,100 ; LOOP_COUNT = 100
NUM_LOOP: ; REPEAT
PUSH CX ; PUSH LOOP_COUNT
MOV AX,0 ;PUSH LOWER
PUSH AX
MOV AX,0000 ;PUSH UPPER
PUSH AX
CALL RANDOM
CALL PUTDEC
CALL NEWLINE ;DISPLAY NEWLINE CHAR.
CMP AX, 5000
JGE HIGH_SEQUENCE
INC LOWCOUNT
HIGH_SEQUENCE:
INC HIGHCOUNT
SUB DX, DX
MOV BX, 2
DIV BX
CMP DX, 0
JNE ODDS
INC EVENCOUNT
ODDS:
INC ODDCOUNT
POP CX ; POP LOOP_COUNT
INC AX ; NUMBER = NUMBER + 1
LOOP NUM_LOOP ; DECREMENT LOOP_COUNT
; UNTIL LOOP_COUNT = 0
;MOV 0,BL
;CALL RESEED
LEA DI, HIGHHEADER
MOV CX, 18
CALL PUTSTRNG
CALL NEWLINE
MAIN ENDP
END MAIN
;===================================================================
; RANDOM.ASM
; r a n d o m n u m b e r g e n e r a t o r
;
; GENERATES PSEUDO-RANDOM INTEGERS IN THE RANGE LOWER TO UPPER
; INPUT: TWO STACK PARAMETERS - LOWER AND UPPER ENDS OF RANGE
; OUTPUT: AX-REG CONTAINS RANDOM INTEGER
; CALLING SEQUENCE: PUSH <LOWER END OF RANGE>
; PUSH <UPPER END OF RANGE>
; CALL RANDOM
;===================================================================
.MODEL SMALL, BASIC
.586
.STACK 256
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.DATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849 ;ADDEND FOR MIXED
;LINEAR CONGRUENTIAL METHOD
UPPER DW 9999
LOWER DW 0
PUBLIC SEED
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
ASSUME DS:DGROUP
RESEED PROC
MOV AX,DGROUP ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO LOCAL DATA SEGMENT
;SAVE REGISTERS (USES LIST)
PUSHF ;SAVE FLAGS
CMP BL,0
JNE NOTZERO
PUSH LOWER
PUSH UPPER
CALL RANDOM
MOV SEED, AX
NOTZERO:
MOV SEED,555H
POPF ;RESTORE FLAGS
;RESTORE REGISTERS (ASSEMBLER
;GENERATES INSTRUCTIONS TO
;RESTORE REGISTERS - USES)
RET ;RETURN
RESEED ENDP
RANDOM PROC FAR PUBLIC USES CX DX DS
;FUNCTION RANDOM(LOWER,UPPER)
;SAVE REGISTERS (USES LIST)
PUSHF ;SAVE FLAGS
;
MOV AH,0 ; SEED = LOWER HALF OF
INT 1AH ; TIME OF DAY CLOCK
MOV SEED,DX
MOV AX,SEED ;X = SEED * MULTIPLIER mod
MUL MULTIPLIER ; 65536
ADD AX,ADDEND ;SEED = (X + ADDEND) mod 65536
MOV SEED,AX
MOV CX,UPPER ;RANGE = UPPER - LOWER + 1
SUB CX,LOWER
INC CX
MUL CX ;RANDOM = (SEED*RANGE)/65536
ADD DX,LOWER ; + LOWER
MOV AX,DX
POPF ;RESTORE FLAGS
;RESTORE REGISTERS (ASSEMBLER
; GENERATES INSTRUCTIONS TO
; RESTORE REGISTERS - USES)
RET ;RETURN (RANDOM)
RANDOM ENDP ;END RAND
END RESEED
What I don't know is how to define two data segments in one file (there are no examples in my book) and whether or not I need to change the calls from main now.
normally, multiple data segments are used for extremely large programs
or, at least, programs that manipulate a large amount of data
this one is very small - all the data involved could easily fit into one 64 Kb segment
the biggest difference with using far data segments is that pointers now require a segment value
whereas near data only requires a 16-bit address
as for defining multiple data segments, did you d/l the MASM programmers guide that i linked above ?
it should tell you everything you need to know
OK, I looked in the guide. I also am only using one data segment for rand and reseed. Now it assembles, but I get an error when I run Main that says illegal instruction encountered and shuts down.
Hi,
One of your PROC statements is lacking the FAR. (RESEED) That might
shut you down.
To define two data segments, you just name them differently. If you
give them the same name in different files, LINK will combine them into
one. So it probably doesn't matter.
DATASG SEGMENT PUBLIC
ASSUME DS:DATASG, SS:STCKSG, CS:CODE
DATASG ENDS
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set up the code definitions the operating system wants. Data segment:
EXTRASG SEGMENT PUBLIC
ASSUME ES:EXTRASG
HTH,
Steve N.
Thanks for answering. I added the far and am using only 1 data segment, but still I get an error.
one thing i see is this....
RANDOM PROC FAR PUBLIC USES CX DX DS
RANDOM is defined as a far procedure, yet it is in the near code segment
this may not cause a problem, but it could
when a RET instruction is encountered in a proc far, a RETF is generated instead of RETN
that is ok if the CALL pushes the code segment
let me look at the proc a few minutes and see if i can find an invalid instruction
ok - i think i see what is goofing you up
you push 2 word parameters onto the stack of the RANDOM procedure, but never pop them off
at the end of the RANDOM proc, use:
RET 4
that will return, and discard 2 words from the stack
OK, I changed the far to a near and inserted RET 4. Still getting an error.
Here is the new code for random :
;===================================================================
; RANDOM.ASM
; r a n d o m n u m b e r g e n e r a t o r
;
; GENERATES PSEUDO-RANDOM INTEGERS IN THE RANGE LOWER TO UPPER
; INPUT: TWO STACK PARAMETERS - LOWER AND UPPER ENDS OF RANGE
; OUTPUT: AX-REG CONTAINS RANDOM INTEGER
; CALLING SEQUENCE: PUSH <LOWER END OF RANGE>
; PUSH <UPPER END OF RANGE>
; CALL RANDOM
;===================================================================
.MODEL SMALL, BASIC
.586
.STACK 256
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.DATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849 ;ADDEND FOR MIXED
;LINEAR CONGRUENTIAL METHOD
UPPER DW 9999
LOWER DW 0
PUBLIC SEED
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
ASSUME DS:DGROUP
RESEED PROC FAR PUBLIC
MOV AX,DGROUP ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO LOCAL DATA SEGMENT
;SAVE REGISTERS (USES LIST)
PUSHF ;SAVE FLAGS
CMP BL,0
JNE NOTZERO
PUSH LOWER
PUSH UPPER
CALL RANDOM
MOV SEED, AX
NOTZERO:
MOV SEED,555H
POPF ;RESTORE FLAGS
;RESTORE REGISTERS (ASSEMBLER
;GENERATES INSTRUCTIONS TO
;RESTORE REGISTERS - USES)
RET ;RETURN
RESEED ENDP
RANDOM PROC NEAR PUBLIC USES CX DX DS
;FUNCTION RANDOM(LOWER,UPPER)
;SAVE REGISTERS (USES LIST)
PUSHF ;SAVE FLAGS
;
MOV AH,0 ; SEED = LOWER HALF OF
INT 1AH ; TIME OF DAY CLOCK
MOV SEED,DX
MOV AX,SEED ;X = SEED * MULTIPLIER mod
MUL MULTIPLIER ; 65536
ADD AX,ADDEND ;SEED = (X + ADDEND) mod 65536
MOV SEED,AX
MOV CX,UPPER ;RANGE = UPPER - LOWER + 1
SUB CX,LOWER
INC CX
MUL CX ;RANDOM = (SEED*RANGE)/65536
ADD DX,LOWER ; + LOWER
MOV AX,DX
POPF ;RESTORE FLAGS
;RESTORE REGISTERS (ASSEMBLER
; GENERATES INSTRUCTIONS TO
; RESTORE REGISTERS - USES)
RET 4 ;RETURN (RANDOM)
RANDOM ENDP ;END RAND
END RESEED
and main :
;===================================================================
; MAIN.ASM
; sets BL =1, AX = 555H
; calls Reseed
; Calls Rand 100 times w/ lower=0 upper = 9999
; Prints values 10 numbers/line and 6 ch/number and right justify
; Counts low values (0-4999) and high values (5000-9999)
; Counts evens and odds
; Sets BL=0
; Calls Reseed
; Calls Rand 100 times w/ lower=0 upper = 9999
; Prints values 10 numbers/line and 6 ch/number and right justify
; Counts low values (0-4999) and high values (5000-9999)
; Counts evens and odds
; Prints statistics (#/200)
;
;===================================================================
EXTERN GETDEC:FAR
EXTERN NEWLINE:FAR
EXTERN PUTDEC:FAR
EXTERN PUTSTRNG:FAR
;==================================================================
.MODEL SMALL,BASIC
;===================================================================
.STACK 256
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA MAIN_DATA
HIGHCOUNT DW 0
LOWCOUNT DW 0
EVENCOUNT DW 0
ODDCOUNT DW 0
HIGHHEADER DB 'High numbers: '
LOWHEADER DB 'Low numbers: '
ODDHEADER DB 'Odd numbers: '
EVENHEADER DB 'Even numbers: '
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
;
.CODE
EXTERN RANDOM : FAR, RESEED : FAR
ASSUME DS:NOTHING,ES:MAIN_DATA
MAIN PROC
MOV AX,DGROUP ;SET ES-REGISTER TO POINT TO
MOV ES,AX ;CONSTANT DATA SEGMENT
MOV BL,1
CALL RESEED
MOV CX,100 ; LOOP_COUNT = 100
NUM_LOOP: ; REPEAT
PUSH CX ; PUSH LOOP_COUNT
MOV AX,0 ;PUSH LOWER
PUSH AX
MOV AX,0000 ;PUSH UPPER
PUSH AX
CALL RANDOM
CALL PUTDEC
CALL NEWLINE ;DISPLAY NEWLINE CHAR.
CMP AX, 5000
JGE HIGH_SEQUENCE
INC LOWCOUNT
HIGH_SEQUENCE:
INC HIGHCOUNT
SUB DX, DX
MOV BX, 2
DIV BX
CMP DX, 0
JNE ODDS
INC EVENCOUNT
ODDS:
INC ODDCOUNT
POP CX ; POP LOOP_COUNT
INC AX ; NUMBER = NUMBER + 1
LOOP NUM_LOOP ; DECREMENT LOOP_COUNT
; UNTIL LOOP_COUNT = 0
;MOV 0,BL
;CALL RESEED
LEA DI, HIGHHEADER
MOV CX, 18
CALL PUTSTRNG
CALL NEWLINE
MAIN ENDP
END MAIN
Thanks again for all your time. I am pretty lost (obviously!)
lol - now you have RESEED as far - don't think it was before
RESEED PROC FAR PUBLIC
ok - now i will try and assemble these
i take it you are making 2 OBJ files and linking them together ?
you have to fix this, too (put them all at the top of the file)
EXTERN RANDOM : FAR, RESEED : FAR
to build this, i need:
EXTERN GETDEC:FAR
EXTERN NEWLINE:FAR
EXTERN PUTDEC:FAR
EXTERN PUTSTRNG:FAR
i am going to hook you up with a little tool i use for 16-bit code
it is similar to debug, but with more features - very helpful
place it in the masm32\bin folder
The command I am using is
ml main.asm random.asm io.lib
What exactly is wrong with
EXTERN RANDOM : FAR, RESEED : FAR ?
They need to be in a different place?
Also, I am using MASM 611. Is that going to make any difference?
let's start by defining the right memory model
if you can get all your stuff into one segment, small is good
if you are required to use far data and/or far code, we need to use large or compact
small: one code segment, one data segment
medium: multiple code segments, one data segment
compact: one code segment, multiple data segments
large: multiple code segments, multiple data segments
i want to try to assemble this, but i need the following proc's (or maybe i need io.lib)
GETDEC
NEWLINE
PUTDEC
PUTSTRNG
i am not sure this works: ml main.asm random.asm io.lib
i think you have to assemble them seperately and create different OBJ's
then, link the OBJ's together
i could be wrong about that
So for the models, main should use compact and random should use small?
I am pretty sure the assemble command I am using is OK. It is in the book like that,a dnI have used it before. I would send you io.lib, but I don't know how to attach things to these messages here!
no - they use the same model
what i was trying to do by mentioning that was to get you to choose a model - lol
you need to decide from the onset whether you are going to use multiple code/data segments
i would do the minimum required by the project
if they require you to use multiple data segments - so be it
if they do not require you to use multiple code segments, avoid that - lol
one code segment and multiple data segments is compact - use that in all the files if that fills the bill
the io.lib file
zip it and attach it at the bottom of the reply where it says Additional Options...
if io.lib has far code - we need to use large
let me look at it and i can figure it out
Here it is. Thanks so much for all your time! I have learned about as much this morning as I have in a month from my teacher.
the externs in that library are far's
i think you said you were required to use multiple data segments
so - that means large model
well - i assembled main and random seperately
then, i linked them together with io.lib using lnk563.exe
result: it executed, no errors, but >poof< nothing happened
let's see if we can make something happen - lol
We were supposed to be using multiple data segments when rand and reseed were two separate files, but I gave up on that. Now I think I'll just use one file for them and one data segment.
it's all good - lol
we can use multiple code and data segments
i got a 4-digit random number as output (different each time), then it displays several garbage characters and hangs
do you have the source file for the procedures in io.lib so i can take a look at them ?
Sorry, I'm not sure what you mean...
Our teacher had us download a file that had that library in it, but I don't see anything like source files for the procedures.
Also, as a check to see if it is working when the seed is 555H, the first few numbers should be 832, 6809, 8658, and 1206.
can you give me the link for the download ?
i need to see how to use those procedures
or - i'll just write my own - lol
here is what i have so far
you can see that i modified the asm files
and, i made a batch file to assemble them - look inside that to see the command lines
It was just a folder he put on a drive at school. I think I found what you wanted though.
JGE HIGH_SEQUENCE ;a count below 5000 gets counted as both high and low ?
INC LOWCOUNT
HIGH_SEQUENCE:
I thought this would skip over 'inc lowcount' if greater or equal than 5000 and go to highsequence? Same here:
JNE ODDS ;an even value gets counted as both even and odd ?
INC EVENCOUNT
ODDS:
INC ODDCOUNT
If the value is less than 5000, both LOWCOUNT and HIGHCOUNT get incremented. Is this what you want? also,
PUSH LOWER
PUSH UPPER
These two line are never popped which is why you need the RET 4. Remove those two lines and you will only need RET. This is not your problem, though, just not good coding (we spoke of this before or was it a comment I made to FORTRAN). Another way you could clean that up is to add UPPER and LOWER to the proc statement so the procedure will do the popping for you. If either option is used RET 4 must be changed to RET for stack balancing.
CMP BL,0
JNE NOTZERO
I assume BL should contain the value of the seed? If so, that code is missing.
Paul
No, I want highcount incremented if it is 5000 or above and lowcount to be incremented if it is under. I was told a jump like jge would jump past whatever is between it and the place it is jumping to, so JGE HIGH_SEQUENCE would skip past INC LOWCOUNT and go to HIGH_SEQUENCE. If that is incorrect, please tell me how to increment low and high.
BL should not contain the value of the seed. BL should contain either a 1 or a 0. This is set in main. First, it will set BL = 0 and call reseed, which will cause reseed to call random and use that for a seed. Then main will call random 100 times and print out the values and get stats. Then main will set BL = 1, which will cause reseed to set the seed = 555H. Then main goes into a loop again and prints and collects data. When those two loops are over, main will print out the statistics for high/low and even/odd for all 200 numbers.
Hi,
You have:
CMP DX, 0
JNE ODDS
INC EVENCOUNT
ODDS:
INC ODDCOUNT
and that counts even numbers if not odd, but counts
odd numbers all the time.
You will want something more like:
CMP DX, 0
JNE ODDS
INC EVENCOUNT
JMP EVENS ; If even, don't count odds.
ODDS:
INC ODDCOUNT
EVENS:
Steve
Oh! I see. Here's the new one. Now sometimes i get numbers, sometimes I get errors, and sometimes I get 'divide overflow.' When main calls reseed, will it continue through reseed all the way to random? Or will it return to main with the ret in reseed?
;===================================================================
; RANDOM.ASM
; r a n d o m n u m b e r g e n e r a t o r
;
; GENERATES PSEUDO-RANDOM INTEGERS IN THE RANGE LOWER TO UPPER
; INPUT: TWO STACK PARAMETERS - LOWER AND UPPER ENDS OF RANGE
; OUTPUT: AX-REG CONTAINS RANDOM INTEGER
; CALLING SEQUENCE: PUSH <LOWER END OF RANGE>
; PUSH <UPPER END OF RANGE>
; CALL RANDOM
;===================================================================
.MODEL SMALL, BASIC
.586
.STACK 256
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA RAND_DATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849 ;ADDEND FOR MIXED
;LINEAR CONGRUENTIAL METHOD
UPPER DW 9999
LOWER DW 0
PUBLIC SEED
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
RESEED PROC PUBLIC
MOV AX, RAND_DATA
MOV DS, AX
ASSUME DS:RAND_DATA
PUSHF
CMP BL,0
JNE NOTZERO
PUSH LOWER
PUSH UPPER
CALL RANDOM
MOV SEED, AX
JMP ZERO
NOTZERO:
MOV SEED,555H
ZERO:
POPF
RET 4
RESEED ENDP
RANDOM PROC NEAR PUBLIC USES CX DX DS
MOV AX,RAND_DATA
MOV DS, AX
PUSHF
MOV AH,0 ; SEED = LOWER HALF OF
INT 1AH ; TIME OF DAY CLOCK
MOV SEED,DX
MOV AX,SEED ;X = SEED * MULTIPLIER mod
MUL MULTIPLIER ; 65536
ADD AX,ADDEND ;SEED = (X + ADDEND) mod 65536
MOV SEED,AX
MOV CX,UPPER ;RANGE = UPPER - LOWER + 1
SUB CX,LOWER
INC CX
MUL CX ;RANDOM = (SEED*RANGE)/65536
ADD DX,LOWER ; + LOWER
MOV AX,DX
POPF
ret
RANDOM ENDP ;END RAND
END RESEED
;===================================================================
; MAIN.ASM
; sets BL =1, AX = 555H
; calls Reseed
; Calls Rand 100 times w/ lower=0 upper = 9999
; Prints values 10 numbers/line and 6 ch/number and right justify
; Counts low values (0-4999) and high values (5000-9999)
; Counts evens and odds
; Sets BL=0
; Calls Reseed
; Calls Rand 100 times w/ lower=0 upper = 9999
; Prints values 10 numbers/line and 6 ch/number and right justify
; Counts low values (0-4999) and high values (5000-9999)
; Counts evens and odds
; Prints statistics (#/200)
;===================================================================
EXTERN GETDEC:FAR
EXTERN NEWLINE:FAR
EXTERN PUTDEC:FAR
EXTERN PUTSTRNG:FAR
;==================================================================
.MODEL SMALL,BASIC
;===================================================================
.STACK 256
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA MAIN_DATA
HIGHCOUNT DW 0
LOWCOUNT DW 0
EVENCOUNT DW 0
ODDCOUNT DW 0
HIGHHEADER DB 'High numbers: '
LOWHEADER DB 'Low numbers: '
ODDHEADER DB 'Odd numbers: '
EVENHEADER DB 'Even numbers: '
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
;
.CODE
EXTERN RANDOM : FAR, RESEED : FAR
ASSUME DS:NOTHING,ES:MAIN_DATA
MAIN PROC
MOV AX,DGROUP ;SET ES-REGISTER TO POINT TO
MOV ES,AX ;CONSTANT DATA SEGMENT
MOV BL,1
CALL RESEED
MOV CX,100 ; LOOP_COUNT = 100
NUM_LOOP: ; REPEAT
PUSH CX ; PUSH LOOP_COUNT
MOV AX,0 ;PUSH LOWER
PUSH AX
MOV AX,0000 ;PUSH UPPER
PUSH AX
CALL RANDOM
CALL PUTDEC
CALL NEWLINE ;DISPLAY NEWLINE CHAR.
CMP AX, 5000
JGE HIGH_SEQUENCE
INC LOWCOUNT
JMP LOWSEQUENCE
HIGH_SEQUENCE:
INC HIGHCOUNT
LOWSEQUENCE:
SUB DX, DX
MOV BX, 2
DIV BX
CMP DX, 0
JNE ODDS
INC EVENCOUNT
JMP EVENS
ODDS:
INC ODDCOUNT
EVENS:
POP CX ; POP LOOP_COUNT
INC AX ; NUMBER = NUMBER + 1
LOOP NUM_LOOP ; DECREMENT LOOP_COUNT
; UNTIL LOOP_COUNT = 0
;MOV 0,BL
;CALL RESEED
LEA DI, HIGHHEADER
MOV CX, 18
CALL PUTSTRNG
MOV AX, HIGHCOUNT
CALL PUTDEC
CALL NEWLINE
MAIN ENDP
END MAIN
i have changed things around quite a bit - lol
i also updated the build batch file
i could not get the lib functions to work without errors, so i wrote my own
the main part works - we just need to get the random thing working
one thing i bumped into is that the library also has a function named "random"
so, i renamed yours to nrandom
I can't change it too much... can you tell what's wrong with what I 've done? And I attached the original random program so you can see what I was supposed to use for that part.
there is a bit of a flaw in the reseed mechanism
when you call reseed, it should access the timer
the random function should then generate numbers according to the seed (no timer)
at least, that is how i think you want it to work if you want it to recreate that specific sequence (555h seed)
The timer? Do you mean the clock?
All I have so far is the part that's supposed to set the seed to 555h (BL = 1) and generate numbers based on that. If I can get that working, then I'll worry about the second part (BL = 0) that uses the clock for a seed.
I hope you understand. I know this is confusing and pretty ridiculous.
i have nice randoms - lol
is the sequence 832, 6809, 8658, and 1206 supposed to be with a range of 0 to 9999 ?
Yes, that's right.
to generate that sequence, i have to start with a seed of 5555h, not 555h
gotcha !!! - lol
Oh! I'm so sorry. I had it wrong in my notes.
it was a lucky guess :P
So can I see what you have so far? I 'm still not sure about whether or not reseed stops when I want it to or continues through random.
i fixed reseed
it is done and working - lol
with bl=1, it generates the sequence 832, 6809, 8658, 1206
i moved UPPER and LOWER into the main program and they are transfered on the stack
i changed the segments all around
the main program uses the DS register and DGROUP
the random routine uses the ES register and FAR_DATA
When I try assembling, it says fatal error l1093: random.obj object file not found. I see the object file has been made, so why is it doing this?
are you using the batch file ?
it is probably not looking in the right folder - just a guess
Honestly, I don't even know what a batch file is!
use these command lines - lol
ml /c main.asm
ml /c random.asm
lnk563 main.obj+random.obj,main.exe,nul.map,io.lib,nul.def
your linker may be named Link16.exe instead
the regular LINK.exe will not work with 16-bit code
I get 'cannot open file ml.' I have never seen any of that stuff before, so I have a feeling this is not what I was supposed to be doing...
ml.exe may be named MASM.exe
are you using the masm32 package from this site ?
you said in a previous post that you use ML.exe...
http://www.masm32.com/board/index.php?topic=12477.msg95946#msg95946
I am using MASM 6.11. I believe I found it here:
http://www.phatcode.net/downloads.php?id=175
(http://www.phatcode.net/downloads.php?id=175)
The batch file works for me using ML 6.11 and the 16-bit linker (version 5.60.339).
what is the name of your assembler exe file and linker exe file ?
if you install the masm32 package, you will get masm version 6.14
i am using 6.15, but either should work
this is the one i use
http://www.4shared.com/file/139758027/648a9665/ML_online.html
here is a 16-bit linker (Lnk563.exe)
http://website.masm32.com/microsoft/Lnk563.exe
I downloaded the file, but it executes and immediately shuts down... and what is the instruction 'OR?' and 'SHR?'
grrrrr - lol
it is a zip file - you have to unzip it, first
i think the Lnk563 is also a zip (self-extracting) - you have to run it once before using it
I did unzip it! I got an executable, which I executed, and then it died.
ok - let me re-upload to that site - the file may be corrupt
hang on a few...
try this one...
http://www.4shared.com/file/139758027/648a9665/ML_online.html
The same thing happened, but I managed to run your after I took out the procs you wrote and put the putdec and putstrng stuff back in.
I am fooling around with it now trying to format it the way I need it and do the second part that uses the clock, but there are a few things I don't know, namely
shr, jc, jmp short, & or.
Also, it never seems to get to the bottom to display the stats. Did it when you ran it?
SHR is shift right
JC is Jump if Carry
short tells the assembler it is a short forward reference (eliminates a NOP, is all)
OR - is logical OR - i use it to test the register value for zero
this is Randall Hyde's online instruction reference - very handy
http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-1.html
i had to update that link
there is a file that goes with ML.exe named ML.err
it has all the error text used by that version of ML
i fixed the d/l link - you may want to d/l - once more - lol - sorry about that
That reference looks great! Thank you. I have been looking for a good one.
I re-downloaded, and now I have both files, but the .exe still dies. Argh!
lol - dang !
i dunno what to tell you - it runs here
i d/l'ed it and tested it
it may be something like this....
you type in ML
it runs the one that is in the PATH environment variable
the one you think you are running is not being executed
i don't suppose you know what a PATH environment variable is ?
find the old copy(ies) and rename it to ML_OLD.exe then try again
No, I don't know what a Path environment variable is. I'm sorry! I renamed it, but to no avail.
what version of windows are you using
well - let me upload version 6.14 - give me a few
try this one - version 6.14
http://www.4shared.com/file/139764026/1efb639b/ml614.html
XP Home edition version 2002 SP2
Same thing happened!
Please don't worry anymore. I've taken so much of your time. I really appreciate all your help. I am going to have dinner and I will fool around with this some more later and tomorrow. I will most likely be back with all sorts of questions.
QuoteI re-downloaded, and now I have both files, but the .exe still dies.
By dies, do you mean that it closes immediately?
Yes. I see it flash open, then a split second later it closes by itself.
Try right-clicking on the EXE and selecting Properties on the context menu, then on the Program tab clear the Close on exit checkbox.
There is no Program tab. There is General, Compatibility, Summary.
If there is no Program tab then the file is a 32-bit Windows program. I am referring to the main.exe from Dave's Random3.zip attachment, which is a 16-bit DOS program.
It is almost done. The only problem left is my strings are coming out as garbage. The numbers show up fine, but my headers are mumbo-jumbo. Can anyone see why?
;===================================================================
; MAIN.ASM
;===================================================================
EXTERN GETDEC:FAR
EXTERN NEWLINE:FAR
EXTERN PUTSTRNG:FAR
EXTERN NRANDOM:FAR
EXTERN RESEED:FAR
EXTERN PUTDEC:FAR
;===================================================================
.MODEL LARGE
.STACK 512
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.DATA
UPPER DW 9999
LOWER DW 0
HIGHCOUNT DW 0
LOWCOUNT DW 0
EVENCOUNT DW 0
ODDCOUNT DW 0
LOOPER DW 0
HIGHHEADER DB 'High: '
LOWHEADER DB 'Low: '
ODDHEADER DB 'Odd: '
EVENHEADER DB 'Even: '
SPACE DB ' '
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
ASSUME DS:DGROUP
;-------------------------------------------------------------------
MAIN PROC
MOV AX,DGROUP ;SET DS-REGISTER TO POINT TO
MOV DS,AX ;DATA SEGMENT
MOV BL,1
CALL RESEED
MOV LOOPER,100 ;LOOP_COUNT = 100
NUM_LOOP:
MOV CX,10 ;LOOP_COUNT = 10
LINE_LOOP:
PUSH CX ; PUSH LOOP_COUNT
MOV AX,UPPER ;PUSH UPPER
PUSH AX
MOV AX,LOWER ;PUSH LOWER
PUSH AX
CALL NRANDOM
MOV BH,1
CALL PUTDEC
LEA DI, SPACE
MOV CX, 1
CALL PUTSTRNG
CMP AX,5000
JAE HIGH_SEQUENCE
INC LOWCOUNT
JMP SHORT HILO_COUNTED
HIGH_SEQUENCE:
INC HIGHCOUNT
HILO_COUNTED:
SHR AX,1
JC ODDS
INC EVENCOUNT
JMP SHORT EVENODD_COUNTED
ODDS:
INC ODDCOUNT
EVENODD_COUNTED:
POP CX ; POP LOOP_COUNT
LOOP LINE_LOOP ; DECREMENT LOOP_COUNT
CALL NEWLINE
SUB LOOPER,10 ; POP LOOP_COUNT
CMP LOOPER,0
JNE NUM_LOOP
;============display
CALL NEWLINE
CALL NEWLINE
LEA DI, HIGHHEADER
MOV CX, 6
CALL PUTSTRNG
MOV AX, HIGHCOUNT
CALL PUTDEC
CALL NEWLINE
LEA DI, LOWHEADER
MOV CX, 6
CALL PUTSTRNG
MOV AX, LOWCOUNT
CALL PUTDEC
CALL NEWLINE
LEA DI, EVENHEADER
MOV CX, 6
CALL PUTSTRNG
MOV AX, EVENCOUNT
CALL PUTDEC
CALL NEWLINE
LEA DI, ODDHEADER
MOV CX, 6
CALL PUTSTRNG
MOV AX, ODDCOUNT
CALL PUTDEC
CALL NEWLINE
;==================
MOV AX,4C00H
INT 21H
MAIN ENDP
END MAIN
;===================================================================
; RANDOM.ASM
; r a n d o m n u m b e r g e n e r a t o r
; GENERATES PSEUDO-RANDOM INTEGERS IN THE RANGE LOWER TO UPPER
; INPUT: TWO STACK PARAMETERS - LOWER AND UPPER ENDS OF RANGE
; OUTPUT: AX-REG CONTAINS RANDOM INTEGER
; CALLING SEQUENCE: PUSH <LOWER END OF RANGE>
; PUSH <UPPER END OF RANGE>
; CALL RANDOM
;===================================================================
.MODEL LARGE
;===================================================================
PUBLIC SEED
PUBLIC RESEED
PUBLIC NRANDOM
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
ASSUME DS:NOTHING,ES:FAR_DATA
;-------------------------------------------------------------------
RESEED PROC FAR PUBLIC USES AX CX DX ES
MOV AX,FAR_DATA ;SET ES-REGISTER TO POINT
MOV ES,AX ;TO FAR DATA SEGMENT
PUSHF
cmp bl,0
jne NOTZERO
mov dx,5555h
MOV AH,0 ; SEED = LOWER HALF OF
INT 1AH ; TIME OF DAY CLOCK
jmp endd
NOTZERO:
MOV SEED,5555h
endd:
POPF
RET
RESEED ENDP
NRANDOM PROC FAR PUBLIC
PUSH CX ;( [BP+8] )
PUSH DX ;( [BP+6] )
PUSH ES ;( [BP+4] )
PUSHF ;SAVE FLAGS ( [BP+2] )
PUSH BP ;( [BP+0] )
MOV BP,SP
MOV AX,FAR_DATA ;SET ES-REGISTER TO POINT
MOV ES,AX ;TO FAR DATA SEGMENT
MOV AX,SEED ;X = SEED * MULTIPLIER mod 65536
MUL MULTIPLIER
ADD AX,ADDEND ;SEED = (X + ADDEND) mod 65536
MOV SEED,AX
MOV CX,[BP+16] ;UPPER - RANGE = UPPER - LOWER + 1
SUB CX,[BP+14] ;LOWER
INC CX
MUL CX ;RANDOM = (SEED*RANGE)/65536
ADD DX,[BP+14] ; + LOWER
MOV AX,DX
POP BP
POPF ;RESTORE FLAGS
POP ES ;RESTORE REGISTERS
POP DX
POP CX
RET 4 ;RETURN (RANDOM)
NRANDOM ENDP ;END NRANDOM
END
i had trouble making PutStrng work for me
in the documentation, it says it is a near procedure
when i try to link it as near, the linker has to do "fix-ups" (usually an indication of a problem like near/far)
when i link it as far, the linker does not do fix-ups, but i got garbage out
i disassembled some of the library code and found procedures in there using far returns
yet, all of the procedures in the documentation are specified as near procedures
at that point, i used int 21h, function 9 to display strings instead of PutStrng and it worked fine
i think the documentation you sent me is for a different library named UTIL.LIB
at any rate, i disassembled these library functions to see how regstiers are used
they are indeed FAR procedures - not NEAR like the document says
they are also all capital letters - again, not matching the document
;---------------------------------------------------------------------------------------------
PUTSTRNG requires the string be pointed to by ES:[DI] and be CX bytes long
so, for that part of the program, get DGROUP into the ES register and it should work
make sure that RESEED and NRANDOM preserve the ES register (i think i did that - lol)
MOV AX,DGROUP ;SET DS-REGISTER TO POINT TO
MOV DS,AX ;DATA SEGMENT
MOV ES,AX ;AND ES
GETDEC appears to return a 16-bit signed binary value in AX from keyboard entry - very strangely written routine - lol
NEWLINE has no input parameters and has no output other than a carriage return/line feed to the display
PUTDEC displays a 16-bit signed integer from AX to the display
if BH is 0, the string is left-justified, if BH is non-zero, the string is right-justified in a 6-character field
;---------------------------------------------------------------------------------------------
i see you muddled with RESEED - lol
cmp bl,0
jne NOTZERO
mov dx,5555h ;<-------------------------------------- take this line out
MOV AH,0 ; SEED = LOWER HALF OF
INT 1AH ; TIME OF DAY CLOCK
MOV SEED,DX ;<-------------------------- oops - you forgot that line
jmp short endd ;<-------------------------------------- add the short
NOTZERO:
MOV SEED,5555h
endd:
;---------------------------------------------------------------------------------------------
your loop structure is a little strange
you can use the CX register and LOOP for both inner and outer loops (and get rid of LOOPER)
MOV CX,10 ;LINE COUNT = 10
NUM_LOOP:
PUSH CX ;SAVE OUTER LOOP COUNT
MOV CX,10 ;NUMBERS PER LINE COUNT = 10
LINE_LOOP:
PUSH CX ;SAVE INNER LOOP OCUNT
.
.
.
POP CX ;RECALL INNER LOOP COUNT
LOOP LINE_LOOP
CALL NEWLINE
POP CX ;RECALL OUTER LOOP COUNT
LOOP NUM_LOOP
i would swap the names NUM_LOOP and LINE_LOOP - they make more sense reversed
swap them at both the top and the bottom
;---------------------------------------------------------------------------------------------
you are using LEA to get the offsets into DI - use MOV DI,offset___ instead
LEA DI, HIGHHEADER
mov is shorter and faster
MOV DI,OFFSET HIGHHEADER
depending on how the segments are ordered, you sometimes may have to use DGROUP:
(i don't think you need it in this case, but i thought i would mention it)
MOV DI,OFFSET DGROUP:HIGHHEADER
;---------------------------------------------------------------------------------------------
instead of counting characters and putting numbers into CX, use the SIZEOF operator
not only do you not have to count characters (a good place for mistakes),
but if you change the string, the count automatically changes for you
MOV CX,SIZEOF HIGHHEADER
;---------------------------------------------------------------------------------------------
one last note:
i could have used the DS register for the far routines instead of ES
you can get FAR_DATA into the DS register, so long as that register is preserved
by using ES, all of the references to the FAR_DATA area use a segment override (the assembler adds them)
.CODE
ASSUME DS:FAR_DATA ;<------------- change
.
.
.
RESEED PROC FAR PUBLIC USES AX CX DX DS ;<-------notice the change here
MOV AX,FAR_DATA ;SET DS-REGISTER TO POINT <------------- change the comment
MOV DS,AX ;TO FAR DATA SEGMENT <------------- change
.
.
.
NRANDOM PROC FAR PUBLIC
PUSH CX ;( [BP+8] )
PUSH DX ;( [BP+6] )
PUSH DS ;( [BP+4] ) <------------- change
PUSHF ;SAVE FLAGS ( [BP+2] )
PUSH BP ;( [BP+0] )
MOV BP,SP
MOV AX,FAR_DATA ;SET DS-REGISTER TO POINT <------------- change the comment
MOV DS,AX ;TO FAR DATA SEGMENT <------------- change
.
.
.
POP BP
POPF ;RESTORE FLAGS
POP DS ;RESTORE REGISTERS <------------- change
POP DX
POP CX
RET 4 ;RETURN (RANDOM)
NRANDOM ENDP ;END NRANDOM
i made those changes and added a few things - lol
see attached file
Enter 0 for Random Seed or 1 for 5555h Seed and Range 0-9999: 1
832 6809 8658 1206 5968 8066 3916 5338 8185 6129
2739 7450 3575 8968 2470 1758 732 7051 2952 4983
751 3347 6531 6342 7225 3324 8049 7555 6248 4952
4850 2840 6413 8699 6778 8916 8815 7534 6177 5001
7047 6925 7890 2816 7203 4842 9262 6577 7876 1753
135 3005 160 627 2854 1317 7650 6932 2263 3233
6438 8638 5704 2971 5119 6213 3023 7251 4787 2626
6563 5290 9034 3346 1166 8807 3955 6341 4179 2022
8144 2080 5443 1652 2695 3532 7302 6918 1200 6166
4602 9537 9754 7950 4684 3728 6950 9353 7393 6211
High: 56
Low: 44
Even: 54
Odd: 46
Enter 0 to Exit or 1 to Run Again: 1
Enter 0 for Random Seed or 1 for 5555h Seed and Range 0-9999: 0
Enter Lower End of Range: 300
Enter Upper End of Range: 500
348 498 384 399 357 383 348 324 366 385
323 497 410 426 470 461 373 477 395 416
389 360 360 408 443 347 474 333 368 361
496 340 451 372 435 424 424 403 350 432
473 325 352 462 430 461 399 460 382 382
301 422 462 310 318 397 455 318 358 481
395 327 382 420 366 308 397 411 303 485
465 302 390 327 493 390 463 359 442 420
403 350 320 391 347 324 389 348 480 352
355 390 433 356 380 462 494 307 473 361
High: 41
Low: 59
Even: 54
Odd: 46
Enter 0 to Exit or 1 to Run Again: 0
This is from a long time ago and I confess to being 15 years out of date with DOS software but something looked wrong in this directive,
.MODEL SMALL,BASIC
A very long time ago when I used to write assembler modules in MASM for Microsoft basic you always used,
.MODEL MEDIUM,BASIC
From memory you cannot access FAR data from a small memory model, MEDIUM, LARGE and HUGE are the ones that could handle FAR addressed segments.
we got her to LARGE, Hutch - lol
she wanted to use multiple code and data segments
i modified the last d/l so it works with negative range values
Enter 0 for Random Seed or 1 for 5555h Seed and Range 0-9999:
Enter Lower End of Range: -3000
Enter Upper End of Range: -2000
-2263 -2532 -2621 -2754 -2878 -2780 -2387 -2660 -2299 -2176
-2187 -2972 -2670 -2672 -2037 -2015 -2879 -2973 -2703 -2872
-2567 -2529 -2700 -2368 -2125 -2546 -2293 -2081 -2695 -2977
-2498 -2341 -2165 -2522 -2082 -2225 -2178 -2638 -2559 -2561
-2124 -2526 -2195 -2927 -2142 -2139 -2006 -2651 -2125 -2182
-2758 -2812 -2712 -2106 -2966 -2237 -2294 -2115 -2895 -2506
-2011 -2162 -2561 -2946 -2756 -2951 -2731 -2634 -2167 -2934
-2919 -2399 -2636 -2313 -2391 -2820 -2303 -2044 -2163 -2224
-2059 -2829 -2000 -2690 -2545 -2120 -2419 -2044 -2150 -2121
-2685 -2868 -2016 -2786 -2812 -2487 -2034 -2817 -2567 -2980
High: 48
Low: 52
Even: 50
Odd: 50
Enter 0 to Exit or 1 to Run Again:
Quote from: hutch-- on October 10, 2009, 12:46:19 PM
From memory you cannot access FAR data from a small memory model, MEDIUM, LARGE and HUGE are the ones that could handle FAR addressed segments.
Perhabs it's time to learn Masm, finally? After maintaining a Masm forum for so many years ...
Wow! Thank you so much for all your help, Dave. This really would have been a mess if I had done it alone.
no problem, Veronica
i was working on something else and needed a break from it to let it tumble around in my head - lol
this wasn't too hard, so i had 5 brain cells left to work on that at the same time :P
what if we decide to separate the Ressed PROC in separate file? can we easily do that ? and have 3 files main.asm, reseed.asm random.asm
certainly
you will just have to link 3 OBJ's (with the LIB, of course) together instead of 2
furthermore, the NRANDOM and RESEED OBJ's could be put into another library, or added to the IO.LIB library
that is how large projects are sometimes managed
or - if you have a set of commonly used routines
Somehow when I separate it in a file the printing numbers are not what they have to be for 5555h and always printing same ones when using the clock ... thats what I have. I believe there is problem with the definition of UPPER and LOWER if that is the issue I dont really know how to fix it ... First massive is printing 100 numbers using clock. second is printing using 5555h for SEED
;===================================================================
; MAIN.ASM of Random Numnbers
;
;
;===================================================================
.MODEL LARGE
.STACK 256
;===================================================================
;PROCEDURES TO
EXTRN NRANDOM:FAR ;PROCEDURE RANDOM
EXTRN RESEED:FAR ;PROCEDURE RESEED
EXTRN CLEAR:FAR ;CLEAR SCREEN
EXTRN NEWLINE:FAR ;DISPLAY NEWLINE CHARACTER
EXTRN PAUSE:FAR ;PAUSE UNTIL KEY STROKE
EXTRN PUTDEC:FAR
EXTRN PUTSTRNG:FAR ;DISPLAY CHARACTER STRING
;===================================================================
;DATA S E G M E N T D E F I N I T I O N
;
.DATA
UPPER DW 9999 ; set value for UPPER
LOWER DW 0 ; set value for LOWER
COUNTEVEN DW 0
COUNTODD DW 0
COUNTHIGH DW 0
COUNTLOW DW 0
COUNTER DW 0
HEADERHIGH DB 'High 5000-9999: '
HEADERLOW DB 'Low 0-4999: '
HEADEREVEN DB 'Even: '
HEADERODD DB 'ODD: '
SPACE DB ' '
PAUSE_MSG DB ' ANY KEY CONTINUES '
;OURSEED DB 'Numbers Using SEED 5555h are: '
;CLOCKSEED DB 'Numbers USING CLOCK SEED are: '
;===================================================================
;C O D E S E G M E N T D E F I N I T I O N
;
.CODE
ASSUME DS:DGROUP
;-------------------------------------------------------------------
MAIN PROC
MOV AX,DGROUP ;SET DS-REGISTER TO POINT TO
MOV DS,AX ;CONSTANT DATA SEGMENT
MOV BL,0
start:
CALL RESEED
MOV COUNTER,100 ;SET LOOP COUNTS 0 to 100
NUM_LOOP:
MOV CX,10 ;SET TO LOOP 10 numbers per line
LINE_LOOP:
PUSH CX
MOV AX,UPPER ;MOVE UPPER IN AX REGISTER 9999
PUSH AX ; PUSH AX VALUE INTO THE STACK
MOV AX,LOWER ;MOVE LOWER IN AX REGISTER 0
PUSH AX ;PUSH AX VALUE INTO THE STACK
CALL NRANDOM ;CALL PROC RANDOM
MOV BH,+1
CALL PUTDEC
LEA DI,SPACE
MOV CX,1
CALL PUTSTRNG
CMP AX,5000
JAE SEQHIGH
INC COUNTLOW
JMP SHORT HILO_COUNTER
SEQHIGH:
INC COUNTHIGH
HILO_COUNTER:
SHR AX,1
JC ODDS
INC COUNTEVEN
JMP SHORT EVENODD_COUNTER
ODDS:
INC COUNTODD
EVENODD_COUNTER:
POP CX
LOOP LINE_LOOP
CALL NEWLINE
SUB COUNTER,10
CMP COUNTER,0
MOV AX,DGROUP
MOV ES,AX
JNE NUM_LOOP
; ======= PRINT STATISTIC OF NUMBERS ON SCREEN========
CALL NEWLINE
INC BL
CMP BL,1
JE START
CALL NEWLINE
CALL NEWLINE
LEA DI,HEADERHIGH
MOV CX,16
CALL PUTSTRNG
MOV AX, COUNTHIGH
CALL PUTDEC
CALL NEWLINE
LEA DI,HEADERLOW
MOV CX,16
CALL PUTSTRNG
MOV AX,COUNTLOW
CALL PUTDEC
CALL NEWLINE
LEA DI,HEADEREVEN
MOV CX,16
CALL PUTSTRNG
MOV AX,COUNTEVEN
CALL PUTDEC
CALL NEWLINE
LEA DI,HEADERODD
MOV CX,16
CALL PUTSTRNG
MOV AX, COUNTODD
CALL PUTDEC
CALL NEWLINE
CALL NEWLINE ; DISPLAY NEWLINE CHAR.
LEA DI,PAUSE_MSG ; PAUSE AND WAIT FOR
MOV CX,21 ; KEY STROKE
CALL PAUSE
;========= END PRINT STATISTIC OF NUMBERS ON SCREEN ;
.exit
MAIN ENDP
END MAIN
;===================================================================
; RESEED.ASM
; r a n d o m n u m b e r g e n e r a t o r
;
; GENERATES PSEUDO-RANDOM INTEGERS IN THE RANGE LOWER TO UPPER
; INPUT: TWO STACK PARAMETERS - LOWER AND UPPER ENDS OF RANGE
; OUTPUT: AX-REG CONTAINS RANDOM INTEGER
; CALLING SEQUENCE: PUSH <LOWER END OF RANGE>
; PUSH <UPPER END OF RANGE>
; CALL RANDOM
;===================================================================
.MODEL SMALL,BASIC
;===================================================================
EXTRN NRANDOM:FAR
PUBLIC SEED
PUBLIC RESEED
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
;MULTIPLIER DW 25173 ;MULTIPLIER AND
;ADDEND DW 13849 ;ADDEND FOR MIXED
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
;
.CODE
ASSUME DS:FAR_DATA
;---------------------------------------------------------------------
RESEED PROC FAR PUBLIC USES AX CX DX DS
MOV AX,FAR_DATA ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO FAR DATA SEGMENT
PUSHF
cmp bl,0
jne NOTZERO
MOV AH,0 ; SEED = LOWER HALF OF
INT 1AH ; TIME OF DAY CLOCK
MOV SEED,DX
jmp short endd
NOTZERO:
MOV SEED,5555h
endd:
POPF
RET
RESEED ENDP
END
;===================================================================
; RAND.ASM
; r a n d o m n u m b e r g e n e r a t o r
;
; GENERATES PSEUDO-RANDOM INTEGERS IN THE RANGE LOWER TO UPPER
; INPUT: TWO STACK PARAMETERS - LOWER AND UPPER ENDS OF RANGE
; OUTPUT: AX-REG CONTAINS RANDOM INTEGER
; CALLING SEQUENCE: PUSH <LOWER END OF RANGE>
; PUSH <UPPER END OF RANGE>
; CALL RANDOM
;===================================================================
.MODEL LARGE
;===================================================================
PUBLIC NRANDOM
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849 ;ADDEND FOR MIXED
UPPER DW 9999
LOWER DW 0
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
;
.CODE
ASSUME DS:FAR_DATA
;---------------------------------------------------------------------
NRANDOM PROC FAR PUBLIC
PUSH DS ;
PUSHF ;SAVE FLAGS
MOV AX,FAR_DATA ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO FAR DATA SEGMENT
MOV AX,SEED ;X = SEED * MULTIPLIER mod
MUL MULTIPLIER ; 65536
ADD AX,ADDEND ;SEED = (X + ADDEND) mod 65536
MOV SEED,AX
MOV CX,UPPER ;RANGE = UPPER - LOWER + 1
SUB CX,LOWER
INC CX
MUL CX ;RANDOM = (SEED*RANGE)/65536
ADD DX,LOWER ; + LOWER
MOV AX,DX
POPF ;RESTORE FLAGS
POP DS ;RESTORE REGISTERS
RET 4 ;RETURN (RANDOM)
NRANDOM ENDP ;END NRANDOM
END
IF the RSEED PROC portion is in the random.asm everything works perfect when separate it in own file it doesnt. still prints but not what it is supposed to ...
Thank you
Edit: Added code tags
well - you have to look at the last download i posted
UPPER and LOWER are passed to NRANDOM on the stack
but, another problem you have is that SEED is defined as seperate data values in NRANDOM and RESEED
it needs to be a single data item
in the file where it is defined, it should be declared as PUBLIC
in the other files, it should be listed as EXTERN SEED:WORD
It looks like I am in the same class this semester and frankly this teacher is crazy to expect us to figure this stuff out on our own. The book isn't much help; he's pulling these assignments from a different book he used probably 10+ years ago (he says it's no longer being published). The code that we're supposed to "not worry about for now" changes with every example, and apparently, we DO need to worry about it this time. I'd be surprised if half the class got half-credit on this thing, especially with the way he grades.
Sorry, had let off some steam...
ok - i had to use an ASSUME directive to let RESEED know which segment DS was in...
i also changed the name of RANDOM.ASM to NRANDOM.ASM to avoid confusion
(the io.lib file has a RANDOM proc in it, as well)
Mikey - many professors suck - lol
this probably isn't the first and won't be the last
he shouldn't be teaching 16-bit code at all - a waste of time, in a way
he should be teaching 32-bit code
it is kinda obvious, he doesn't know 32-bit code
he barely knows 16-bit
still - be thankful
when i went to school, i had to punch thousands of holerith cards
then, wait in a long line to load the program
then - wait some more for the computer to decide to run it
if i had even the slightest mistake - i had to do most of that over again
and - format statements in fortran - easy to make a mistake - lol
EDIT - there must be a better way to handle SEED as an external
it might be something like EXTERN SEED:FAR_DATA:WORD or FAR PTR WORD - i dunno
the last time i did this stuff, i was using MASM version 5.10 and that was a while back - lol
Aggree with Mikey....
dedndave: I have the push think in my tree files however it still doesnt work. It seems we are all in one class. We better submit different codes ... So please anybody who use that message board to do his own private changes of the coding in his program.
That's why I would like to make my version to work. I will atach my files I have so far. It still can not compile. Lower and Upper gives me error. Please can you take a look if possible..
the major difference in mine is the clock seed procedure. ohh yeah and I am printing both massives at ones and my statistic is for the 200 numbers ...
thank you dedndave :)
i had written the seed routine differently, but Veronica didn't like it - lol
i had something like...
.
.
.
mov dx,5555h
or bl,bl
jnz RExit0
mov ah,0
int 1Ah
RExit0: mov SEED,dx
ret
as for the stack parameters LOWER and UPPER, they can be declared in the PROC directive
NRANDOM PROC LOWER:WORD,UPPER:WORD
the assembler will figure out the correct [bp+nnnn] stack pointer for you
but, when i use a stack frame, i prefer to do that myself
back in the days, the assembler didn't do all that fancy stuff - lol
I guess the problem of my program is I am using that:
NRANDOM PROC FAR PUBLIC
;PUSH CX ;( [BP+8] )
;PUSH DX ;( [BP+6] )
PUSH DS ;( [BP+4] )
PUSHF ;SAVE FLAGS ( [BP+2] )
MOV AX,FAR_DATA ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO FAR DATA SEGMENT
MOV AX,SEED ;X = SEED * MULTIPLIER mod
MUL MULTIPLIER ; 65536
ADD AX,ADDEND ;SEED = (X + ADDEND) mod 65536
MOV SEED,AX
MOV CX,UPPER ;RANGE = UPPER - LOWER + 1
SUB CX,LOWER
INC CX
MUL CX ;RANDOM = (SEED*RANGE)/65536
ADD DX,LOWER ; + LOWER
MOV AX,DX
;POP BP
POPF ;RESTORE FLAGS
POP DS ;RESTORE REGISTERS
;POP DX
;POP CX
RET 4 ;RETURN (RANDOM)
NRANDOM ENDP ;END NRANDOM
END
NRANDOM ENDP ;END NRANDOM
END
Instead of [BP+...]
I dont know how to make it with my procedure for clock time .... MOV CX,[BP+16] is maybe easier for the compiler than MOV CX,UPPER
I am trying to set it with my procedure for clock time but cant ...
delete the
LOWER DW ?
UPPER DW ?
then, try this...
NRANDOM PROC FAR USES CX DX DS LOWER:WORD,UPPER:WORD
.
.
pushf
.
.
.
mov cx,UPPER
sub cx,LOWER
.
.
.
popf
ret
the assembler should generate all the code to access the variables on the stack, as well as saving/restoring registers
the values UPPER and LOWER are provided by MAIN when it calls NRANDOM (by pushing them onto the stack)
the assembler also generates the RET 4 at the end
I guess I cant get it ...
Assembling: main.ASM
Assembling: nrandom.ASM
nrandom.ASM(33): error A2119: language type must be specified
nrandom.ASM(50): error A2006: undefined symbol : UPPER
nrandom.ASM(51): error A2006: undefined symbol : LOWER
nrandom.ASM(54): error A2006: undefined symbol : LOWER
Assembling: reseed.asm
;===================================================================
; RAND.ASM
;===================================================================
.MODEL LARGE
;===================================================================
PUBLIC SEED
PUBLIC NRANDOM
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849 ;ADDEND FOR MIXED
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
;
.CODE
ASSUME DS:FAR_DATA
;---------------------------------------------------------------------
NRANDOM PROC FAR USES CX DX DS LOWER:WORD,UPPER:WORD
;PUSH CX ;( [BP+8] )
;PUSH DX ;( [BP+6] )
PUSH DS
PUSHF ;SAVE FLAGS
;PUSH BP ;( [BP+0] )
;MOV BP,SP
MOV AX,FAR_DATA ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO FAR DATA SEGMENT
MOV AX,SEED ;X = SEED * MULTIPLIER mod
MUL MULTIPLIER ; 65536
ADD AX,ADDEND ;SEED = (X + ADDEND) mod 65536
MOV SEED,AX
MOV CX,UPPER ;RANGE = UPPER - LOWER + 1
SUB CX,LOWER
INC CX
MUL CX ;RANDOM = (SEED*RANGE)/65536
ADD DX,LOWER ; + LOWER
MOV AX,DX
;POP BP
POPF ;RESTORE FLAGS
POP DS ;RESTORE REGISTERS
;POP DX
;POP CX
RET
NRANDOM ENDP ;END NRANDOM
ok - you can take push/pop ds out - they are taken care of in the proc directive
however, that is not the problem
i am running a test at the moment - it is almost done
let me finish that and we will take a look
Well, whichever classmates you guys are, I will see you in about an hour. I barely got something to work (or it appears to anyway). I'll post pieces in case someone else reading this is tempted to copy directly.
This is most of my main.asm
;===================================================================
;D A T A S E G M E N T
;
.DATA
PUBLIC SEED
SEED DW 5555H
EVENS DW 0
ODDS DW 0
HIGHS DW 0
LOWS DW 0
;===================================================================
;C O D E S E G M E N T D E F I N I T I O N
;
.CODE
RANDMAIN:
MOV AX,DGROUP ;SET DS AND ES-REGISTER TO
MOV DS,AX ;POINT TO DATA SEGMENT
MOV ES,AX ;
; SET FIRST SEED TO 5555H
MOV BL,0 ;
SEED_LOOP:
CALL RESEED ;
PUSH BX ;
MOV CX,0 ;INIT. LINE COUNT = 1
LINE_LOOP:
CMP CX,10 ;IF LINE COUNT == 10
JE END_LINE_LOOP ; THEN END LOOP
INC CX ;COUNT++
PUSH CX ;
MOV CX,0 ;INIT. NUM COUNT = 1
NUM_LOOP:
CMP CX,10 ;IF NUM COUNT == 10
JE END_NUM_LOOP ; THEN END LOOP
INC CX ;COUNT++
PUSH CX ;
MOV AX,0 ;RAND RANGE, LOWER
PUSH AX ;
MOV AX,9999 ;RAND RANGE, UPPER
PUSH AX ;
CALL RANDOM ;AX = RANDOM NUMBER
MOV BH,1 ;DISP. 16-BIT NUM IN AX
CALL PUTDEC$ ;DISP.
JMP ADD_STATS ;
GOT_STATS:
POP CX ;
JMP NUM_LOOP ;
END_NUM_LOOP:
CALL NEWLINE ;
POP CX ;
JMP LINE_LOOP ;
END_LINE_LOOP:
; DISPLAY STATS
LEA DI,STAT_HDR ;DISP. STAT_HDR
MOV CX,30 ;DISP. 30 CHARS
CALL PUTSTRNG ;DISP.
CALL NEWLINE ;
MOV BH,-1 ;DISP. LEFT-JUSTIFY
MOV AX,EVENS ;DISP. EVENS
CALL PUTDEC$ ;DISP.
MOV AX,ODDS ;DISP. ODDS
CALL PUTDEC$ ;DISP.
MOV AX,HIGHS ;DISP. HIGHS
CALL PUTDEC$ ;DISP.
MOV AX,LOWS ;DISP. LOWS
CALL PUTDEC$ ;DISP.
MOV EVENS,0 ;RESET TO ZERO
MOV ODDS,0 ;RESET TO ZERO
MOV HIGHS,0 ;RESET TO ZERO
MOV LOWS,0 ;RESET TO ZERO
POP BX ;IF ALREADY DID CLOCK
CMP BL,0 ;SEED, END_SEED_LOOP
JNE END_SEED_LOOP ;ELSE DO CLOCK SEED
CALL NEWLINE ;
MOV BL,1 ;
JMP SEED_LOOP ;
END_SEED_LOOP:
JMP DONE
ADD_STATS:
PUSH AX
PUSH AX
; IF EVEN, GOTO EVENS
AND AX,1
CMP AX,0
JE IS_EVEN
INC ODDS
JMP HIGH_LOW
IS_EVEN:
INC EVENS
HIGH_LOW:
; IF HIGH, GOTO HIGHS
POP AX
CMP AX,4999
JA IS_HIGH
INC LOWS
JMP END_ADD_STATS
IS_HIGH:
INC HIGHS
END_ADD_STATS:
POP AX
JMP GOT_STATS
This is the section of my reseed.asm that seems to allow me to access SEED and whatnot
.DATA
EXTRN SEED:WORD
PUBLIC MULTIPLIER,ADDEND
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849 ;ADDEND FOR MIXED
;LINEAR CONGRUENTIAL METHOD
;===================================================================
; C O D E S E G M E N T
;
.CODE
PUBLIC RESEED
RESEED PROC FAR PUBLIC USES BX CX DX DS
;SAVE REGISTERS (USES LIST)
PUSHF ;SAVE FLAGS
MOV AX,DGROUP ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO LOCAL DATA SEGMENT
MOV ES,AX
Here's part of rand.asm, again, the critical part for me that got the variables working
;===================================================================
.MODEL SMALL,BASIC
;===================================================================
; D A T A S E G M E N T
.DATA
EXTRN SEED:WORD
EXTRN MULTIPLIER:WORD
EXTRN ADDEND:WORD
;===================================================================
; C O D E S E G M E N T
;
.CODE
PUBLIC RANDOM
RANDOM PROC FAR PUBLIC USES CX DX DS,
LOWER:WORD, UPPER:WORD
;FUNCTION RANDOM(LOWER,UPPER)
;SAVE REGISTERS (USES LIST)
PUSHF ;SAVE FLAGS
MOV AX,DGROUP ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO LOCAL DATA SEGMENT
MOV ES,AX
I'm sure it looks very ugly to experienced eyes but I'm using what I have available to me. Like Veronica, I also didn't want to stray too far from the teacher's teachings for fear of losing more points.
lol - good job Mikey
ilian:
the PROC directive wants to see a language specified - let me look that up in the handy MASM manual...
this one assembles and works
i added the language BASIC to the .MODEL directive...
to follow the BASIC calling convention, i had to swap the order of LOWER and UPPER
;===================================================================
; NRANDOM.ASM
; r a n d o m n u m b e r g e n e r a t o r
; GENERATES PSEUDO-RANDOM INTEGERS IN THE RANGE LOWER TO UPPER
; INPUT: TWO STACK PARAMETERS - LOWER AND UPPER ENDS OF RANGE
; OUTPUT: AX-REG CONTAINS RANDOM INTEGER
; CALLING SEQUENCE: PUSH <UPPER END OF RANGE>
; PUSH <LOWER END OF RANGE>
; CALL RANDOM
;===================================================================
.MODEL LARGE,BASIC
;===================================================================
PUBLIC SEED
PUBLIC NRANDOM
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
ASSUME DS:FAR_DATA
;===================================================================
NRANDOM PROC FAR USES CX DX DS UPPER:WORD,LOWER:WORD
PUSHF ;SAVE FLAGS
MOV AX,FAR_DATA ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO FAR DATA SEGMENT
MOV AX,SEED ;X = SEED * MULTIPLIER mod 65536
MUL MULTIPLIER
ADD AX,ADDEND ;SEED = (X + ADDEND) mod 65536
MOV SEED,AX
MOV CX,UPPER ;UPPER - RANGE = UPPER - LOWER + 1
SUB CX,LOWER ;LOWER
INC CX
MUL CX ;RANDOM = (SEED*RANGE)/65536
ADD DX,LOWER ; + LOWER
MOV AX,DX
POPF ;RESTORE FLAGS
RET ;RETURN (NRANDOM)
NRANDOM ENDP ;END NRANDOM
END
Thank you DEDNDAVE it all works now. Thanks ! :)
well - i know that ASSUME DS:SEG SEED can be done a better way
that would be clumsy if we had to reference several variables in the RESEED module
we just need to figure out how to tell the assembler that SEED is in the FAR_DATA segment
it can probably be specified in the EXTERN directive somehow
then we can use ASSUME DS:FAR_DATA and MOV AX,FAR_DATA
maybe MichaelW or Steve (FORTRANS) can help us out
;===================================================================
; RESEED.ASM
; INPUT: BL = 0 - gets a seed value from the time-of day counter
; BL <> 0 - sets the test seed value of 5555h
;
;===================================================================
.MODEL LARGE
;===================================================================
EXTERN SEED:WORD
PUBLIC RESEED
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
ASSUME DS:SEG SEED
;===================================================================
RESEED PROC FAR PUBLIC USES AX CX DX DS
MOV AX,SEG SEED ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO FAR DATA SEGMENT
MOV DX,5555h
OR BL,BL
JNZ NOTZERO
MOV AH,0 ; SEED = LOWER HALF OF
INT 1AH ; TIME OF DAY CLOCK
NOTZERO:
MOV SEED,DX
RET
RESEED ENDP
END
in fact I've changed it to DS:DGROUP and AX,DGROUP and it still works I guess NRANDOM is getting values thru the EXTRNals. originally the teachers procedure has set the DS in NRANDOM that way:
- - - -
.MODEL SMALL,BASIC
;===================================================================
FALSE EQU 0 ;CONSTANT FALSE
TRUE EQU 1 ;CONSTANT TRUE
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.FARDATA RAND_DATA
SEED DW ? ;SEED FOR RANDOM NUMBER GEN.
MULTIPLIER DW 25173 ;MULTIPLIER AND
ADDEND DW 13849 ;ADDEND FOR MIXED
LOWER DW 0 ;LINEAR CONGRUENTIAL UPPER DW 9999
METHOD
FIRST_CALL DB TRUE ;FIRST CALL FLAG
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
;
.CODE RAND
ASSUME DS:RAND_DATA
;
RANDOM PROC FAR PUBLIC USES CX DX DS,
LOWER:WORD, UPPER:WORD
;FUNCTION RANDOM(LOWER,UPPER)
;SAVE REGISTERS (USES LIST)
PUSHF ;SAVE FLAGS
MOV AX,SEG RAND_DATA ;SET DS-REGISTER TO POINT
MOV DS,AX ;TO LOCAL DATA SEGMENT
- - ->
- - ->
one thing your prof should have taught you - lol
TRUE is the inverse of false
for boolean math, TRUE should be all 1's (or -1)
that way, you can perform bit-wise logic with it
FALSE EQU 0
TRUE EQU NOT FALSE
Quote from: dedndave on October 13, 2009, 11:50:56 PM
for boolean math, TRUE should be all 1's (or -1)
that way, you can perform bit-wise logic with it
FALSE EQU 0
TRUE EQU NOT FALSE
You have truely good ideas, Dave. Go and tell Billieboy - Redmond voted for
plus 1. By design, of course ::)
@ilian007: The Masm32 library uses +1, like Microsoft. Stupid but that's it...
i know that's true, Jochen, but no need to perpetuate a bad habit - lol
odd they did that - billy boy had it right in ms basic
Z says hi and sends a K
:bg
> Perhabs it's time to learn Masm, finally? After maintaining a Masm forum for so many years ...
Yeah. learn to tune up a T model Ford to win Indy. I confess to never having wasted my time on old junk like this since about 1995, feel free to be the 16 bit real mode DOS guru. :P
Next cab off the rank can be Digital Research DOS. :bdg
hahah Yeah the teacher wonders why programs (we try to compile) gives random errors on Vista. Then he concludes: "who knows what will be in the future" :)))
However, we have new project assigned. The problem is unclear I will ask him some questions in class tonite and will start it then. :) it is something playing with Parity and Shifting thing. To be Continued .... :P
MichaelW and/or Steven FORTRANS
i would still like a little help on this one...
http://www.masm32.com/board/index.php?topic=12477.msg96303#msg96303
Hi,
I will look at it later, but what I will first try is to put an empty ".FARDATA'
declaration/directive in the file. I got side tracked on some misleading
documentation in an old TASM 2.0 document. And nearly posted some
complete (incomplete?) garbage. Amazing what MASM will assemble
at times. I generally do not use the simplified directives in 16-bit code
as they did not exist when I was learning the craft.
Oh well, here comes a weekend. And I will be back on the machine with
the better setup.
Cheers,
Steve N.
thanks for looking at it, Steve
i tried the .FARDATA thing
masm wants to name these far data segments with the module name
for example, in the reseed.asm module, it named it as RESEED_DATA (or something to that effect)
when i create the .FARDATA segment in NRANDOM, and try to use ASSUME, it is looking in the wrong segment
this did not happen with masm 5.10 - well - i always opened and closed my own segments with SEGMENT
perhaps, that is the best solution
FAR_DATA SEGMENT WORD PUBLIC 'FAR_DATA'
FAR_DATA ENDS
then, all the modules will reference the same segment
Hi Dave,
Quotemasm wants to name these far data segments with the module name
Ew.
Quotethis did not happen with masm 5.10
Then I would have posted bad code anyway... Unless I had the sense
to double check it in 6.14. Most of the time I'm using a machine with
5.0 for 16-bit code. The one with 6.14 gets used for 32-bit stuff, and is
a bit screwed up, or cursed, or Windows, or whatever, or all of the above.
Quotei always opened and closed my own segments with SEGMENT
perhaps, that is the best solution
Unless that goes against the course rules, that looks good to me.
They will have to know the differences between SEGMENT/ENDS and
.DATA/.CODE usage, and that only makes sense if they have covered
it somewhere. If so, try both ways AND look at the listing and cross
reference files.
Again, I'll try to see what happens with the .FARDATA glop later on.
Thanks,
Steve
How can I count how many 1's are in a 16bit binary number ?
for example : 0001011101101011 - they are 9 - 1's do I have to MASK it with an 'AND' ?
or I have to SHR and to create procedure with COUNTER which will count the JC ..
thanks
http://www.masm32.com/board/index.php?topic=12528.msg96432#msg96432
thanks dedndave actually I made it last night :) used SHR and JC :P i will continue to post to the other topic because still have some dificulties with something. thanks will talk there
Quote from: hutch-- on October 14, 2009, 12:33:35 PM
:bg
Yeah. learn to tune up a T model Ford to win Indy. I confess to never having wasted my time on old junk like this since about 1995, feel free to be the 16 bit real mode DOS guru. :P
Yes, I know this "old junk". It's essential knowledge. Knowing how to do "Win32 application programming with Masm" isn't the whole world of assembly, just in case you didn't know that.