我正在尝试为 ATmega16 编写一些代码。我一直在 FreeBSD 12.2-RELEASE 下使用 avra(版本 1.4.2)。我的代码段中有以下内容:
helloStr: .db "Hello World\0"
我的理解是字符的字节应该是连续的。但是,当我查看生成的目标文件时,我看到以下内容(我正在使用命令 avra main.asm 组装代码):
00000190: 0000 3600 0000 2a65 4800 0039 0000 002b ..6...*eH..9...+
000001a0: 6c6c 0000 3900 0000 2c20 6f00 0039 0000 ll..9..., o..9..
000001b0: 002d 6f57 0000 3900 0000 2e6c 7200 0039 .-oW..9....lr..9
000001c0: 0000 002f 5c64 0000 3900 0000 3000 3000 .../\d..9...0.0.
000001d0: 0039 0000 0031 e2fa 0000 3d00 0000 32e0 .9...1....=...2.
注意右边的字符不是连续的。我正在查看 avra 正在生成的 .obj 文件。当我尝试运行代码时,它似乎确认我的暂停字符字节没有连续存储,因为我在显示器上看到的大部分都是垃圾,带有一些正确的字符,但间隔太远。我认为我的显示例程没有任何问题(例如,如果我删除循环代码并使用 ldi r16 将字符直接存储在 r16 中,则 LCD 显示代码将正确显示字符,'H'。):
WRITE_TO_LCD:
push r16
push r17
START_WRITE_TO_LCD:
lpm r16, Z+
ldi r17, 0b0
cp r16, r17 ; Have we hit the null byte?
breq END_WRITE_TO_LCD
;; Output character command.
out PortA, r16
ldi r16, low(registerSelect) ; Set RS control signal
out PortC, r16
;; Set E and RS control siginals.
ldi r16, (low(registerSelect) | low(enable))
out PortC, r16
ldi r16, low(registerSelect) ; Clear E control signal
out PortC, r16
jmp START_WRITE_TO_LCD
END_WRITE_TO_LCD:
pop r17
pop r16
ret
我正在加载 Z:
ldi r31, low(helloStr)
ldi r30, high(helloStr)
在我打电话给 WRITE_TO_LCD 之前。我不确定低到 r31 和高到 r30 是否正确,但我也尝试过另一种方法。我还读到内存是使用 2 字节字寻址的,所以我应该使用 2*helloStr。我也试过这样做。也许我刚才提到的这些细节在我在这里显示的代码中是不正确的,但我已经尝试了所有的排列,我认为这不是问题(正如 LCD 上的输出和我可以在十六进制编辑器中看到。)
我还在中断向量之后定义了 helloStr 。如果我将它放在中断向量之前,我似乎在 .obj 文件中看不到它的任何证据,并且当我实际运行它时 LCD 上的输出是不同的。我认为这与中断向量需要成为内存中的第一件事或类似的东西有关。但是我会认为它仍然会出现在代码中,并且中断的处理会被搞砸。
无论如何,我真正感兴趣的事情是在 Flash 中获得一个连续的字符串,这样我就可以遍历它。
如果有人知道我可能做错了什么,我将非常感谢您的意见。