使用$符号将值赋给上一行中存在的变量 [英] Assigning value to the variable present in previous line using $ sign

查看:76
本文介绍了使用$符号将值赋给上一行中存在的变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解MS-DOS v2.0 源代码,并且特别是 MSDATA.ASM中的某些代码.该代码最初是使用35年以上的MASM汇编程序(该版本尚未在市场上出售)进行汇编的.我感兴趣的代码即将开始:

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 version that wasn't commercially available). The code I'm interested in is near the beginning:

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'm trying to understand this code in particular:

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

ENDMEM      DW      ?

似乎定义了DWORD公共变量DMAADD,然后将变量80H的值80H分配给第一个单词,然后将?分配给第二个单词.我心中有一个疑问,也许最重要的问题是-为什么这样做,而不是将80H的值分配给变量DMAADD的下一行.为什么在此应用此策略,其目的是什么?为什么ORG $-CONSTRT-4?

It appears to define a DWORD public variable DMAADD then it assigns the variable DMAADD the values 80H to the first word and then ? to the second word. I have some doubt in my mind and perhaps the most important question is - why is it doing it this way, instead of just assigning value of 80H to the variable DMAADD to the next line. Why is this strategy being applied here, and what is its purpose? WHy the ORG $-CONSTRT-4?

I_AM宏的定义和描述方式如下:

The I_AM macro is defined and described this way:

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

推荐答案

开发人员似乎打算使用I_AM宏来使其他模块可公开访问的符号(指向BYTE,WORD和DWORD) .问题是I_AM宏不允许您指定数据,它使数据未初始化为?.为了解决这个问题,开发人员决定备份程序计数器以覆盖未初始化的数据,以便他们可以用80h的WORD值和未初始化的第二个WORD(?)填充它.

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 (?).

不允许使用带有org的负数的表达式.您无法通过以下方式备份程序计数器:

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

您需要一个绝对值.您需要知道程序计数器距段的开头有多远.他们选择通过在顶部设置CONSTRT来做到这一点:

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

在这种情况下,CONSTRT被赋予值0(段的开始). $是相对于段开头的当前程序计数器.

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.

要确定当前程序计数器的绝对值早4个字节,可以采用当前程序计数器$,并从段开头(设置为CONSTRT)的程序计数器中减去它.一旦知道离分段的起点有多远,就减去4.

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.

那么我们就是:

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

这定义了一个公共可访问的标签,该标签被定义为指向未初始化的DWORD值.这样会将程序计数器备份4,以替换未初始化的DWORD:

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

然后发出WORD值80h,其后是未初始化的WORD值:

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

        DW      80H
        DW      ?

您可能已经替换了I_AM宏,备份了指针并将数据替换为:

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

作为Microsoft的编码要求,DOS开发人员可能总是通过I_AM宏导出指向BYTE,WORD,DWORD数据的标签.这完全是推测.他们可能认为通用的宏将允许他们更改导出此类数据的方法,而无需在无数地方更改代码.

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.

这篇关于使用$符号将值赋给上一行中存在的变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆