Using 这项技术 https://stackoverflow.com/q/17095324/995714, if (a >= '0' && a <= '9')
可以转化为
if ((unsigned char)(a - '0') <= ('9'-'0'))
这可以节省你的比较和跳转。现在只需一次比较就足够了
结果可能是这样的
SUBB A, #'0' ; A = a - '0'
CLR C
MOV R1, A ; R1 = a - '0'
MOV A, #9 ; A = '9' - '0'
SUBB A, R1 ; C = 1 if ('9' - '0') < (a - '0')
JC bad: ; jump when C != 0, i.e. !((a - '0') <= ('9' - '0'))
valid:
; do something
bad:
大多数现代编译器都知道如何优化此范围检查。我找不到 8051 在线编译器,也没有离线编译器,但 AVR 足够接近,可以提供演示。 AVR gcc 给出相同的输出原始状态和变换后的状态 https://gcc.godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(j:1,lang:c%2B%2B,source:'char+getMask(char+a)%0A%7B%0A++++return+(unsigned+char)(a+-+!'0!')+%3C%3D+(!'9!'-!'0!')%3B%0A%7D%0A%0Achar+getMask2(char+a)%0A%7B%0A++++return+a+%3E%3D+!'0!'+%26%26+a+%3C%3D+!'9!'%3B%0A%7D%0A'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:31.17831909738605,l:'4',m:100,n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:avrg464,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',trim:'1'),lang:c%2B%2B,libs:!(),options:'-O3',source:1),l:'5',n:'0',o:'AVR+gcc+4.6.4+(Editor+%231,+Compiler+%231)+C%2B%2B',t:'0')),header:(),k:35.48834756928063,l:'4',m:100,n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:clang_trunk,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',trim:'1'),lang:c%2B%2B,libs:!(),options:'-O3',source:1),l:'5',n:'0',o:'x86-64+clang+(trunk)+(Editor+%231,+Compiler+%232)+C%2B%2B',t:'0')),k:33.33333333333333,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4
mov r25,r24 ; input in r24
subi r25,lo8(-(-48)) ; r25 = input - '0'
ldi r24,lo8(1) ; r24 = 1
cpi r25,lo8(10) ; if r25 < 10
brlo .L2 ; jump to .L2
ldi r24,lo8(0) ; r24 = 0
.L2:
ret ; return value in r24
Update:
8051 的输出示例 https://gcc.godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(fontScale:14,j:1,lang:___c,selection:(endColumn:1,endLineNumber:10,positionColumn:1,positionLineNumber:10,selectionStartColumn:1,selectionStartLineNumber:10,startColumn:1,startLineNumber:10),source:'char+getMask(char+a)%0A%7B%0A++++return+(unsigned+char)(a+-+!'0!')+%3C%3D+(!'9!'-!'0!')%3B%0A%7D%0A%0Achar+getMask2(char+a)%0A%7B%0A++++return+a+%3E%3D+!'0!'+%26%26+a+%3C%3D+!'9!'%3B%0A%7D%0A'),l:'5',n:'0',o:'C+source+%231',t:'0')),k:32.13585891574134,l:'4',m:100,n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:sdcc400,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'1',trim:'1'),fontScale:14,j:1,lang:___c,libs:!(),options:'--opt-code-speed',selection:(endColumn:23,endLineNumber:17,positionColumn:23,positionLineNumber:17,selectionStartColumn:23,selectionStartLineNumber:17,startColumn:23,startLineNumber:17),source:1),l:'5',n:'0',o:'SDCC+4.0.0+(Editor+%231,+Compiler+%231)+C',t:'0')),header:(),k:67.86414108425865,l:'4',m:100,n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4来自SDCC
mov r7,dpl
cjne r7,#0x30,00110$
00110$:
jc 00103$
mov a,r7
add a,#0xff - 0x39
jnc 00104$
00103$:
mov r7,#0x00
sjmp 00105$
00104$:
mov r7,#0x01
00105$:
mov dpl,r7
ret