65.9K
CodeProject 正在变化。 阅读更多。
Home

Z80 汇编器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (15投票s)

2020 年 10 月 3 日

CPOL

3分钟阅读

viewsIcon

21152

downloadIcon

484

早在 1984 年,我就想编写一个 Z80 汇编器。当时,这意味着要用 Z80 机器码来编写,但由于现代技术的便利,我现在用 C++ 完成了它。

实现

我再次使用自己的词法分析和解析库来实现汇编器。一个典型的规则看起来像这样

g_map[grules.push("opcode", "LD '(' HL ')' ',' integer")] = [](data& data)
{
    data._memory.push_back(0x36);
    data.push_byte();
};

汇编器有两种运行模式。如果只提供源文件,则源文件将连同操作码一起转储回 std::cout。但是,如果提供了模板 .sna 文件和目标路径名,则会创建一个包含汇编代码的新 .sna 文件。

例如,如果您的源代码如下所示

  ORG 23296

  LD IX, 16384
  LD DE, 6912
  CALL 1366
  RET

那么默认输出看起来像这样

23296   221  33   0  64     LD IX, 16384
23300    17   0  27         LD DE, 6912
23303   205  86   5         CALL 1366
23306   201                 RET

示例汇编源文件

这是一个用于 Sinclair ZX Spectrum 的简单填充例程

  ORG 23298

  LD BC, (23296)
  CALL GetScreenPos
Line:
  CALL FillLine
  CALL GetNextLine
  LD A, (HL)
  OR A
  JR Z, Line
  RET
FillLine:
  PUSH HL
  CALL FillLeft
  POP HL
  PUSH HL
  INC HL
  CALL FillRight
  POP HL
  RET
FillLeft:
  LD A, (HL)
  OR A
  JR NZ, MaskLeft
  LD (HL), 255
  DEC HL
  JR FillLeft
MaskLeft:
  LD B, 0
  PUSH AF
LeftAgain:
  BIT 0, A
  JR NZ, EndFillLeft
  SLA B
  SET 0, B
  SRA A
  JR LeftAgain
EndFillLeft:
  POP AF
  OR B
  LD (HL), A
  RET
FillRight:
  LD A, (HL)
  OR A
  JR NZ, MaskRight
  LD (HL), 255
  INC HL
  JR FillRight
MaskRight:
  LD B, 0
  PUSH AF
RightAgain:
  BIT 7, A
  JR NZ, EndFillRight
  SRA B
  SET 7, B
  SLA A
  JR RightAgain
EndFillRight:
  POP AF
  OR B
  LD (HL), A
  RET
GetScreenPos:
  LD A, C
  AND %00111000
  RLCA
  RLCA
  OR B
  LD L, A
  LD A, C
  AND %00000111
  LD H, A
  LD A, C
  AND %11000000
  RRCA
  RRCA
  RRCA
  OR H
  OR &40
  LD H, A
  RET
; Takes HL as Screen Address
GetNextLine:
  INC H
  LD A, H
  AND 7
  RET NZ
  LD A, L
  ADD A, 32
  LD L, A
  RET C
  LD A, H
  SUB 8
  LD H, A
  RET

这是 Sinclair Basic 中的驱动程序

10 CIRCLE 125,100,50
14 POKE 23296,25
16 POKE 23297,15
20 RANDOMIZE USR 23298

生成结果如下

Using the Code

用法: z80_assembler <路径名> [<源 .sna> <目标 .sna>]

这是一个正在进行中的工作,所以请务必报告任何问题。

历史

  • 2020 年 10 月 3 日:发布
  • 2020 年 10 月 3 日:添加了 Z80 源代码示例
  • 2020 年 10 月 3 日:现在默认情况下转储带有操作码的 mnemonic
  • 2020 年 10 月 4 日:现在支持整数以及 CALL 和 JP 的标签
  • 2020 年 10 月 4 日:修复了规则 integer: Hex;
  • 2020 年 10 月 4 日:修复了 wlabel()
  • 2020 年 10 月 5 日:无法识别的反汇编操作码现在显示为 db nnn
  • 2020 年 10 月 5 日:如果标签与操作码位于同一行,则正确计算地址
  • 2020 年 10 月 15 日:现在检查是否超出内存末尾,并简化了代码。
  • 2020 年 10 月 16 日:修复了 RST 指令。
  • 2020 年 10 月 20 日:添加了缺少的指令。
  • 2020 年 10 月 21 日:添加了基本表达式支持,并修复了大量无效索引。
  • 2020 年 10 月 21 日:添加了 '*', '/', '|' 和 '&' 支持,并修复了更多索引。
  • 2020 年 10 月 21 日:添加了 gcc Makefile。
  • 2020 年 10 月 22 日:添加了未公开的指令。
  • 2020 年 10 月 24 日:现在允许在 EQU、DB 和 DW 表达式中使用括号。
  • 2020 年 1 月 10 日:修复了 DS/DEFS 以使其正常工作。 获取了 JSW 的反汇编,并成功地汇编并运行了它。
  • 2020 年 1 月 16 日:添加了对所有指令的测试,并修复了许多指令的反汇编。
  • 2020 年 1 月 17 日:修复了 DS 指令,在反汇编器中添加了缺少的空格,添加了另一个测试文件。
  • 2020 年 1 月 19 日:将助记符验证添加到测试代码。
  • 2020 年 2 月 2 日:汇编器现在记录字节范围的类型(代码、db、dw、ds),以辅助反汇编。
  • 2021 年 2 月 3 日:始终在 dump() 中设置偏移量。
  • 2021 年 7 月 3 日:更新了 parsertl
  • 2021 年 8 月 30 日:引入了 program struct。
  • 2021 年 9 月 1 日:修复了 disassem.cpp 中的求值顺序,并修复了 clang 警告。
  • 2021 年 9 月 2 日:修复了使用 clang 和 -Wall 构建时的警告。
  • 2022 年 3 月 15 日:添加了用于十六进制、十进制和相对跳转(偏移量、绝对)的开关。
  • 2022 年 3 月 16 日:现在将 base 和 relative 传递给 main.cpp 中的 parse() 和 dump()。
  • 2022 年 4 月 14 日:修复了命令行处理,并在十六进制模式下将“h”添加到 realtive 跳转中。
  • 2022 年 4 月 17 日:反汇编器现在为 db 每行输出最多 4 个字节,为 dw 每行输出 2 个字。
  • 2022 年 5 月 6 日:索引寄存器采用带符号的位移(在反汇编器中)。
  • 2022 年 8 月 11 日:+/- 修复了 sbto_string()
  • 2023 年 1 月 21 日:更新为使用最新版本的 parsertl
  • 2023 年 1 月 31 日:更新为使用最新版本的 parsertl
  • 2023 年 9 月 11 日:更新到最新的 lexertlparsertl。 将 lexertl 路径添加到 Makefile 和 .vcxproj。
  • 2024 年 2 月 15 日:更新为使用 lexertl17parsertl17
  • 2024 年 4 月 20 日:添加了 $ (程序计数器)支持。
  • 2024 年 5 月 24 日:添加了 .skool 文件支持。
© . All rights reserved.