检查号码是否在 8051 的范围内

2024-03-01

我通过 UART 收到了一个字符,需要验证它是否是数字字符。

通常我会这样做

if (char >= '0' && char <= '9') { /* VALID */ }

然而,我必须这样做组装中.

我还没有找到任何比较指令(所以我假设没有)。

我怎样才能做到这一点?

    mov A, SBUF    ; load the number

    ; -- pseudocode --
    cmp A, #'0'    ; In AVR, I'd do it this way
    brlt fail      ; but I'm new to 8051
    cmp A, #'9'
    brge fail
    ; -- pseudocode --

    ; number is good

fail:

编辑:好的,这就是我现在所拥有的,但它不起作用

;======================================================
; check if r1 is number char -> r0 = 1 or 0
;------------------------------------------------------
fn_isnum:
    PUSH acc
    PUSH 1

    MOV r1,A

    SUBB A,#'0'
    JC isnum_bad

    MOV A,r1

    SUBB A,#'9'+1
    JC isnum_bad

    POP 1
    POP acc

    MOV r0,#1
    RET 

isnum_bad:

    POP 1
    POP acc

    MOV r0,#0
    RET
;======================================================

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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

检查号码是否在 8051 的范围内 的相关文章

  • 本机代码、机器代码和汇编代码有什么区别?

    我对 NET 语言上下文中的机器代码和本机代码感到困惑 它们之间有什么区别 它们是一样的吗 这些术语确实有点令人困惑 因为它们有时使用不一致 机器代码 这是定义最明确的一种 它是使用字节码指令的代码 您的处理器 执行实际工作的物理金属部件
  • RISC-V反汇编器与秒杀运行结果不符?

    我已经设置了一个 hello world 程序只是为了测试我的riscv32 unknown elf工具链 spike pk等等虽然我设法使用打印了 hello worldspike isa RV32 pk hello elf 我发现如果我
  • 全局变量在函数调用之间是否刷新?

    我正在编写嵌入式固件 发现有时很难决定何时需要易失性 当我有一个等待中断更改某个布尔标志的函数时 很明显该标志需要是易失性的 因为否则该函数将永远等待 因为编译器没有意识到该值可以通过打断 但是 当我有一个只检查第一行中的标志的短函数时 我
  • 使用 XCHG 解锁的自旋锁

    维基百科提供的使用 x86 XCHG 命令的自旋锁的示例实现是 Intel syntax locked The lock variable 1 locked 0 unlocked dd 0 spin lock mov eax 1 Set t
  • MS-DOS - 是否可以对 24 位图形进行编程?

    是否可以在 DOS 机器上以 24 位颜色深度进行编程 我知道 VGA 支持 8 位色深 但是有没有办法弄出 24 位色深 谷歌的研究没有发现任何结果 我正在 FreeDOS 而不是 MS DOS 上编程 如果这会影响答案的话 对的 这是可
  • 进入嵌入式[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 段错误...关于你好世界

    这段代码非常简单 但我在 x86 64 Linux 系统上遇到了段错误 这让我很烦恼 刚开始接触asm 请耐心等待 与 NASM 组装nasm f elf64 test asm 与连接ld o test test o SECTION tex
  • 简单内核无法在 GRUB 中启动

    我正在学习一些操作系统开发的知识OSDev org http osdev org 我有一个内核 我正在尝试使用 qemu 在 GRUB Legacy 0 97 中启动 但是 当我输入kernel 200 9 我收到消息 Multiboot
  • (nasm x86实模式)如何在引导加载的扇区中写入/读取字符串?

    我正在使用 NASM 为 x86 实模式编写一个最小操作系统 用于教育目的 我想使用 512 字节引导扇区加载包含操作系统其余部分的更大扇区 我已经成功创建了一个加载另一个扇区的引导扇区 但我似乎无法在加载的扇区中写入 读取字符串 这是我的
  • _addcarry_u64 和 _addcarryx_u64 与 MSVC 和 ICC

    MSVC 和 ICC 都支持内在函数 addcarry u64 and addcarryx u64 根据英特尔的内在指南 https software intel com sites landingpage IntrinsicsGuide
  • 内存映射图形输出

    我正在探索使用内存映射图形绘制像素和线条 我在 Windows 的 Textpad 中使用 TASM 当我单击 运行 时 整个屏幕变成蓝色 就是这样 没有绘制像素 model small stack data saveMode db xVa
  • 读取STM32 MCU SPI数据寄存器的值

    有很多类似的问题 但似乎没有一个问题完全相同 我正在将 STML4 MCU 连接到 6 轴传感器 LSM6DS3 我已经成功地在 I2C 中实现了所有内容 但想要 SPI 的额外速度 和 DMA 如果我能让这些第一步工作起来的话 因此 第一
  • 调用 printf 系统子例程在汇编代码中输出整数错误[重复]

    这个问题在这里已经有答案了 来回 在windows7控制台窗口中运行gcc s2 asm 然后生成一个exe文件 运行a exe 然后崩溃 为什么 s2 asm 代码由以下源代码生成 int m m 1 iprint m s2 asm请参考
  • 了解近调用指令编码

    通过反汇编一些二进制代码 我发现了近调用指令call 0x8ae编码为e8 97 08 00 00 查看指令集参考 我发现这些指令被编码为 call XX XX XX XX lt gt e8 XX XX XX XX being XX XX
  • 计算PE文件中入口点的文件偏移量

    In http en redinskala com finding the ep http en redinskala com finding the ep 有关于如何查找 exe 文件中入口点的文件偏移量的信息 在这里我可以读到 EP 文
  • 如何将 4 位十六进制转换为 7 位 ASCII?

    作业是通过编写一个可以在 4 位十六进制和 7 位 ASCII 之间转换的子程序来学习汇编编程 起初我不知道 但经过一些研究后 我可以做出努力并绘制流程图并制作程序 但它并不完全正确 所以我请求您的指导来帮助我解决这个问题 实际的作业文本是
  • Linux 在崩溃时自动重新启动应用程序 - 守护进程

    我有一个运行嵌入式 Linux 的系统 它的持续运行至关重要 基本上 它是一个与传感器通信并将数据中继到数据库和 Web 客户端的过程 如果发生崩溃 如何自动重启应用程序 此外 还有多个线程进行轮询 例如套接字和 uart 通信 如何确保没
  • 汇编器堆栈对齐(或使用 PUSH 更好的未对齐示例)

    首先我了解 或者我认为我了解 堆栈未对齐的问题 但我知道 就像定义一样 将 16 位值推入 32 位宽的堆栈可能会导致堆栈未对齐 但我不明白的是 这是怎么发生的 因为PUSH and POP检查段描述符处的 D 标志 1 递增 递减 32
  • 了解使用内存源操作数和 x87 fcomi / fcmov 的 GCC 内联汇编代码

    我正在阅读研究论文Privado 实用且安全的 DNN 推理 用于隐藏依赖于输入的分支 https arxiv org pdf 1810 00602 pdf 我试图理解该论文中的以下 GCC 汇编代码 float temp asm vola
  • .so 文件的 objdump?需要帮助来理解消息

    我正在开发一个与流相关的本机应用程序 我在我的 c 模块中遇到了一些问题 我收到的是来自 Logcat 的一些消息 这是 Logcat 消息 INFO DEBUG 28 Build fingerprint generic sdk gener

随机推荐