论坛公告:任何声称来自本站,告知您的密码已过期,或您需要验证您的详细信息、确认您的电子邮件、解决问题、进行威胁或要求付款的消息,都是垃圾邮件。 我们不会向用户发送任何此类消息。 如果您忘记了密码,可以使用密码重置链接获取新密码。 由于论坛上的垃圾邮件,所有帖子现在都需要版主批准。 **整个论坛 ** ➜ **编程 ** ➜ **通用 ** ➜ GPascal - a blast from the past GPascal - a blast from the past

距离上次发帖已超过 60 天。 此主题已关闭。 刷新页面 **页数:12 ** 发表者 | Nick Gammon 澳大利亚 (23,140 篇帖子) 简介 论坛管理员 ---|--- 日期 | 2011 年 6 月 25 日星期六 05:22 上午 (UTC) 由 Nick Gammon 于 2011 年 6 月 25 日星期六 11:33 下午 (UTC) 修改 消息 | | ![](https://www.gammon.com.au/images/GPascal Manual Front Cover.png) Commodore 64 手册封面 很多年前(1978 年),我开始使用微处理器,特别是 Motorola 6800 评估板。 后来我为它制作了一个“微型”Pascal 编译器,它完全存储在 EEPROM(可擦除 ROM)中。 后来它被转换为在 Apple II 上运行,然后又转换为在 Commodore 64 上运行。 来自墨尔本 Supercoders 的 Andrew Stuart 发表了一篇冗长的博客文章,其中描述(带有图像和 PDF 文件)了该项目的历史:http://www.supercoders.com.au/blog/nickgammongpascal.shtml 我设法挖掘出了关于 GPascal 的旧广告、“GPascal News”问题和杂志评论。 此外,非常幸运的是,找到了原始(Commodore 64 版本)编译器的源代码清单——以汇编语言编写。 ![](https://www.gammon.com.au/images/GPascal Source Snapshot.png) GPascal 源代码快照 完整源代码:http://www.gammon.com.au/GPascal/source/ Andrew 已将这些内容整理成一篇不错的文章,其中包含指向我发送给他的各种文章和图像的链接。 因此,如果您想了解我 30 年前使用计算机所做的事情,请阅读该文章! 您甚至可以获取编译器的副本和 Commodore 64 模拟器,然后尝试一下! 感谢 Andrew 激励我挖掘出所有这些档案资料。 再过 10 年,备份在 DVD 上的源代码可能会丢失。 ![](https://www.gammon.com.au/images/GPascal Apple Manual Version 2 Cover.png) Apple II 手册封面


https://github.com/fiendish/aardwolfclientpackage 顶部 发表者 | Nick Gammon 澳大利亚 (23,140 篇帖子) 简介 论坛管理员 ---|--- 日期 | 回复 #2 发表于 2011 年 6 月 26 日星期日 12:30 上午 (UTC) 由 Nick Gammon 于 2011 年 6 月 26 日星期日 06:07 上午 (UTC) 修改 消息 | | 谢谢,Fiendish! 为了解释源代码 (http://www.gammon.com.au/GPascal/source/),我们投入了大量工作来将其放入可用内存中。 我使用的一种方法是对错误消息之类的内容进行令牌化。

消息令牌 这是通过将高位设置为内部消息的字节,然后在显示时将其展开来完成的。 这是我提取的各种令牌的表,以十六进制表示,(来自 PAS1.ASM 第 1754+ 行):


B0 = P-codes
B1 = full
B2 = Constant
B3 = Identifier
B4 = expected
B5 = missing
B6 = Illegal
B7 = Incorrect
B8 = string
BA = compiler
BB = literal
BC = mismatch
BD = Error
BE = zero
BF = source file
C0 = of
C1 = or
C2 = to
C3 = ended at
C4 = Symbol
C6 = Stack
C7 = Instruction
C8 = table
C9 = Type
CA = list
CC = Number
CD = Line
CE = Gambit
CF = Games
D2 = Version 3.1 Ser# 5001
D3 = Copyright 1983
D4 = <C>ompile
D5 = <S>yntax
D6 = Written by Nick Gammon
D7 = <Q>uit
D8 = Range
D9 = Parameter
DA = <E>dit,
DB = <

错误消息 一旦展开令牌,错误消息(以十进制表示)为(来自 PAS1.ASM 第 1222+ 行):


 1: Memory full
 2: Constant expected
 3: = expected
 4: Identifier expected
 5: , or : expected
 6: bug
 7: *) expected
 8: Incorrect string
 9: . expected
10: ; expected
11: Undeclared Identifier
12: Illegal Identifier
13: := expected
14: literal string of zero length
15: compiler limits exceeded
16: THEN expected
17: ; or END expected
18: DO expected
19: Incorrect Symbol
20: bug
21: Use of procedure Identifier in expression
22: ) expected
23: Illegal factor
24: Type mismatch
25: BEGIN expected
26: "of " expected
27: Stack full
28: TO or DOWNTO expected
29: string literal too big
30: Number out of Range
31: ( expected
32: , expected
33: [ expected
34: ] expected
35: Parameters mismatched
36: Data Type not recognised
37: Symbol table full
38: Duplicate Identifier

源令牌 处理源时,它被转换为“令牌”(例如,数字、符号、保留字、标识符等)。 这使得在编译器中进行比较变得容易,因为您只需检查一个字节,而不必进行字符串比较。 源令牌(以十六进制表示)为(来自 PAS1.ASM 第 559+ 行):


81 = get
82 = const
83 = var
84 = array
85 = of
86 = procedure
87 = function
88 = begin
89 = end
8A = or
8B = div
8C = mod
8D = and
8E = shl
8F = shr
90 = not
91 = mem
92 = if
93 = then
94 = else
95 = case
96 = while
97 = do
98 = repeat
99 = until
9A = for
9B = to
9C = downto
9D = write
9E = read
9F = call
A1 = char
A2 = memc
A3 = cursor
A4 = xor
A5 = definesprite
A6 = plot
A7 = getkey
A8 = clear
A9 = address
AA = wait
AB = chr
AC = hex
AD = spritefreeze
AE = close
AF = put
DF = sprite
E0 = positionsprite
E1 = voice
E2 = graphics
E3 = sound
E4 = setclock
E5 = scroll
E6 = spritecollide
E7 = groundcollide
E8 = cursorx
E9 = cursory
EA = clock
EB = paddle
EC = spritex
ED = joystick
EE = spritey
EF = random
F0 = envelope
F1 = scrollx
F2 = scrolly
F3 = spritestatus
F4 = movesprite
F5 = stopsprite
F6 = startsprite
F7 = animatesprite
F8 = abs
F9 = invalid
FA = load
FB = save
FC = open
FD = freezestatus
FE = integer
FF = writeln

请注意,范围 0xB0 到 0xDB 中的“消息令牌”不在列表中。 这是为了输出例程可以将既是消息又是保留字的令牌转换回来,而不会发生冲突。 这使得前面帖子中的源代码片段更容易理解:


        1800 * REPEAT
        1801 *
9734: 20 02 90 1802 REPEAT  JSR PSHPCODE
9737: 20 49 80 1803 REP1   JSR GTOKEN
973A: 20 63 93 1804     JSR STMNT
973D: A5 16   1805     LDA TOKEN
973F: C9 3B   1806     CMP #';'
9741: F0 F4   1807     BEQ REP1
9743: A9 99   1808     LDA #$99
9745: A2 0A   1809     LDX #10
9747: 20 34 80 1810     JSR CHKTKN
974A: 20 40 90 1811     JSR GETEXPR
974D: 20 55 80 1812     JSR PULWRK
9750: 20 51 90 1813     JSR WRK:OPND
9753: A9 3D   1814     LDA #61
9755: 4C 88 80 1815     JMP GENRJMP

该代码调用 GTOKEN(获取令牌)并处理语句。 然后它检查我们是否得到了“;” 令牌,如果是,则获取另一个语句。 当用分号分隔的语句用完时,它会检查令牌 0x99(来自上表的“until”),如果它没有得到它,则输出错误 10,即来自上表的“; expected”)。

P-codes 这是 P 代码(伪机器代码)的含义:


Code Function  Description
---- ---------- ------------------------------------
00 = LIT   	Load constant
01 = DEF:SPRT	DEFINESPRITE
02 = NEG   	Negate (sp)
03 = HPLOT  	PLOT
04 = ADD   	Add (sp) to (sp - 1)
05 = TOHPLOT 	PLOT (not used)
06 = SUB   	Subtract (sp) from (sp - 1)
07 = GETKEY 	GETKEY
08 = MUL   	Multiply (sp) * (sp - 1)
09 = CLEAR  	CLEAR
0A = DIV   	Divide (sp - 1) / (sp)
0B = MOD   	Modulus (sp - 1) MOD (sp)
0C = ADRNN  	Address of integer
0D = ADRNC  	Address of character
0E = ADRAN  	Address of integer array
0F = ADRAC  	Address of character array
10 = EQL   	Test (sp - 1) == (sp)
11 = FINISHD 	Stop run (end program)
12 = NEQ   	Test (sp - 1) != (sp)
13 = CUR   	Cursor position
14 = LSS   	Test (sp - 1) < (sp)
15 = FREEZE:S 	SPRITEFREEZE
16 = GEQ   	Test (sp - 1) >= (sp)
17 = INH   	Input hex number
18 = GTR   	Test (sp - 1) > (sp)
19 = LEQ   	Test (sp - 1) <= (sp)
1A = ORR   	OR (sp - 1) | (sp)
1B = AND   	AND (sp - 1) & (sp)
1C = INP   	Input number
1D = INPC  	Input character
1E = OUT   	Output numbher
1F = OUTC  	Output character
20 = EOR   	Not (sp) (logical negate)
21 = OUH   	Output hex number
22 = SHL   	Shift left (sp) bits
23 = OUS   	Output string
24 = SHR   	Shift right (sp) bits
25 = INS   	Input string into array
26 = INC   	Increment (sp) by 1
27 = CLL   	Relative procedure/function call
28 = DEC   	Decrement (sp) by 1
29 = RTN   	Procedure/function return
2A = MOV   	Copy (sp) to (sp + 1)
2B = CLA   	Call absolute address
2C = LOD   	Load integer onto stack
2D = LODC  	Load character onto stack
2E = LDA   	Load absolute address integer
2F = LDAC  	Load absolute address character
30 = LDI   	Load integer indexed
31 = LDIC  	Load character indexed
32 = STO   	Store integer
33 = STOC  	Store character
34 = STA   	Store integer absolute address
35 = STAC  	Store character absolute address
36 = STI   	Store integer indexed
37 = STIC  	Store character indexed
38 = ABSCLL 	Absolute procedure/function call
39 = WAIT  	WAIT
3A = XOR   	XOR (sp - 1) ^ (sp)
3B = INT   	Increment stack pointer
3C = JMP   	Jump unconditionally
3D = JMZ   	Jump if (sp) zero
3E = JM1   	Jump if (sp) not zero
3F = SPRITE 	SPRITE
40 = MVE:SPRT 	POSITIONSPRITE
41 = VOICE  	VOICE
42 = GRAPHICS 	GRAPHICS
43 = SOUND  	SOUND
44 = SET:CLK 	SETCLOCK
45 = SCROLL 	SCROLL
46 = SP:COLL 	SPRITECOLLIDE
47 = BK:COLL 	GROUNDCOLLIDE
48 = CURSORX 	CURSORX
49 = CURSORY 	CURSORY
4A = CLOCK  	CLOCK
4B = PADDLE 	PADDLE
4C = SPRT:X 	SPRITEX
4D = JOY   	JOYSTICK
4E = SPRT:Y 	SPRITEY
4F = OSC3  	RANDOM
50 = VOICE3 	ENVELOPE
51 = SCROLLX 	SCROLLX
52 = SCROLLY 	SCROLLY
53 = SPT:STAT 	SPRITESTSTATUS
54 = MOV:SPT 	MOVESPRITE
55 = STOP:SPT 	STOPSPRITE
56 = STRT:SPT 	STARTSPRITE
57 = ANM:SPT 	ANMINATESPRITE
58 = ABS   	ABS (absolute value of (sp))
59 = INVALID 	INVALID
5A = LOADIT 	LOAD
5B = SAVEIT 	SAVE
5C = X:OPEN 	OPEN
5D = FR:STAT 	FREEZESTATUS
5E = OUTCR  	Output a carriage-return
5F = X:CLOSE 	CLOSE
60 = X:GET  	GET
61 = X:PUT  	PUT

提到 (sp) 的操作是指“堆栈顶部的值”,而 (sp - 1) 是从顶部开始的第二个值。 因此,例如,当您添加时,它会从堆栈中提取停止值,然后提取第二个顶部值,将它们相加,然后将结果推送到堆栈上。






顶部 发表者 | Nick Gammon 澳大利亚 (23,140 篇帖子) 简介 论坛管理员 ---|--- 日期 | 回复 #8 发表于 2012 年 2 月 22 日星期三 07:56 下午 (UTC) 消息 | | 太酷了,谢谢! 你从哪里获得汇编程序?

ca65 来自 CC65 6502 交叉编译器套件 (www.cc65.org; ftp://ftp.musoftware.de/pub/uz/cc65/) ... 有很多交叉汇编程序可供选择,但我被 ca65 吸引是因为它可以在我的 Unix 系统上轻松构建,并且它的原生语法与“Commodore”的方式非常相似(所有这些 "LABEL = " 业务是什么? :P :)。 它也是一个功能齐全的宏汇编程序,支持所有 6502 型号,并且你可以获得源代码——我个人使用它来添加对 Mitsubishi 740/50734 CPU 的支持(一个非常不错的 10MHz 嵌入式 6502 克隆..) 我从未想过使用 "BLT" 和 "BGE" 代替 BCC 和 BCS... 既然我已经设法构建了一个正常的 G-Pascal,我现在的项目是创建一个通用的 6502 版本,该版本将为 SYM-1、VIC20 和 50734 等机器构建; 制作一个可 ROM 的 GPascal 应该不会花费太多精力,所以我可以拥有一个启动到 PASCAL 而不是 BASIC 的系统 :D ... 我已经与某人交谈过,他正在努力将 IDE 分离为独立的解析器和解释器。

顶部 发表者 | Cjb 澳大利亚 (3 篇帖子) 简介 ---|--- 日期 | 回复 #10 发表于 2012 年 2 月 23 日星期四 05:40 下午 (UTC) 消息 | | Cjb 说: 既然我已经设法构建了一个正常的 G-Pascal,我现在的项目是创建一个通用的 6502 版本,该版本将为 SYM-1、VIC20 和 50734 等机器构建 [...] 这可能会吓到人们:http://kildall.apana.org.au/~cjb/vicpascal.png (只是一个粗略的概念验证尝试...)

顶部 发表者 | Nick Gammon 澳大利亚 (23,140 篇帖子) 简介 论坛管理员 ---|--- 日期 | 回复 #11 发表于 2012 年 2 月 23 日星期四 10:27 下午 (UTC) 消息 | | Cjb 说: ... 制作一个可 ROM 的 GPascal 应该不会花费太多精力,所以我可以拥有一个启动到 PASCAL 而不是 BASIC 的系统 :D ... 我已经与某人交谈过,他正在努力将 IDE 分离为独立的解析器和解释器。 它被设计为进入 ROM - 也就是说,程序空间内没有修改。 此外,独立的解释器应该很容易。 我过去常常出售/赠送 GPascal 解释器,它基本上只是代码的运行时部分(很容易获得,因为我认为这只是其中一个源文件)。


顶部 发表者 | [Nick Gammon](https://www.gammon.com.au/