CALL指令错误跳转至0x0而非0x800h的编译器问题求助
解决CALL 0x800指令被错误编译为CALL 0x0的问题
问题背景
当前程序中所有调用地址$800h(即0x800)的CALL指令,被编译器错误生成为CALL 0x0,导致程序执行时进入死循环。相关反汇编代码片段如下:
主程序反汇编片段
**DISASSEMBLED CODE:** 0164 0739 ADDWF 0x39, W 531: addwf Trigger777,0 ;to get proper patch table 0165 0733 ADDWF 0x33, W 532: addwf countUp,0 ;to get proper patch table 0166 00BC MOVWF 0x3C 533: movwf EnvPointer 0167 2109 CALL 0x109 534: Call read 0168 210C CALL 0x10C 535: CALL TinyDelay;NEW 0169 3008 MOVLW 0x8 536: movlw HIGH ATKDecayTable 016A 008A MOVWF PCLATH 537: movwf PCLATH 016B 083C MOVF 0x3C, W 538: MOVF EnvPointer,0 016C 1003 BCF STATUS, 0x0 539: BCF STATUS,0 ;CLEAR CARRY FLAG 540: # **016D 2000 CALL 0x0 541: call ATKDecayTable ;GET RegData FROM TABLE** 542: 016E 00B0 MOVWF 0x30 543: MOVWF RegData 016F 0086 MOVWF PORTB 544: movwf PORTB
目标表反汇编片段
2398: org 0x800 2399: 2400: 2401: ATKDecayTable ;EnvTest PARAM CHANGE 24-39 DECIMAL INCLUSIVE 2402: 0800 0782 ADDWF PCL, F 2403: ADDWF PCL ,1 2404: ;00h 0801 3400 RETLW 0x0 2405: RETLW 0x00 ; ENV_FreqLow equ 0xB 0802 3401 RETLW 0x1 2406: RETLW 0x01 ; ENV_FreqHgh equ 0xC
问题分析
从代码逻辑看,程序已经通过MOVLW 0x8和MOVWF PCLATH设置了高地址位为0x8,理论上CALL 0x0应跳转到0x800(PCLATH<<8 | 0x0),但实际执行进入死循环,说明编译器生成的指令或地址映射存在错误,导致跳转未指向ATKDecayTable。
EPROM烧录器修改步骤
- 定位错误指令地址:找到反汇编中错误的
CALL 0x0指令所在的EPROM地址,这里是0x016D。 - 确认正确机器码:
- 针对PIC架构,
CALL指令为双字节:0x20+ 目标地址低8位。目标0x800的低8位是0x00,结合已设置的PCLATH=0x8,正确机器码应为0x20 0x00;若实际跳转错误,需检查PCLATH的设置指令是否正常执行。 - 若编译器未正确处理跨页调用,可根据单片机型号替换为对应长跳转指令的机器码。
- 针对PIC架构,
- 修改EPROM镜像:
- 打开烧录器软件,加载当前程序镜像。
- 导航到地址
0x016D,确认当前机器码为0x20 0x00,若需调整则替换为正确指令字节。 - 同时检查地址
0x0169(MOVLW 0x8,机器码0x30 0x08)和0x016A(MOVWF PCLATH,机器码0x00 0x8A),确保这两条设置PCLATH的指令未被错误编译。
- 验证修复效果:重新烧录EPROM到单片机,运行程序确认死循环问题解决,
ATKDecayTable调用正常。
源代码层面替代修复
- 检查
ATKDecayTable的org 0x800声明是否正确,确保编译器能正确识别该标签地址。 - 手动编写汇编指令序列,强制确保
PCLATH设置后再执行调用:movlw HIGH ATKDecayTable movwf PCLATH call LOW ATKDecayTable
内容的提问来源于stack exchange,提问作者Dan Laskowski
相关产品推荐
相关产品推荐

