TASM 减一寻址
TASM addressing off by one
我目前正在为大学实施 Snake,为此我们必须使用 TASM。
我的主要游戏数据是这样布局的(使用C语法):
struct GameLine {
uint8_t direction_bits[10]; // 2 bits per entry, the first entry is invalid since valid x positions start at one
uint8_t collision_bits[5]; // 1 bit per entry, the first entry is again invalid but has to stay zero
uint8_t aux; // padding such that GameLine is 16 bytes big, also used to store other information at times.
};
struct GameData {
struct GameLine lines[23];
} PHYSICAL_GAME_DATA;
问题是每帧写入方向位会覆盖大 x 位置的读取冲突位(38 是最大位置,但它发生得更早)。我说“读取冲突位”是因为我无法验证 physical_game_data
实际驻留的位置,因为我不知道如何指示汇编器 (tasm
) and/or 链接器 (tlink
) and/or 调试器 (td
) 向我展示。
我的代码中的声明是:
physical_game_data DB 368 DUP (0)
; ..., Some `EQU`s for `aux` data I'm using to store other information
game_data EQU (offset physical_game_data) - 16 ; Since 1 <= y <= 23, this allows addressing a line via `game_data + (y << 4)`
这里我最担心的 mov
是这两个:
; This one is for writing a new direction
mov BYTE [ds:game_data + bx], dh
; ...
; This one is for reading a collision bit to check if the player lost
mov dl, [ds:game_data + 10 + si]
查看 td
中的内容会产生以下结果:
mov [bx+05AF],dh
; ...
mov dl,[si+05B8]
但是 0x05AF 和 0x05B8 之间的区别是 9,而不是 10。我目前通过在源代码中添加 11 来“修复”这个问题,这意味着错误不会发生,但我宁愿妥善解决这个问题。
我假设这是我对 TASM 或 x86/x86-16 程序集的一些误解,但我不知道那个误解到底是什么。
这是一个展示此问题的完整文件:
.model tiny
.286
.data
datastart:
physical_game_data DB 368 DUP (0)
; ..., Some `EQU`s for `aux` data I'm using to store other information
game_data EQU (offset physical_game_data) - 16 ; Since 1 <= y <= 23, this allows addressing a line via `game_data + (y << 4)`
.code
ORG 100h
start:
mov ax, seg datastart
mov ds, ax
; This one is for writing a new direction
mov BYTE [ds:game_data + bx], dh
; ...
; This one is for reading a collision bit to check if the player lost
mov dl, [ds:game_data + 10 + si]
; Exit
mov ax, 4C00h
int 21h
end start
使用tasm MRE.ASM
、tlink MRE.OBJ
编译,使用td MRE.EXE
使用td
打开,反编译代码为:
mov ax,48AF
mov ds,ax
mov [bx+0103],dh
mov dl,[si+010C]
mov ax,4C00
int 21
其中 0x10C - 0x103 是 9。
如果有兴趣,我是运行Dosbox下的这段代码
谢谢!
您的问题是 BYTE 关键字。在 MASM 模式中,BYTE 关键字的计算结果为 BYTE 的大小:1。这被添加到方括号 []
中的表达式中,因为方括号在 MASM 模式中主要充当加法运算符。您需要改写 BYTE PTR [ds:game_data + bx]
,尽管您的下一条指令表明您也可以将其省略。
我目前正在为大学实施 Snake,为此我们必须使用 TASM。
我的主要游戏数据是这样布局的(使用C语法):
struct GameLine {
uint8_t direction_bits[10]; // 2 bits per entry, the first entry is invalid since valid x positions start at one
uint8_t collision_bits[5]; // 1 bit per entry, the first entry is again invalid but has to stay zero
uint8_t aux; // padding such that GameLine is 16 bytes big, also used to store other information at times.
};
struct GameData {
struct GameLine lines[23];
} PHYSICAL_GAME_DATA;
问题是每帧写入方向位会覆盖大 x 位置的读取冲突位(38 是最大位置,但它发生得更早)。我说“读取冲突位”是因为我无法验证 physical_game_data
实际驻留的位置,因为我不知道如何指示汇编器 (tasm
) and/or 链接器 (tlink
) and/or 调试器 (td
) 向我展示。
我的代码中的声明是:
physical_game_data DB 368 DUP (0)
; ..., Some `EQU`s for `aux` data I'm using to store other information
game_data EQU (offset physical_game_data) - 16 ; Since 1 <= y <= 23, this allows addressing a line via `game_data + (y << 4)`
这里我最担心的 mov
是这两个:
; This one is for writing a new direction
mov BYTE [ds:game_data + bx], dh
; ...
; This one is for reading a collision bit to check if the player lost
mov dl, [ds:game_data + 10 + si]
查看 td
中的内容会产生以下结果:
mov [bx+05AF],dh
; ...
mov dl,[si+05B8]
但是 0x05AF 和 0x05B8 之间的区别是 9,而不是 10。我目前通过在源代码中添加 11 来“修复”这个问题,这意味着错误不会发生,但我宁愿妥善解决这个问题。
我假设这是我对 TASM 或 x86/x86-16 程序集的一些误解,但我不知道那个误解到底是什么。
这是一个展示此问题的完整文件:
.model tiny
.286
.data
datastart:
physical_game_data DB 368 DUP (0)
; ..., Some `EQU`s for `aux` data I'm using to store other information
game_data EQU (offset physical_game_data) - 16 ; Since 1 <= y <= 23, this allows addressing a line via `game_data + (y << 4)`
.code
ORG 100h
start:
mov ax, seg datastart
mov ds, ax
; This one is for writing a new direction
mov BYTE [ds:game_data + bx], dh
; ...
; This one is for reading a collision bit to check if the player lost
mov dl, [ds:game_data + 10 + si]
; Exit
mov ax, 4C00h
int 21h
end start
使用tasm MRE.ASM
、tlink MRE.OBJ
编译,使用td MRE.EXE
使用td
打开,反编译代码为:
mov ax,48AF
mov ds,ax
mov [bx+0103],dh
mov dl,[si+010C]
mov ax,4C00
int 21
其中 0x10C - 0x103 是 9。
如果有兴趣,我是运行Dosbox下的这段代码
谢谢!
您的问题是 BYTE 关键字。在 MASM 模式中,BYTE 关键字的计算结果为 BYTE 的大小:1。这被添加到方括号 []
中的表达式中,因为方括号在 MASM 模式中主要充当加法运算符。您需要改写 BYTE PTR [ds:game_data + bx]
,尽管您的下一条指令表明您也可以将其省略。