段寄存器的汇编程序使用
Assembler use of segment register
最近在写汇编,我写的程序运行在DOSBox下没有任何问题。现在我需要将相同的程序移植到使用 DOS 的真实计算机中,但出现了一些问题。
首先,在 DOSBox 下,我使用 ML 进行编译,但在真正的 PC 上,一旦我输入 ML,它会说:
This program cannot be run in DOS mode.
因此我一直在寻找解决方案,发现 MASM 可以毫无问题地编译 asm 程序。不幸的是,我需要移植的程序在编译时报告了严重的错误(只有一种类型)。
error A2061: Improper use of segment register
出现这些问题的行如下
...
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
(更新:Michael Petch 说 some MASM 或 MASM 兼容的汇编程序允许大小和段覆盖 inside 括号。但是 update2:不是全部,所以这实际上可能是问题所在。它至少是更标准的样式,所以我建议始终这样做。)
在正常的 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
操作数大小,它也在括号之外。例如,查看反汇编程序输出。
And into BYTE PTR ES:0017H
which compiled the code successfully,
是的,这是有效的语法:括号在某些情况下是可选的(包括绝对地址或符号)。许多人建议 总是 在内存操作数周围使用括号(而不是 OFFSET symbol
立即数)以使人类读者更清楚。
如果您要使用方括号,它们会在 size ptr
和 seg:
覆盖之后。
the program ran but did not work correctly
那么你的代码除了语法错误之外还有其他错误。
或者,如果您试图将其构建到 Windows 可执行文件中:当然,采用为 DOS[=62= 编写的代码是行不通的](实模式,控制整台机器)并将其构建为32位或64位Windows可执行文件(保护模式或64位模式,ring 3 在 OS 下)。系统调用 ABI 甚至 API 也完全不同:它们是不同的 OSes 并且 DOS API 不适用于 Windows可执行文件。
Michael 还建议,USE32 或其他指令可能会使 MASM 尝试将您从自己身上拯救出来,并拒绝在本应 运行 具有平面内存模型的代码中使用分段。但是,如果 es:[17H]
有效,那么可能就不是这样了。
不清楚我应该回答这个问题的哪一部分。
- 最初的错误与打字错误有关。
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,如有必要)。这与 CS=DS=ES=SS 并且不需要此类初始化的 COM 程序不同。您将添加这些行来初始化 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 "Whosebug question a2061"
Author
Title
Re: Whosebug 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
最近在写汇编,我写的程序运行在DOSBox下没有任何问题。现在我需要将相同的程序移植到使用 DOS 的真实计算机中,但出现了一些问题。
首先,在 DOSBox 下,我使用 ML 进行编译,但在真正的 PC 上,一旦我输入 ML,它会说:
This program cannot be run in DOS mode.
因此我一直在寻找解决方案,发现 MASM 可以毫无问题地编译 asm 程序。不幸的是,我需要移植的程序在编译时报告了严重的错误(只有一种类型)。
error A2061: Improper use of segment register
出现这些问题的行如下
...
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
(更新:Michael Petch 说 some MASM 或 MASM 兼容的汇编程序允许大小和段覆盖 inside 括号。但是 update2:不是全部,所以这实际上可能是问题所在。它至少是更标准的样式,所以我建议始终这样做。)
在正常的 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
操作数大小,它也在括号之外。例如,查看反汇编程序输出。
And into
BYTE PTR ES:0017H
which compiled the code successfully,
是的,这是有效的语法:括号在某些情况下是可选的(包括绝对地址或符号)。许多人建议 总是 在内存操作数周围使用括号(而不是 OFFSET symbol
立即数)以使人类读者更清楚。
如果您要使用方括号,它们会在 size ptr
和 seg:
覆盖之后。
the program ran but did not work correctly
那么你的代码除了语法错误之外还有其他错误。
或者,如果您试图将其构建到 Windows 可执行文件中:当然,采用为 DOS[=62= 编写的代码是行不通的](实模式,控制整台机器)并将其构建为32位或64位Windows可执行文件(保护模式或64位模式,ring 3 在 OS 下)。系统调用 ABI 甚至 API 也完全不同:它们是不同的 OSes 并且 DOS API 不适用于 Windows可执行文件。
Michael 还建议,USE32 或其他指令可能会使 MASM 尝试将您从自己身上拯救出来,并拒绝在本应 运行 具有平面内存模型的代码中使用分段。但是,如果 es:[17H]
有效,那么可能就不是这样了。
不清楚我应该回答这个问题的哪一部分。
- 最初的错误与打字错误有关。
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,如有必要)。这与 CS=DS=ES=SS 并且不需要此类初始化的 COM 程序不同。您将添加这些行来初始化 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 "Whosebug question a2061"
Author
Title
Re: Whosebug 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