汇编程序使用段寄存器 [英] Assembler use of segment register
问题描述
最近在写汇编,我写的程序在DOSBox下运行没有任何问题.现在我需要将相同的程序移植到使用 DOS 的真实计算机中,但出现了一些问题.
Recently I was writing assembly and the program I wrote ran without any problems under DOSBox. Now I need to port the same program into a real computer using DOS but some problems arised.
首先,在 DOSBox 下,我是用 ML 编译的,但是在真正的 PC 上,一旦我输入 ML,它就会说:
First of all, under DOSBox I was compiling with ML, but on the real PC once I type in ML it says:
此程序无法在 DOS 模式下运行.
This program cannot be run in DOS mode.
因此我一直在寻找解决方案,结果发现 MASM 可以毫无问题地编译 asm 程序.不幸的是,我需要移植的程序在编译时报告了严重错误(仅 1 种类型).
Therefore I was looking for a solution amd found out that MASM can compile asm program without problems. Unfortunately, the program which I need to port reports severe errors (1 type only) while compiling.
错误 A2061:段寄存器使用不当
error A2061: Improper use of segment register
出现这些问题的线路如下
The lines at which these problems arise are the following
...
CARLOC EQU $-2
...
MOV [WORD PTR DS:CARLOC],DX
...
同样的问题出现在下面的代码中
Also the same problem arises with the following code
...
MOV ES,CX
MOV AL, [BYTE PTR ES:0017H]
...
到目前为止,我已经尝试将此 BYTE PTR 更改为BYTE PTR [ES:0017H]
产生了同样的错误
So far I have tried to change this BYTE PTR into
BYTE PTR [ES:0017H]
which produced the same error
进入BYTE PTR ES:0017H
成功编译代码,程序运行但无法正常运行
And into
BYTE PTR ES:0017H
which compiled the code successfully, the program ran but did not work correctly
注意:我不知道当前在哪种架构下工作.并且可能无法物理访问机器,但如果我可以输入一些代码来查看屏幕上的信息,我会很乐意这样做.
Note: I do not know under which architecture am currently working. And probably won't be able to access the machine physically, but if there is some code that I can type in to see the information on screen I will be glad to do so.
代码在这里,如果我需要在这里粘贴它,那么这里太长了,但在那之前https://pastecode.xyz/view/5f332efc
Code is here, it is too long for here if i need to paste it here then ok, but until then https://pastecode.xyz/view/5f332efc
PC 说它运行 MSDOS 6
The PC says it runs MSDOS 6
推荐答案
不清楚我应该回答这个问题的哪一部分.
It is unclear what part of this question I should answer.
- 最初的错误与拼写错误有关.
DS
应该是DX
您使用的 MASM 5.10 版不支持方括号
[]
内的段和大小覆盖.代码如下:
- The original error was related to a typo.
DS
should have beenDX
Version 5.10 of MASM you use doesn't support the segment and size overrides inside the square brackets
[]
. Code like this:
MOV [WORD PTR DS:CARLOC],DX
需要写成:
MOV WORD PTR DS:[CARLOC],DX
您使用的 MASM 和 LINK 版本不会生成 COM 程序.您需要一个曾经与 DOS 一起提供的名为 EXE2BIN 的程序,它可以将某些类型的 EXE 程序转换为 COM.你必须像这样运行 EXE2BIN:
The version of MASM and LINK you are using doesn't generate COM programs. You need a program that used to come with DOS called EXE2BIN that could convert certain types of EXE programs to COM. You'd have to run EXE2BIN like this:
EXE2BIN progname.exe progname.com
MASM 版本不支持简化段指令 .MODEL
、.CODE
、.DATA
和 .STACK
我知道所以它们需要被删除.
The version of MASM doesn't support the simplified segment directives .MODEL
, .CODE
, .DATA
, and .STACK
that I am aware of so they need to be removed.
您可以修改代码以作为 EXE 程序运行,而不是使用 EXE2BIN 将 EXE 转换为 COM 程序.删除行:
Rather than use EXE2BIN to convert from an EXE to a COM program you can modify the code to run as an EXE program. Remove the lines:
.MODEL TINY
.CODE
.ORG 100h
使用以下内容创建 STACK
段:
Create a STACK
segment with something like:
STACK SEGMENT STACK
db 512 DUP(?)
STACK ENDS
EXE 程序需要在程序开始时尽早初始化 DS(以及 ES 如有必要).这与 CS=DS=ES=SS 并且不需要这样的初始化的 COM 程序不同.您将添加这些行来初始化 DS:
An EXE program needs to initialize the DS (and ES if necessary) early on at the program start. This is unlike COM programs where CS=DS=ES=SS and no such initialization is necessary. You'd add these lines to initialize DS:
MOV AX, CODE ; Initialize the Code Segment
MOV DS, AX
您将所有数据放在 CODE
段中,因此您需要将 DS 初始化为与 CODE
相同.
You placed all your data in the CODE
segment so you need to initialize DS to be the same as CODE
.
应该作为 EXE 运行的程序的最终版本是:
The final version of the program that should run as an EXE is:
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
这篇关于汇编程序使用段寄存器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!