【问题标题】:Assembler use of segment register汇编器使用段寄存器
【发布时间】:2020-01-30 14:49:09
【问题描述】:

最近我在写汇编,我写的程序在DOSBox下运行没有任何问题。现在我需要将相同的程序移植到使用 DOS 的真实计算机中,但出现了一些问题。

首先,我在 DOSBox 下使用 ML 进行编译,但在真正的 PC 上输入 ML 后会显示:

此程序无法在 DOS 模式下运行。

因此我一直在寻找解决方案,发现 MASM 可以毫无问题地编译 asm 程序。不幸的是,我需要移植的程序在编译时报告了严重错误(仅限 1 种类型)。

错误 A2061:段寄存器使用不当

出现这些问题的行如下

...
CARLOC EQU $-2
...
MOV [WORD PTR DS:CARLOC],DX
...

下面的代码也会出现同样的问题

...
MOV ES,CX
MOV AL, [BYTE PTR ES:0017H]
...

到目前为止,我已尝试将此 BYTE PTR 更改为 BYTE PTR [ES:0017H] 产生了同样的错误

然后进入 BYTE PTR ES:0017H 成功编译代码,程序运行但不能正常工作

注意:我不知道目前在哪种架构下工作。并且可能无法物理访问机器,但如果我可以输入一些代码来查看屏幕上的信息,我会很乐意这样做。

代码在这里,如果我需要将它粘贴在这里,那么这里太长了,但在那之前https://pastecode.xyz/view/5f332efc

PC 说它运行的是 MSDOS 6

【问题讨论】:

  • 当你说“[n]现在我需要使用 DOS 将同一个程序移植到一台真实的计算机中”时,你真的是说你想在 Windows 命令提示符应用程序中运行它吗?那么你就不能了,因为那个“DOS 提示符”并不是真正的 DOS,它仍然是 Windows,因此不会运行旧的 16 位应用程序。
  • 在电脑上它看起来像 CMD,但我正在运行 program.exe 并弹出第一个屏幕,但在我的解决方案之后程序冻结。
  • 您也不能只构建一个旧的 16 位 DOS 程序,假设它完全控制整个计算机,然后在 Windows 中运行它。您需要翻译代码才能处理受保护模式 Windows 的现代共享环境。
  • 为什么这个标签是emu8086?您最初使用的是 DOSBox,而不是 emu8086,现在您尝试在 32 位或 64 位可执行文件中本地运行它。这些都不是emu8086。
  • [word ptr ds:carloc], dx 产生错误,但 word ptr ds:[carloc], dx 没有,[carloc],dx 给出错误 a4057 操作数非法大小。

标签: assembly x86 masm addressing-mode memory-segmentation


【解决方案1】:

(更新:Michael Petch 说 一些 MASM 或 MASM 兼容的汇编器允许大小和段覆盖 inside 括号。但更新2:不是全部,所以这实际上可能是问题。它至少是更标准的风格,所以我建议总是这样做。)


在正常的 MASM 语法中,您需要 MOV [CARLOC], DX 根据您声明 carloc 的方式,您可能仍需要 mov word ptr [CARLOC], dx,但 DS: 已经是默认段。

如果您想明确说明,MOV word ptr ds:[CARLOC], dx 但我建议在 asm 源代码中省略冗余 DS 前缀,因为某些汇编程序在机器代码中包含冗余 DS 前缀! DS: 唯一不冗余的情况是与 ds:[bp] 或 ebp 或 ds:[esp] 一起使用,这意味着 SS 作为默认段。

对于 MASM,ds: 前缀也需要数字绝对地址。否则,这将被视为立即(无论括号如何),当然不能成为目的地。对于CARLOC equ $-2 之类的定义,您将需要ds:[CARLOC]。显然 MASM 不会在机器代码中添加无用的 ds 前缀,因此您不必担心该汇编程序。

如果您需要 CS/DS/ES/FS/GS/SS 前缀,标准语法是将其放在括号外:

MOV AL, ES:[0017H]

AL 目标意味着byte ptr 操作数大小,它也在括号之外。以反汇编程序输出为例。

进入编译成功的BYTE PTR ES:0017H

是的,这是有效的语法:括号在某些情况下是可选的(包括绝对地址或符号)。许多人建议总是在内存操作数周围使用括号(而不是 OFFSET symbol 立即数),以使人类读者更清楚。

如果您要使用括号,它们会在 size ptrseg: 覆盖之后。

程序运行但没有正常工作

那么你的代码除了语法错误之外还有其他错误。

或者如果你想把它构建成一个 Windows 可执行文件:当然,为 DOS 编写代码是行不通的(实模式,控制整个机器)并将其构建为 32 位或 64 位 Windows 可执行文件(保护模式或 64 位模式,操作系统下的 ring 3)。系统调用 ABI 甚至 API 也完全不同:它们是不同的操作系统,Windows 可执行文件无法使用 DOS API。

Michael 还建议,使用 USE32 或其他指令可能会使 MASM 试图将您从自己手中拯救出来,并拒绝在应该使用平面内存模型运行的代码中使用分段。但如果es:[17H] 有效,那可能就不是这样了。

【讨论】:

  • @MichaelPetch:啊,如果 MASM 具有不允许分段寻址的模式,那将是有意义的。我确实取消了我的答案的某些部分,留下了可能仍然相关的部分,即 OP 将 DOS 代码构建为原生 Windows 可执行文件的想法注定要失败。
  • 错字:MOV [CARLOC], DS - (我想你的意思是 DX)。
  • @500-InternalServerError:那个错字出现在原始问题中;我想我应该澄清或只是改变我的答案以匹配,因为这个问题不是关于你是否可以将段寄存器存储到内存中。 (你可以)。 OP 注意到他们自己的错字并在错误的答案建议 mov ax,ds 并存储 AX 后更新了他们的问题。
  • MASM 保留类型信息。如果您将 CARLOC 定义为 CARLOC $-2 MASM 不会考虑立即值,因为它是相对于标签的。在这种情况下,mov word ptr [CARLOC], dx 是合法的。但是,如果 CARLOC 解析为立即值,则 mov word ptr [CARLOC], dx 将与 immediate mode illegal 出错。在这种情况下,您实际上需要一个段覆盖,即使它是 DS(这可能是默认设置,但无论如何都是必需的)。这有效 mov word ptr DS:[CARLOC], dx 。一般情况下,mov word ptr DS:[CARLOC], dx 无论 CARLOC 是否立即有效。
  • @MichaelPetch:我想我记得一些情况,一些汇编程序需要一些导致冗余前缀的源语法,因此最有效的编码只能手动获得。感谢您确认 MASM 不是那样的。 (在 NASM 中,如果您不想要前缀,则永远不需要源代码中的 ds。所以这也绝对不是我所记得的。我实际上使用 NASM 和 GAS,并且会知道它们中的任何一个是否有可怕的强制浪费字节。)
【解决方案2】:

目前还不清楚我应该回答这个问题的哪一部分。

  • 原始错误与拼写错误有关。 DS 应该是 DX
  • 您使用的 MASM 5.10 版不支持方括号 [] 内的段和大小覆盖。像这样的代码:

    MOV     [WORD PTR DS:CARLOC],DX
    

    需要写成:

    MOV     WORD PTR DS:[CARLOC],DX
    
  • 您使用的 MASM 和 LINK 版本不会生成 COM 程序。您需要一个曾经随 DOS 一起提供的名为 EXE2BIN 的程序,它可以将某些类型的 EXE 程序转换为 COM。您必须像这样运行 EXE2BIN:

    EXE2BIN progname.exe progname.com
    
  • MASM 版本不支持我知道的简化段指令.MODEL.CODE.DATA.STACK,因此需要将它们删除。


您可以修改代码以作为 EXE 程序运行,而不是使用 EXE2BIN 将 EXE 转换为 COM 程序。删除行:

    .MODEL  TINY
    .CODE
    .ORG 100h

创建一个STACK 段,内容如下:

STACK SEGMENT STACK
    db 512 DUP(?)
STACK ENDS

EXE 程序需要在程序启动的早期初始化DS(如果需要,还需要初始化ES)。这与 COM 程序不同,其中 CS=DS=ES=SS 并且不需要这样的初始化。您将添加这些行来初始化 DS

    MOV     AX, CODE                ; Initialize the Code Segment
    MOV     DS, AX

您将所有数据放在CODE 段中,因此您需要将DS 初始化为与CODE 相同。

应该作为 EXE 运行的程序的最终版本是:

        TITLE   FormulaONE TURBO (256 byte game)


STACK SEGMENT STACK
    db 512 DUP(?)
STACK ENDS

CODE    SEGMENT BYTE PUBLIC 'CODE'
        ASSUME  CS:CODE,DS:CODE

;--------------------------------------------------------------------------
;                       ACTUAL PROGRAM BEGINS HERE
;--------------------------------------------------------------------------
START:
        MOV     AX, CODE                ; Initialize the Code Segment
        MOV     DS, AX
        MOV     BP,AX                   ; Reset score to 0 (=MOV BP,0)
        MOV     AH,06H                  ; Clear Screen and home the cursor
        CALL    SCROLL
;--------------------------------------------------------------------------
;                             MAIN GAME LOOP
;--------------------------------------------------------------------------
GAME:
        MOV     DX,1629H                ; Load CAR loc (LINE 16H, COL 29H)
CARLOC  EQU     $-2                     ; Self modifying code (CAR loc)

        CALL    MOVEIT                  ; Move cursor to DH,DL (car loc)
;--------------------------------------------------------------------------
;  Erase the car at old screen location
;--------------------------------------------------------------------------
        MOV     AL,20H                  ; Print 5 spaces
        PUSH    AX
        OUT     61H,AL                  ;   Turn off speaker (AL=00100000b)
        MOV     BL,70H                                                ;^^
        MOV     CL,5
        INT     10H

        MOV     AX,0E0AH                ; Move cursor to next line
        INT     10H

        POP     AX                      ; Print 5 more spaces
        INT     10H
;--------------------------------------------------------------------------
;  Move to new car location based on shift key status
;--------------------------------------------------------------------------
        MOV     CL,40H                  ; Get shift key status
        MOV     ES,CX                   ;   (=MOV ES,0040H)
        MOV     AL,BYTE PTR ES:[0017H]

        TEST    AL,1                    ; Right SHIFT key pressed?
        JZ      TRYLFT                  ;    No...Try left shift
        INC     DX                      ;    Yes..move car right 1 space
TRYLFT: TEST    AL,2                    ; Left SHIFT key pressed?
        JZ      KEYEND                  ;    No...done checking keys
        DEC     DX                      ;    Yes..move car left 1 space
KEYEND: MOV     WORD PTR DS:[CARLOC],DX ; Save new car location in memory
                                        ; (That is the self-modifying part)
        PUSH    DX                      ; Save car location on stack also
;--------------------------------------------------------------------------
;  Scroll the track down one line
;--------------------------------------------------------------------------
        MOV     AX,0701H                ; Scroll screen down 1 line
        CALL    SCROLL                  ;   this also sets BH=0 and BL=2
                                        ;   and homes the cursor

        MOV     CL,40                   ; Print left side of track
LMARGN  EQU     $-1                     ;   (Pointer to Left Margin)
        INT     10H

        MOV     DX,CX                   ; Find right side of track position
        ADD     DX,26                   ;   (Starting track width = 26)
TRKWID  EQU     $-1                     ;   (Pointer to Track Width)
        MOV     CL,80
        SUB     CX,DX
        CALL    MOVEIT                  ; Move cursor to right side of track
        INT     10H                     ; Print grass on right side of track
;--------------------------------------------------------------------------
;  Print the score in the lower right corner of the screen
;--------------------------------------------------------------------------
        MOV     DX,184EH                ; Screen loc 77,25 bottom right
        CALL    MOVEIT                  ; Move cursor to score location
        MOV     AX,BP                   ; Move Score to AX
        MOV     CL,8                    ; Shift score right 8 bits
        SAR     AX,CL                   ; (This makes it hard to get to Z!)
        ADD     AX,0E00H+65             ; MOV AH,0Eh & Convert score to A-Z
        INT     10H                     ; Print the score on the screen
;--------------------------------------------------------------------------
;  Check for a collision
;--------------------------------------------------------------------------
        POP     DX                      ; Restore car location from stack
        CALL    MOVEIT                  ; Move cursor under left front tire
        JNZ     PCAR                    ; Hit something? Yes... Print our
                                        ;   red car and exit the game
        PUSH    DX                      ; Save left tire position to stack
        ADD     DL,4                    ; Move cursor under right front tire
        CALL    MOVEIT                  ; Check to see if we hit something
        POP     DX                      ;    Restore our car position
        JNZ     PCAR                    ; Hit something? Yes... Print our
                                        ;   red car and exit the game
        PUSH    DX                      ; Save car position to stack
;--------------------------------------------------------------------------
;  No collision, go ahead and print our car (red)
;--------------------------------------------------------------------------
        CALL    PCAR                    ; Print our red car (CX=8)
;--------------------------------------------------------------------------
;  Slow game down by waiting for 3 vertical retraces and play sound effects
;--------------------------------------------------------------------------
        MOV     CL,3                    ; CX is delay invertical retraces
DELAY:  MOV     DX,03DAH                ; Video screen port
HERE:   IN      AL,DX                   ; Get current video status
        TEST    AL,8                    ; Check vertical retrace bit
        JNE     HERE                    ; Wait for 1 full vertical retrace
HERE2:                                  ; Turn on and off speaker...
        ADD     AL,BYTE PTR DS:[005DH]  ;   (Check command line for Q)
        DEC     AX                      ;   (which is for Quiet mode.)
        OUT     61H,AL                  ; while waiting for screen refresh
        IN      AL,DX
        TEST    AL,8
        JE      HERE2
        LOOP    DELAY                   ; Go wait for another until CX=0
;--------------------------------------------------------------------------
;  Keep track of our current score
;--------------------------------------------------------------------------
        INC     BP                      ; Count lines printed so far (score)
;--------------------------------------------------------------------------
;  Adjust size and placement of track
;--------------------------------------------------------------------------
        POP     DX                      ; Restore our car position fm stack
        MOV     AX,BP                   ; TEST AL=2 bytes, TEST BP=4 bytes

        TEST    AL,255                  ; Make track smaller each 256 lines
        JNZ     NOCHG                   ;   Go around if not time for change
        DEC     BYTE PTR DS:[TRKWID]    ;   Change width (Self-mod code!)
NOCHG:

        TEST    AL,9                    ; Make track wavy every so often
        JNZ     ENEMY                   ;  Time to go straight
        TEST    AL,128                  ;  Left or right?
        JZ      LEFT
        ADD     BYTE PTR DS:[LMARGN],2  ; -Move right 2 spaces (Self-mod!)
;        INC     DX                      ;    Make sure that enemy car
;        INC     DX                      ;      stays ON the track. (TAI)
LEFT:   DEC     BYTE PTR DS:[LMARGN]    ; -Move left 1 space   (Self-mod!)
;        DEC     DX                      ;    Make sure that enemy car
                                        ;      stays ON the track. (TAI)
;--------------------------------------------------------------------------
;  Draw an opponent car every 15 screen lines
;--------------------------------------------------------------------------
ENEMY:                                  ; Our car position is in DX register
        MOV     DH,0                    ; Make it into enemy position using
                                        ; True Artificial Intellegence (tm)
                                        ; ^    ^          ^  TAI :-)
        TEST    AL,15                   ; Every 15 lines print enemy car
        MOV     AX,OFFSET GAME          ;    Prepare for RET below
        PUSH    AX                      ;    Use RET as a jump to GAME loop
        JNZ     GOBACK                  ; Not time yet to print enemy car
;--------------------------------------------------------------------------
;                PRINT CAR AT SCREEN LOCATION "DX"
;
; On entry:  DH points to line, DL to column, CX to car graphic offset
;                                             (8 for red, 0 for blue car)
; On exit:  The proper car will be drawn.  Also, if we used CALL PCAR to
;           get here we will be returned into the program at that point.
;           If we used JNZ PCAR to get here we will be returned to the
;           DOS prompt (the game will end).
;--------------------------------------------------------------------------
PCAR:
        PUSH    BP                      ; Save our current score counter
        MOV     BP,OFFSET CAR2          ; Point to the car graphic
        ADD     BP,CX                   ;   Add offset to proper car
        SUB     BYTE PTR [BP+4],24      ; Print stripe on hood of car
        MOV     AX,1302H                ; Print the car to the screen
        PUSH    AX                      ;    AX may change in INT 10h call
        MOV     CL,5                    ;    Graphic is 5 characters wide
        PUSH    DS                      ;    It is located in the data seg
        POP     ES                      ;      but INT 10h needs that in ES
        INT     10H                     ; Print the first line of the car
        ADD     BYTE PTR [BP+4],24      ; Print cockpit and rear stripe
        POP     AX                      ; (=MOV AX,1302H)
        INC     DH                      ; Point to next line of the screen
        INT     10H                     ; Print the second line of the car
        POP     BP                      ; Restore current score counter
GOBACK: RET
CAR2:  
        DB      0DCH,70H,0DEH,71H,0D2H,1FH,0DDH,71H     ; Blue car graphic
        DB      0DCH,70H                                ;   Common tire
        DB      0DEH,74H,0D2H,4EH,0DDH,74H,0DCH,70H     ; Red car graphic
;--------------------------------------------------------------------------
;                     SCROLL SCREEN DOWN "AL" LINES
;                      (or if AH=6, clear screen)
;
; On entry:  AH must be 7, AL must be number of lines to scroll (1)
; On exit:   BH will be 0, BL will be 2 and we will fall through to
;            MOVEIT to home the cursor.             ^^^^^^^^^^^^
;--------------------------------------------------------------------------
SCROLL:
        MOV     BH,70H                  ; Use Black on Gray (road color)
        XOR     CX,CX                   ;   From UL corner (=MOV CX,0)
        MOV     DX,184FH                ;   to LR corner
        INT     10H
        MOV     BX,02                   ; Set BH to 0 and BL to 2 for use
                                        ;   when we return.
        XOR     DX,DX                   ; Now, home the cursor  (=MOV DX,0)
;--------------------------------------------------------------------------
;                  MOVE CURSOR TO SCREEN LOCATION DH,DL
;               AND SEE IF THERE IS A SPACE (TRACK) THERE
;
; On entry:  DH is screen line, DL is screen column
; On exit:   Z flag will be set/reset if there is a space character
;            under the cursor and AH will be 9 and AL will be 0DBh
;--------------------------------------------------------------------------
MOVEIT:
        MOV     AH,2                    ; Move cursor to DH,DL
        INT     10H
        MOV     AH,8                    ; Get the character under cursor
        INT     10H
        CMP     AL,20H                  ; Is it a space? (set Z flag)
        MOV     AX,09DBH                ; Set AH to 9 and AL to 0DBh for
        RET                             ;  use just after we return (don't
                                        ;  worry, Z flag will still be set)
CODE    ENDS

        END     START

Reply to "Stackoverflow question a2061"
Author
Title
Re: Stackoverflow question a2061
Language

Your paste - Paste your paste here
        TITLE   FormulaONE TURBO (256 byte game)
;==========================================================================
;      FormulaONE TURBO Copyright 1995, 1996, 1998 by David S. Issel
;                          all rights reserved.
;
;                      Written using Turbo Assembler
;
;                     To assemble use:  TASM F1-TURBO
;                         To link use:  TLINK /x/t F1-TURBO
;
; For Microsoft Macro Assembler 6.0 use:  ML /AT F1-TURBO.ASM
;
;
;               To run FormulaONE use:  F1-TURBO
;     To run FormulaONE without sound:  F1-TURBO Q
;
;  Use left and right shift keys to control your car                  __,        
;  at bottom of screen.  Try not to run into anything       _ _.--'-n_/          
;  for as long as you can.                                -(_)------(_)=         
;==========================================================================
        .MODEL  TINY
        .CODE
CODE    SEGMENT BYTE PUBLIC 'CODE'
        ASSUME  CS:CODE,DS:CODE
        ORG     0100H                   ; This will be a COM file
;--------------------------------------------------------------------------
;                       ACTUAL PROGRAM BEGINS HERE
;--------------------------------------------------------------------------
START:
        MOV     BP,AX                   ; Reset score to 0 (=MOV BP,0)
        MOV     AH,06H                  ; Clear Screen and home the cursor
        CALL    SCROLL
;--------------------------------------------------------------------------
;                             MAIN GAME LOOP
;--------------------------------------------------------------------------
GAME:
        MOV     DX,1629H                ; Load CAR loc (LINE 16H, COL 29H)
CARLOC  EQU     $-2                     ; Self modifying code (CAR loc)

        CALL    MOVEIT                  ; Move cursor to DH,DL (car loc)
;--------------------------------------------------------------------------
;  Erase the car at old screen location
;--------------------------------------------------------------------------
        MOV     AL,20H                  ; Print 5 spaces
        PUSH    AX
        OUT     61H,AL                  ;   Turn off speaker (AL=00100000b)
        MOV     BL,70H                                                ;^^
        MOV     CL,5
        INT     10H

        MOV     AX,0E0AH                ; Move cursor to next line
        INT     10H

        POP     AX                      ; Print 5 more spaces
        INT     10H
;--------------------------------------------------------------------------
;  Move to new car location based on shift key status
;--------------------------------------------------------------------------
        MOV     CL,40H                  ; Get shift key status
        MOV     ES,CX                   ;   (=MOV ES,0040H)
        MOV     AL,[BYTE PTR ES:0017H]

        TEST    AL,1                    ; Right SHIFT key pressed?
        JZ      TRYLFT                  ;    No...Try left shift
        INC     DX                      ;    Yes..move car right 1 space
TRYLFT: TEST    AL,2                    ; Left SHIFT key pressed?
        JZ      KEYEND                  ;    No...done checking keys
        DEC     DX                      ;    Yes..move car left 1 space
KEYEND: MOV     [WORD PTR DS:CARLOC],DX ; Save new car location in memory
                                        ; (That is the self-modifying part)
        PUSH    DX                      ; Save car location on stack also
;--------------------------------------------------------------------------
;  Scroll the track down one line
;--------------------------------------------------------------------------
        MOV     AX,0701H                ; Scroll screen down 1 line
        CALL    SCROLL                  ;   this also sets BH=0 and BL=2
                                        ;   and homes the cursor

        MOV     CL,40                   ; Print left side of track
LMARGN  EQU     $-1                     ;   (Pointer to Left Margin)
        INT     10H

        MOV     DX,CX                   ; Find right side of track position
        ADD     DX,26                   ;   (Starting track width = 26)
TRKWID  EQU     $-1                     ;   (Pointer to Track Width)
        MOV     CL,80
        SUB     CX,DX
        CALL    MOVEIT                  ; Move cursor to right side of track
        INT     10H                     ; Print grass on right side of track
;--------------------------------------------------------------------------
;  Print the score in the lower right corner of the screen
;--------------------------------------------------------------------------
        MOV     DX,184EH                ; Screen loc 77,25 bottom right
        CALL    MOVEIT                  ; Move cursor to score location
        MOV     AX,BP                   ; Move Score to AX
        MOV     CL,8                    ; Shift score right 8 bits
        SAR     AX,CL                   ; (This makes it hard to get to Z!)
        ADD     AX,0E00H+65             ; MOV AH,0Eh & Convert score to A-Z 
        INT     10H                     ; Print the score on the screen
;--------------------------------------------------------------------------
;  Check for a collision
;--------------------------------------------------------------------------
        POP     DX                      ; Restore car location from stack
        CALL    MOVEIT                  ; Move cursor under left front tire
        JNZ     PCAR                    ; Hit something? Yes... Print our
                                        ;   red car and exit the game
        PUSH    DX                      ; Save left tire position to stack
        ADD     DL,4                    ; Move cursor under right front tire
        CALL    MOVEIT                  ; Check to see if we hit something
        POP     DX                      ;    Restore our car position
        JNZ     PCAR                    ; Hit something? Yes... Print our
                                        ;   red car and exit the game
        PUSH    DX                      ; Save car position to stack
;--------------------------------------------------------------------------
;  No collision, go ahead and print our car (red)
;--------------------------------------------------------------------------
        CALL    PCAR                    ; Print our red car (CX=8)
;--------------------------------------------------------------------------
;  Slow game down by waiting for 3 vertical retraces and play sound effects
;--------------------------------------------------------------------------
        MOV     CL,3                    ; CX is delay invertical retraces
DELAY:  MOV     DX,03DAH                ; Video screen port
HERE:   IN      AL,DX                   ; Get current video status
        TEST    AL,8                    ; Check vertical retrace bit
        JNE     HERE                    ; Wait for 1 full vertical retrace
HERE2:                                  ; Turn on and off speaker...
        ADD     AL,[BYTE PTR DS:005DH]  ;   (Check command line for Q)
        DEC     AX                      ;   (which is for Quiet mode.)
        OUT     61H,AL                  ; while waiting for screen refresh
        IN      AL,DX
        TEST    AL,8
        JE      HERE2
        LOOP    DELAY                   ; Go wait for another until CX=0
;--------------------------------------------------------------------------
;  Keep track of our current score
;--------------------------------------------------------------------------
        INC     BP                      ; Count lines printed so far (score)
;--------------------------------------------------------------------------
;  Adjust size and placement of track
;--------------------------------------------------------------------------
        POP     DX                      ; Restore our car position fm stack
        MOV     AX,BP                   ; TEST AL=2 bytes, TEST BP=4 bytes

        TEST    AL,255                  ; Make track smaller each 256 lines
        JNZ     NOCHG                   ;   Go around if not time for change
        DEC     [BYTE PTR DS:TRKWID]    ;   Change width (Self-mod code!)
NOCHG:

        TEST    AL,9                    ; Make track wavy every so often
        JNZ     ENEMY                   ;  Time to go straight
        TEST    AL,128                  ;  Left or right?
        JZ      LEFT
        ADD     [BYTE PTR DS:LMARGN],2  ; -Move right 2 spaces (Self-mod!)
;        INC     DX                      ;    Make sure that enemy car
;        INC     DX                      ;      stays ON the track. (TAI)
LEFT:   DEC     [BYTE PTR DS:LMARGN]    ; -Move left 1 space   (Self-mod!)
;        DEC     DX                      ;    Make sure that enemy car
                                        ;      stays ON the track. (TAI)
;--------------------------------------------------------------------------
;  Draw an opponent car every 15 screen lines
;--------------------------------------------------------------------------
ENEMY:                                  ; Our car position is in DX register
        MOV     DH,0                    ; Make it into enemy position using
                                        ; True Artificial Intellegence (tm)
                                        ; ^    ^          ^  TAI :-)
        TEST    AL,15                   ; Every 15 lines print enemy car
        MOV     AX,OFFSET GAME          ;    Prepare for RET below
        PUSH    AX                      ;    Use RET as a jump to GAME loop
        JNZ     GOBACK                  ; Not time yet to print enemy car
;--------------------------------------------------------------------------
;                PRINT CAR AT SCREEN LOCATION "DX"
;
; On entry:  DH points to line, DL to column, CX to car graphic offset
;                                             (8 for red, 0 for blue car)
; On exit:  The proper car will be drawn.  Also, if we used CALL PCAR to
;           get here we will be returned into the program at that point.
;           If we used JNZ PCAR to get here we will be returned to the
;           DOS prompt (the game will end).
;--------------------------------------------------------------------------
PCAR:
        PUSH    BP                      ; Save our current score counter
        MOV     BP,OFFSET CAR2          ; Point to the car graphic
        ADD     BP,CX                   ;   Add offset to proper car
        SUB     BYTE PTR [BP+4],24      ; Print stripe on hood of car
        MOV     AX,1302H                ; Print the car to the screen
        PUSH    AX                      ;    AX may change in INT 10h call
        MOV     CL,5                    ;    Graphic is 5 characters wide
        PUSH    DS                      ;    It is located in the data seg
        POP     ES                      ;      but INT 10h needs that in ES
        INT     10H                     ; Print the first line of the car
        ADD     BYTE PTR [BP+4],24      ; Print cockpit and rear stripe
        POP     AX                      ; (=MOV AX,1302H)
        INC     DH                      ; Point to next line of the screen
        INT     10H                     ; Print the second line of the car
        POP     BP                      ; Restore current score counter
GOBACK: RET
CAR2:   
        DB      0DCH,70H,0DEH,71H,0D2H,1FH,0DDH,71H     ; Blue car graphic
        DB      0DCH,70H                                ;   Common tire
        DB      0DEH,74H,0D2H,4EH,0DDH,74H,0DCH,70H     ; Red car graphic
;--------------------------------------------------------------------------
;                     SCROLL SCREEN DOWN "AL" LINES
;                      (or if AH=6, clear screen)
;
; On entry:  AH must be 7, AL must be number of lines to scroll (1)
; On exit:   BH will be 0, BL will be 2 and we will fall through to
;            MOVEIT to home the cursor.             ^^^^^^^^^^^^
;--------------------------------------------------------------------------
SCROLL: 
        MOV     BH,70H                  ; Use Black on Gray (road color)
        XOR     CX,CX                   ;   From UL corner (=MOV CX,0)
        MOV     DX,184FH                ;   to LR corner
        INT     10H
        MOV     BX,02                   ; Set BH to 0 and BL to 2 for use
                                        ;   when we return.
        XOR     DX,DX                   ; Now, home the cursor  (=MOV DX,0)

MOVEIT: 
        MOV     AH,2                    ; Move cursor to DH,DL
        INT     10H
        MOV     AH,8                    ; Get the character under cursor
        INT     10H
        CMP     AL,20H                  ; Is it a space? (set Z flag)
        MOV     AX,09DBH                ; Set AH to 9 and AL to 0DBh for
        RET                             ;  use just after we return (don't
                                        ;  worry, Z flag will still be set)
CODE    ENDS

        END     START

【讨论】:

  • mov r/m16, Sreg 是可编码的。如果源寄存器是 DX 而不是 DS,MASM 会打印关于括号的不同错误消息吗?我很惊讶你说原来的错误与那个错字有关。
  • @PeterCordes :如果生成 16 位代码 mov [mem], ds 应该可以工作,但我相信如果代码在 USE32FLAT 段中,它可能会出错(我似乎回想一下 MASM 的某些版本的一个特性,它会产生这样的错误)
  • 8C modrm 无论前缀如何,在任何模式下都始终具有 16 位的内存操作数大小。 felixcloutier.com/x86/mov。只有当目的地是一个寄存器时,才会有任何混淆。 (尽管即使那样写一个 16 位 reg 并且不修改高字节也是不可能的:在 PPro 及更高版本上归零,在 Pentium、Quark 及更早版本上未定义。IIRC,具有寄存器目标,即使使用@,它也总是写入完整的寄存器宽度987654344@ 操作数大小前缀。虽然不是 100% 确定我没记错。)
猜你喜欢
  • 2016-11-11
  • 2011-06-21
  • 2021-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-02
相关资源
最近更新 更多