Ассемблер использует сегментный регистр - PullRequest
2 голосов
/ 01 октября 2019

Недавно я писал ассемблер, и программа, которую я написал, работала без проблем в DOSBox. Теперь мне нужно перенести ту же программу на реальный компьютер, используя DOS, но возникли некоторые проблемы.

Прежде всего, в DOSBox я компилировал с ML, но на реальном ПК, когда я набираю ML, он говорит:

Эту программу нельзя запустить в режиме DOS.

Поэтому я искал решение и обнаружил, что MASM может без проблем скомпилировать программу asm. К сожалению, программа, которую мне нужно портировать, сообщает о серьезных ошибках (только 1 тип) при компиляции.

ошибка A2061: неправильное использование регистра сегмента

Строки, в которых возникают эти проблемы, следующие

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

Также возникает та же проблемасо следующим кодом

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

До сих пор я пытался изменить этот PTR BYTE на BYTE PTR [ES:0017H], который выдал ту же ошибку

И на BYTE PTR ES:0017H, который успешно скомпилировал код,программа работала, но не работала правильно

Примечание: я не знаю, под какой архитектурой в настоящее время работаетИ, вероятно, не сможет получить физический доступ к машине, но если есть какой-то код, который я могу ввести, чтобы увидеть информацию на экране, я буду рад это сделать.

Код здесь, он естьздесь слишком долго, если мне нужно вставить его, тогда хорошо, но до тех пор https://pastecode.xyz/view/5f332efc

ПК говорит, что работает MSDOS 6

Ответы [ 2 ]

5 голосов
/ 01 октября 2019

(Обновление: Майкл Петч говорит, что некоторые MASM или MASM-совместимые ассемблеры допускают переопределение размера и сегмента внутри скобок. Но update2: не все, так что это, возможно, и было проблемойЭто как минимум более стандартный стиль, поэтому я бы рекомендовал всегда делать это.)


В обычном синтаксисе MASM вы хотите MOV [CARLOC], DX. В зависимости от того, как вы объявили carloc,вам все еще может понадобиться mov word ptr [CARLOC], dx, но DS: уже является сегментом по умолчанию.

Если вы хотите быть откровенным об этом, MOV word ptr ds:[CARLOC], dx, но я рекомендую опустить избыточные префиксы DS в источнике asm, потому что некоторыеассемблеры включают избыточный префикс 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 ptr и seg: переопределяют.

программа работала, но не работала правильно

Тогда либо в вашем коде есть другие ошибки, кроме синтаксических ошибок.

Или, если вы пытаетесь встроить это в исполняемый файл Windows: Конечно, не получается взять код, написанный для DOS (реальный режим, контролирующий всю машину) и создайте его как 32-разрядный или 64-разрядный исполняемый файл Windows (защищенный режим или 64-разрядный режим, кольцо 3 под ОС). Системный вызов ABI и даже API тоже совершенно разные: это разные ОС, а DOS API недоступен для исполняемых файлов Windows.

Майкл также предположил, что USE32 или другая директива может заставить MASM попытатьсяизбавить вас от себя и отказаться от использования сегментации в коде, который должен работать с плоской моделью памяти. Но если es:[17H] работает, то это, вероятно, не так.

4 голосов
/ 01 октября 2019

Неясно, на какую часть этого вопроса я должен ответить.

  • Первоначальная ошибка была связана с опечаткой. DS должно было быть DX
  • Используемая вами версия 5.10 MASM не поддерживает переопределения сегментов и размеров в квадратных скобках []. Код такой:

    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, которые мне известны, поэтому их необходимо удалить.


Вместо того, чтобы использовать EXE2BIN для преобразования из EXE в программу COM, вы можете изменить код для запускакак программа EXE. Удалите строки:

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