Присвоение значения переменной, представленной в предыдущей строке, с помощью знака $ - PullRequest
2 голосов
/ 17 июня 2019

Я пытаюсь понять исходный код MS-DOS v2.0 и, в частности, часть кода в MSDATA.ASM .Этот код был изначально собран с 35-летнего ассемблера MASM (версия, которая не была коммерчески доступна).Код, который меня интересует, находится в самом начале:

SUBTTL Initialized data and data used at DOS initialization
PAGE
; DATA AREA for MS-DOS

IFNDEF  KANJI
KANJI   EQU     0       ;FALSE
ENDIF

CONSTANTS       SEGMENT BYTE PUBLIC 'CONST'
        EXTRN   international_table:BYTE
        EXTRN   Current_Country:WORD


        ORG     0
CONSTRT EQU     $               ; Start of constants segment

        PUBLIC  DevStrLen
DEVSTRLEN DB    3              ; Size of below
        PUBLIC  DevString
DEVSTRING DB    "DEV"          ; Dummy device directory

;
; Table of routines for assignable devices
;
; MSDOS allows assignment if the following standard devices:
;   stdin  (usually CON input)
;   stdout (usually CON output)
;   auxin  (usually AUX input)
;   auxout (usually AUX output)
;   stdlpt (usually PRN output)
;
; SPECIAL NOTE:
;   Status of a file is a strange idea.  We choose to handle it in this manner:
;   If we're not at end-of-file, then we always say that we have a character.
;   Otherwise, we return ^Z as the character and set the ZERO flag.  In this
;   manner we can support program written under the old DOS (they use ^Z as EOF
;   on devices) and programs written under the new DOS (they use the ZERO flag
;   as EOF).

; Default FCBs for boot up

sftabl      LABEL   DWORD                     ; file table
            DW      -1
            DW      -1
            DW      sf_default_number  ; Number of entries in table
            DB      sf_default_number DUP ( (SIZE sf_entry) DUP (0))

        I_AM    NoSetDir,BYTE           ; true -> do not set directory
        I_am    DidCTRLC,BYTE           ; true -> we did a ^C exit
        I_am    SpaceFlag,BYTE          ; true -> embedded spaces are allowed
                                        ; in FCB
; the next two variables relate to the position of the logical stdout/stdin
; cursor.  They are only meaningful when stdin/stdout are assigned to the
; console.

        i_am    CARPOS,BYTE             ; cursor position in stdin
        i_am    STARTPOS,BYTE           ; position of cursor at beginning
                                        ; of buffered input call
        I_AM    PFLAG,BYTE
        I_AM    VERFLG,BYTE             ; Initialize with verify off
        I_AM    CONTPOS,WORD
        PUBLIC  CHARCO
CHARCO      DB      00000011B           ; Allows statchks every 4 chars...

        I_AM    DMAADD,DWORD            ; User's disk transfer address
                                        ; (disp/seg)
            ORG     $-CONSTRT-4
            DW      80H
            DW      ?

ENDMEM      DW      ?

Я пытаюсь понять этот код, в частности:

        I_AM    DMAADD,DWORD            ; User's disk transfer address
                                        ; (disp/seg)
            ORG     $-CONSTRT-4
            DW      80H
            DW      ?

ENDMEM      DW      ?

Кажется, он определяет публичную переменную DWORD DMAADD затем присваивает переменной DMAADD значения 80H первому слову, а затем ? второму слову.У меня есть некоторые сомнения, и, возможно, самый важный вопрос - почему он делает это таким образом, вместо того, чтобы просто присваивать значение 80H переменной DMAADD следующей строке.Почему эта стратегия применяется здесь и какова ее цель?ПОЧЕМУ ORG $-CONSTRT-4?


Макрос I_AM определяется и описывается следующим образом:

;
; define a data item to be public and of an appropriate size/type
;
I_AM    MACRO   name,size
    PUBLIC  name

    IFIDN <size>,<WORD>
        name    DW  ?
    ELSE
        IFIDN <size>,<DWORD>
            name    DD  ?
        ELSE
            IFIDN <size>,<BYTE>
                name    DB  ?
            ELSE
                name    DB  size DUP (?)
            ENDIF
        ENDIF
    ENDIF
ENDM

1 Ответ

3 голосов
/ 17 июня 2019

Похоже, что разработчики намеревались использовать макрос I_AM, чтобы сделать символы (указывающие на BYTE, WORD и DWORD) общедоступными для других модулей. Проблема в том, что макрос I_AM не позволяет указывать данные, он оставляет их неинициализированными как ?. Чтобы обойти это, разработчики решили создать резервную копию счетчика программы, чтобы перезаписать неинициализированные данные, чтобы они могли заполнить их значением WORD 80h и вторым неинициализированным WORD (?).

Вы не можете использовать выражения с org, который является отрицательным. Вы не можете создать резервную копию счетчика программы:

org -4

Вам нужно абсолютное значение. Вам нужно знать, как далеко находится счетчик программ от начала сегмента. Они решили сделать это, установив CONSTRT вверху с помощью:

CONSTANTS       SEGMENT BYTE PUBLIC 'CONST'
        EXTRN   international_table:BYTE
        EXTRN   Current_Country:WORD


        ORG     0
CONSTRT EQU     $               ; Start of constants segment

В этом случае CONSTRT присваивается значение 0 (начало сегмента). $ - текущий счетчик программы относительно начала сегмента.

Чтобы определить абсолютное значение счетчика текущей программы на 4 байта раньше, вы можете взять счетчик текущей программы $ и вычесть его из счетчика программы в начале сегмента (для которого установлено значение CONSTRT). Как только вы знаете, как далеко вы находитесь от начала сегмента, вы вычитаете 4.

Что мы имеем тогда:

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

Это определяет общедоступную метку, которая определяется как указывающая на неинициализированное значение DWORD. Это создает резервную копию счетчика программы на 4 для замены неинициализированного DWORD:

        ORG     $-CONSTRT-4

Затем выдается значение WORD 80h, за которым следует неинициализированное значение WORD:

        DW      80H
        DW      ?

Вы могли бы заменить макрос I_AM, резервное копирование указателя и заменить данные на:

        public DMAADD
        DMAADD dd 80h

Возможно, разработчики DOS всегда экспортировали метки, указывающие на данные BYTE, WORD, DWORD через макрос I_AM, как требование кодирования в Microsoft. Это полностью умозрительно. Возможно, они чувствовали, что общий макрос позволит им изменить метод экспорта таких данных без изменения кода в бесчисленных местах.

...