Assigning value to the variable present in previous line using $ sign

后端 未结 1 1000
小鲜肉
小鲜肉 2021-01-21 18:50

I\'m trying to understand the MS-DOS v2.0 source code, and in particular some of the code in MSDATA.ASM. This code was originally assembled with a 35+ year old MASM assembler (a

相关标签:
1条回答
  • 2021-01-21 19:22

    It appears that the developers were intent on using the I_AM macro to make symbols (that point at BYTEs, WORDs, and DWORDs) publicly accessible by other modules. The problem is that the I_AM macro doesn't allow you to specify the data, it leaves it uninitialised as ?. To get around that the developers decided to back the program counter up to overwrite the uninitialised data so they could fill it in with a WORD value of 80h and a second WORD that is uninitialised (?).

    You aren't allowed to use an expressions with an org that is negative. You couldn't back the program counter up with:

    org -4
    

    You need an absolute value. You need to know how far the program counter is from the beginning of the segment. They chose to do that by setting up CONSTRT at the top with:

    CONSTANTS       SEGMENT BYTE PUBLIC 'CONST'
            EXTRN   international_table:BYTE
            EXTRN   Current_Country:WORD
    
    
            ORG     0
    CONSTRT EQU     $               ; Start of constants segment
    

    In this case CONSTRT is given the value 0 (the start of the segment). $ is the current program counter relative to the beginning of the segment.

    To determine the absolute value of the current program counter 4 bytes earlier you can take the current program counter $ and subtract it from the program counter at the beginning of the segment (which CONSTRT is set to). Once you know how far you are from the beginning of the segment you subtract 4.

    What we have then is:

        I_AM    DMAADD,DWORD            ; User's disk transfer address
                                        ; (disp/seg)
    

    That defines a publicly accessible label that is defined as pointing at an uninitialised DWORD value. This backs up the program counter by 4 to replace the uninitialised DWORD:

            ORG     $-CONSTRT-4
    

    This then emits the WORD value 80h followed by an uninitialised WORD value:

            DW      80H
            DW      ?
    

    You could have replaced the I_AM macro, the backing up of the pointer and replacing of the data with:

            public DMAADD
            DMAADD dd 80h
    

    It may be that the DOS developers always exported labels that point at BYTE, WORD, DWORD data via the I_AM macro as a coding requirement at Microsoft. This is entirely speculative. They may have felt that a common macro would allow them to change the method of exporting such data without changing code in countless places.

    0 讨论(0)
提交回复
热议问题