chu*_*ica 6 embedded pic bootloader
如何使用小代码空间减少十六进制ASCII字符转换的代码空间?
在嵌入式应用程序中,我有非常有限的空间(注1).我需要将字节从串行I/O转换为ASCII值'0'到'9'和'A'到'F'到通常的十六进制值0到15.此外,所有其他240种组合,包括' a'到'f',需要被检测到(作为错误).
图书馆的功能,例如scanf(), atoi(), strtol()是远太大而不能使用.
速度不是问题.代码大小是限制因素.
我现在的方法将256字节代码重新映射成256个代码,使得"0"到"9"和"A"到"Z"具有0到35的值.关于如何减少或不同方法的任何想法都是值得 赞赏的.
unsigned char ch = GetData(); // Fetch 1 byte of incoming data;
if (!(--ch & 64)) { // decrement, then if in the '0' to '9' area ...
ch = (ch + 7) & (~64); // move 0-9 next to A-Z codes
}
ch -= 54; // -= 'A' - 10 - 1
if (ch > 15) {
; // handle error
}
Run Code Online (Sandbox Code Playgroud)
注1:对于引导加载程序,PIC保护存储器中存在256条指令用于代码和常量数据(1字节数据需要1条指令).此代码需要大约10条指令.当前的ap需要重写并且只需要1条备用指令,即使是1条指令也是有价值的.我正在逐步完成它.还看了整体重建.
注:PIC16.我更喜欢用'C'编码,但必须做任何需要的事情.汇编代码如下.不需要快速回答.
if (!(--ch & 64)) {
002D:DECF 44,F 002E:BTFSC 44.6 002F:GOTO 034
ch = (ch + 7) & (~64);
0030:MOVLW 07 0031:ADDWF 44,W 0032:ANDLW BF 0033:MOVWF 44
}// endif
ch -= 54;
0034:MOVLW 36 0035:SUBWF 44,F
Run Code Online (Sandbox Code Playgroud)
[编辑最佳解决方案 ]
按照@GJ的建议优化现有解决方案.在C中,执行ch += 7; ch &= (~64);代替ch = (ch + 7) & (~64);保存的1指令.要通过装配不必重新加载保存的另一个ch内if().
PIC16系列是RISC MCPU,因此您可以尝试优化您的asm代码.这是你的c编译器asm代码...
decf ch, f
btfsc ch, 6
goto Skip
movlw 07
addwf ch, w
andlw 0xBF
movwf ch
Skip
movlw 0x36
subwf ch, f
Run Code Online (Sandbox Code Playgroud)
这是我对上层代码的优化......
decf ch, w //WREG = (--ch)
btfsc WREG, 6 //if (!(WREG & 64)) {
goto Skip
addlw 7 //WREG += 7
andlw 0xBF //WREG &= (~64)
Skip
addlw 0x100 - 0x36 //WREG -= 54;
movwf ch //ch = WREG
//
addlw 0x100 - 0x10 //if (WREG > 15) {
btfsc STATUS, 0 //Check carry
goto HandleError
Run Code Online (Sandbox Code Playgroud)
...所以只有7个操作码(少2个)没有范围错误检查,10个操作码带有范围错误检查!
编辑:尝试这个PIC16 C编译器优化功能,不确定是否工作...
WREG = (--ch);
if (!(WREG & 64)) { // decrement, then if in the '0' to '9' area ...
WREG = (WREG + 7) & (~64); // move 0-9 next to A-Z codes
}
ch = WREG - 54; // -= 'A' - 10 - 1
if (WREG > 15) {
; // handle error
}
Run Code Online (Sandbox Code Playgroud)
编辑II:增加的版本与旧的PIC16 MCPU兼容,不是用XLP技术制造的,但代码大小是一个操作码更长.
decf ch, f ;//ch = (--ch)
movf ch, w ;//WREG = ch
btfsc ch, 6 ;//if (!(ch & 64)) {
goto Skip
addlw 7 ;//WREG += 7
andlw 0xBF ;//WREG &= (~64)
Skip
addlw 0x100 - 0x36 ;//WREG -= 54;
movwf ch ;//ch = WREG
//
addlw 0x100 - 0x10 ;//if (WREG > 15) {
btfsc STATUS, 0 ;//Check carry
goto HandleError
Run Code Online (Sandbox Code Playgroud)
编辑III:解释
'D Kruegers'解决方案也非常好,但需要进行一些修改......
这段代码..
if (((ch += 0xC6) & 0x80) || !((ch += 0xF9) & 0x80)) {
ch += 0x0A;
}
Run Code Online (Sandbox Code Playgroud)
......我们可以翻译成......
if (((ch -= ('0' + 10)) < 0) || ((ch -= ('A' - '0' - 10)) >= 0)) {
ch += 10;
}
Run Code Online (Sandbox Code Playgroud)
之后我们可以优化整体...
call GetData
//if GetData return result in WREG then you do not need to store in ch and read it again!
// movwf ch
// movf ch, w
addlw 0x100 - '0' - 10 //if (((WREG -= ('0' + 10)) < 0) || ((WREG -= ('A' - '0' - 10)) >= 0)) {
btfss STATUS, 0
goto DoAddx
addlw 0x100 - ('A' - '0' - 10)
btfsc STATUS, 0
DoAddx
addlw 10 //WREG += 10; }
movwf ch //ch = WREG;
addlw 0x100 - 0x10 //if (WREG > 15) {
btfsc STATUS, 0 //Check carry
goto HandleError
Run Code Online (Sandbox Code Playgroud)