News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Linking programs

Started by veronicak5678, October 09, 2009, 02:33:44 AM

Previous topic - Next topic

veronicak5678

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!


dedndave

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

veronicak5678

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!

dedndave

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


MichaelW

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;
eschew obfuscation

dedndave

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

FORTRANS

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

dedndave

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

FORTRANS

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.

dedndave

you got me on bad spelling, Steve - lol
i am guilty   :P

veronicak5678

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.

dedndave

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

veronicak5678

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.

FORTRANS

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.

veronicak5678

Thanks for answering. I added the far and am using only 1 data segment, but still I get an error.