使用 $ 符号为上一行中存在的变量赋值

2023-12-09

我正在尝试了解 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?


The 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

看来开发者有意使用I_AM宏使符号(指向字节、字和双字)可供其他模块公开访问。问题是I_AM宏不允许您指定数据,它会使其未初始化为?。为了解决这个问题,开发人员决定支持程序计数器以覆盖未初始化的数据,以便他们可以用 80h 的 WORD 值和第二个未初始化的 WORD 来填充它(?).

不允许您使用带有 a 的表达式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 的编码要求。这完全是推测。他们可能觉得一个通用的宏可以让他们改变导出此类数据的方法,而无需在无数地方更改代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 $ 符号为上一行中存在的变量赋值 的相关文章

  • 如何在汇编程序中使用 C 库?

    我想知道如何用汇编语言编写文本编辑器 但现代操作系统需要 C 库 特别是对于它们的窗口系统 我找到了这个page http pengu1n is programmer com posts 8304 html 这对我有很大帮助 但我想知道是否
  • 将 C 转换为 MIPS - 嵌套数组

    我正在学习 MIPS 汇编语言 在书中看到了这个例子 对我来说这似乎是不正确的 如果是的话 这将不是我在本书中发现的第一个错误 变量f and g被分配寄存器 s0 and s1分别是数组的基地址A and B are s6 and s7分
  • 现代 x86 硬件不能将单个字节存储到内存中吗?

    说到 C 的并发内存模型 Stroustrup 的C 编程语言 第 4 版 第 1 节 41 2 1 说 就像大多数现代硬件一样 机器无法加载或存储小于单词的任何内容 然而 我的 x86 处理器已经有几年的历史了 它可以并且确实存储小于单词
  • g++ 内联汇编括号中不匹配

    g 向我抱怨以下代码中缺少括号 1 2 3 v v v asm volatile inb 1 0 a result Nd portnumber 1 2 3 正如您所看到的 括号是匹配
  • elf .rel.text 部分中 R_386_32/R_386_PC32 的含义

    为了理解重定位的概念 我编写了一个简单的 chk c 程序 如下所示 1 include
  • MASM 字符串反转

    好吧 我正在讨论这个问题 可能是一个非常复杂的解决方案 但这是我脑海中浮现的第一件事 我需要编写一个汇编语言程序来反转 源 字符串 而不使用 目标 字符串 临时变量 这是我的尝试 INCLUDE Irvine32 inc data sour
  • 如何调试 iOS 应用程序在启动时崩溃,仅在程序集文件中设置断点

    我遇到了当前正在开发的应用程序的问题 问题是应用程序在启动时在后台运行一段时间后崩溃 并且仅在这种情况下 在应用程序被杀死时启动应用程序不会导致调试器或手机崩溃 无论是否进行调试 在后台启动应用程序大约 5 10 分钟都不会导致崩溃 在后台
  • DASM 汇编器中的 ASCII 到 C64 屏幕代码

    我正在通过 C64 模拟器学习 6502 micro 的汇编 目前正在尝试将字符串输出到屏幕 这是我的代码 processor 6502 org 1000 ldx 00 using x register as column counter
  • 装配中出现奇怪的字符?

    我写了以下代码 386 model small stack 100h data text db Paper 0 code start lea dx text mov ah 9h int 21h mov ah 4ch int 21h end
  • 为什么这个 C++ 包装类没有被内联掉?

    EDIT 我的构建系统出了问题 我还在弄清楚到底是什么 但是gcc产生了奇怪的结果 尽管它是 cpp文件 但是一旦我使用了g 然后它按预期工作 对于我一直遇到麻烦的事情来说 这是一个非常精简的测试用例 其中使用数字包装类 我认为会内联 使我
  • 编写 AMD64 SysV 程序集时使用哪些寄存器作为临时寄存器?

    我正在使用实现一个功能cpuid根据 AMD64 SysV ABI 进行组装 我需要在函数本身中使用 2 个临时寄存器 第一个用于累积返回值 第二个用作计数器 我的功能目前如下所示 zero argument function some c
  • 破坏/分解函数的函数

    我以前有过 here https stackoverflow com questions 4920610 c class function in assembly 已经表明 C 函数不容易用汇编表示 现在我有兴趣以一种或另一种方式阅读它们
  • C++ 中的 CPUID 实现

    我想知道这里是否有人有一些可以从任何托管 net 语言引用的 C CPUID 实现的好示例 另外 如果情况并非如此 我是否应该注意 X86 和 X64 之间的某些实现差异 我想使用 CPUID 来获取运行我的软件的机器上的信息 崩溃报告等
  • 如何在汇编语言中换行打印多个字符串

    我试图在汇编中的不同行上打印多个字符串 但使用我的代码 它只打印最后一个字符串 我对汇编语言非常陌生 所以请耐心等待 section text global start start mov edx len mov edx len1 mov
  • 尝试使用 x86 程序集 GNU GAS 在数组索引处赋值时出现错误

    我在用x86GNU 与 GCC 的程序集 并尝试实现相当于以下内容的程序集c c int x 10 x 0 5 但是 当我尝试运行 使用命令 a out 我的汇编代码如下 第一次编译后gcc filename s 错误Segmentatio
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • 汇编8086监听键盘中断

    我有与此完全相同的问题 边画边听键盘 https stackoverflow com questions 13970325 8086 listen to keyboard while drawing 但第一个答案 接受的答案 只听键盘一次
  • 寄存器寻址模式与直接寻址模式

    我在试卷中遇到过这个问题 它指出 哪种给定的寻址模式更快 为什么 寄存器寻址方式 直接寻址方式 现在根据我的说法 寄存器寻址模式应该更快 因为寄存器是计算机中最快的存储位置 这是正确答案吗 请帮忙 谢谢 两种寻址模式之间的区别是 地址的来源
  • 为什么我的空循环在 Intel Skylake CPU 上作为函数调用时运行速度是原来的两倍?

    我正在运行一些测试来比较 C 和 Java 并遇到了一些有趣的事情 在 main 调用的函数中 而不是在 main 本身中 运行具有优化级别 1 O1 的完全相同的基准代码 导致性能大约翻倍 我正在打印 test t 的大小 以毫无疑问地验
  • 弹出 x86 堆栈以访问函数 arg 时出现分段错误

    我正在尝试链接 x86 程序集和 C 我的C程序 extern int plus 10 int include

随机推荐

  • 如何使用 R8 在堆栈跟踪中保留原始行号?

    我正在尝试找出如何使用 R8 保留原始行号 使用当前的AndroidStudio制作应用程序并使用R8对其进行混淆 甚至上传mapping txt将文件上传到 Google Play Console 后 用户的堆栈跟踪在某些情况下是无用的
  • T-SQL 中的编辑距离

    我对 T SQL 计算 Levenshtein 距离的算法感兴趣 我在 TSQL 中实现了标准 Levenshtein 编辑距离函数 并进行了多项优化 与我所知的其他版本相比 速度有所提高 如果两个字符串的开头有共同的字符 共享前缀 结尾有
  • 无法使最大宽度与 Bootstrap 下拉菜单一起使用

    我有一个 Bootstrap 下拉菜单 在某些情况下 菜单项可能非常大 所以我需要设置一个max width 另外 我不希望菜单项被剪切 所以我必须使用white space normal也 问题是我的max width被完全忽略 如果我设
  • File.Copy 与手动 FileStream.Write 复制文件

    我的问题是关于文件复制性能 我们有一个媒体管理系统 需要将文件系统上的大量文件移动到不同位置 包括同一网络上的 Windows 共享 FTP 站点 AmazonS3 等 当我们都在一个 Windows 网络上时 我们可以使用System I
  • Delphi 编译器指令反向求值参数

    这个使用 Math pas 中的 IFThen 函数的 delphi 两行代码给我留下了深刻的印象 但是 它首先评估 DB ReturnFieldI 这很不幸 因为我需要调用 DB first 来获取第一条记录 DB RunQuery se
  • 如何对只读实例属性进行输入验证?

    发布了一个非常相似的问题here 但没有公认的答案 没有代码示例 而且我不太喜欢按照那里提供的唯一一个答案所建议的使用外部库的想法 以下代码允许定义只读实例属性 class Point def init self x y self x x
  • 有充分的理由编写我自己的 daemonize 函数而不是使用 daemon(3) 吗?

    网上有很多守护进程的示例实现 我看到的大多数不使用 daemon 3 函数在后台运行程序 这只是一个品味 无知的问题 还是有充分的理由编写我自己的守护函数 使用 daemon 3 有什么具体的缺点吗 是不是没有安全感 daemon 函数历史
  • 核心数据中的可转换属性无法导出/与 iCloud 同步

    我在用NSPersistentCloudKitContainer 所有数据均在 iCloud 中同步 卸载应用程序后 它会正确同步 但是 需要对敏感数据进行加密 我将密码属性设置为可转换 因此在本地工作得很好 但是当我删除该应用程序时 再次
  • 在 Origin 中将破幂律实现为拟合函数

    再会 我正在尝试使用 origin OriginLab 中的函数生成器来创建一个新函数来适应破碎的幂律 http en wikipedia org wiki Power law Broken power law 所以 我想我已经把实际的功能
  • 从 GUI 类 PyQt4 以外的类更改进度条的值

    我有一个由 Qt 设计器创建的 GUI 类 其中有一个进度条 还有另一个类 其中完成所有数字运算 在此期间我希望进度条定期更新 我认为我会这样做的方式是在其他班级中做类似的事情 gui progressbar setValue some 但
  • 在没有 xts 对象的情况下在 PortfolioAnalytics 中创建有效前沿

    有没有办法在 PortfolioAnalytics 包中创建有效前沿而不指定资产回报的 xts 对象 相反 我想提供预期回报向量和协方差矩阵 有两种方法 首先 您可以提供一个包含矩阵的列表 其结构如下所示 然后调用 Optimize por
  • 在 Mac 应用程序中的保存对话框中包含 iCloud

    我已经实施了iCloud支持我的 Mac 基于文档的应用程序 NSDocument子类可以处理本地存储上打开的保存文件 并且iCloud 但是 我可以将我的文件上传到iCloud只需将其拖动到 打开新文件 面板上即可 当应用程序提示用户保存
  • 如何区分 EOF 字符和实际的文件结尾?

    When reading a file I understand the last character provided is an EOF Now what happens when I have an EOF character in
  • Mojarra 2.0.3 中复合组件所需属性抛出异常

    我一直在使用 JSF 2 0 复合组件 但我对其中的 require 属性有点困惑composite attribute标签的意思是做 文档指出 如果页面作者必须提供此属性的值 则必需的属性为 true 我将其解释为必须为所有具有复合属性的
  • apollo-android可以用作java客户端吗?

    我正在开发一个需要与 Github GraphQl API 通信的 Spring Boot 应用程序 apollo android 可以用于此目的吗 由于所有可用的稀缺文档以及示例项目都是用 android 编写的 所以我不确定 维护者在这
  • 获取距离直线最近的点

    我想要一个直接的 C 函数来获取距离线段 AB 最近的点 从点 P 抽象函数可能如下所示 我已经搜索过了 但没有找到可用的 由我 解决方案 public Point getClosestPointFromLine Point A Point
  • Pandas:根据子字符串删除重复项[重复]

    这个问题在这里已经有答案了 我有以下两列 来自 Pandas DataFrame antecedents consequents apple orange orange apple apple water apple pineapple w
  • 检查 PDO 是否存在的最佳方法是什么[重复]

    这个问题在这里已经有答案了 有人告诉我 rowCount 不安全 所以我想在这里问它 我有 2 个例子 想知道检查某些东西是否存在的最安全和最好的方法是什么 sql SELECT count FROM users WHERE usernam
  • 更改 XML 序列化中元素的类型

    我在 XML 序列化方面遇到了巨大的问题 我有两个类 都需要可序列化 在继承的类中 我想更改序列化行为 以便将字符串属性序列化为复杂类型 public class Animal XmlElement ElementName NAME pub
  • 使用 $ 符号为上一行中存在的变量赋值

    我正在尝试了解 MS DOS v2 0源代码 特别是其中的一些代码MSDATA ASM 该代码最初是使用 35 多年历史的 MASM 汇编器 未商用的版本 进行汇编的 我感兴趣的代码就在开头附近 SUBTTL Initialized dat