使用 PIC16 汇编中的宏创建高级 IF ELSE ENDIF

发布于 2024-10-27 14:22:45 字数 402 浏览 7 评论 0原文

我尝试在 PIC16F84 的汇编中模拟 IF() .... ELIF .... ENDIF ,但它似乎不适用于多种用途。我尝试在两个地方使用类似的东西,但它给出了一些标签重复的错误。宏中的参数是否也应该在标签中替换? (真实姓名中的姓名:)

_f macro name
  btfsc EQUAL,0
  goto true_name
  goto false_name
  true_name:
endm

_lse macro name
  goto next_name
  false_name:
endm

_ndif macro name
  goto next_name
  next_name:
endm

;; usage example
_f label1
  ...
_lse label1
  ...
_ndif 

I tried to simulate IF() .... ELIF .... ENDIF in assembly for PIC16F84, but it doesn't seem to work for more than one usage. I tried to use something like this in two places, but it gives some error that a label is duplicated. Shouldn't the parameter from the macro be replaced in the labels too? (name in true_name:)

_f macro name
  btfsc EQUAL,0
  goto true_name
  goto false_name
  true_name:
endm

_lse macro name
  goto next_name
  false_name:
endm

_ndif macro name
  goto next_name
  next_name:
endm

;; usage example
_f label1
  ...
_lse label1
  ...
_ndif 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

零度℉ 2024-11-03 14:22:45

我认为一个人可以做得更好一点。下面是一些可以嵌套五层的 if-else-endif 宏。不幸的是,我无法像我希望的那样定义 if1、if2..,因为汇编器不接受“#ifndef if#v(lvl)”,因此宏将嵌套级别限制为 5深的。这些符号计算给定嵌套级别的 If 数量,以便可以附加唯一的标签。包括一个无意义的例子。

xIf macro L,R,A

#ifndef lvl
lvl=0
#endif
lvl=lvl+1

#ifndef if1
if1=0
if2=0
if3=0
if4=0
if5=0
#endif

if#v(lvl)=if#v(lvl)+1

    movf    R,A
    xorlw L
    bnz   _false_#v(lvl)_#v(if#v(lvl))
    endm 

xElse macro
    bra  _end_#v(lvl)_#v(if#v(lvl))
_false_#v(lvl)_#v(if#v(lvl)):
    endm

xEndIf macro
_end_#v(lvl)_#v(if#v(lvl)):
lvl=lvl-1
    endm

    xIf 123,STATUS,A
        clrf    TMR3H,A
        xIf 75,STATUS,A
            clrf    TMR3H,A
        xElse
            setf    TMR3L,A
        xEndIf
    xElse
        setf    TMR3H,A
    xEndIf

I think one can do a bit better. Here's some if-else-endif macros that can be nested five deep. Unfortunately, I was not able to make the definitions of if1, if2.. as nice as I would like since the assembler does not accept "#ifndef if#v(lvl)" so the macros as they stand limit the nesting level to five deep. These symbols count the number of Ifs at a given nesting level so unique labels can be attached. A nonsense example is included.

xIf macro L,R,A

#ifndef lvl
lvl=0
#endif
lvl=lvl+1

#ifndef if1
if1=0
if2=0
if3=0
if4=0
if5=0
#endif

if#v(lvl)=if#v(lvl)+1

    movf    R,A
    xorlw L
    bnz   _false_#v(lvl)_#v(if#v(lvl))
    endm 

xElse macro
    bra  _end_#v(lvl)_#v(if#v(lvl))
_false_#v(lvl)_#v(if#v(lvl)):
    endm

xEndIf macro
_end_#v(lvl)_#v(if#v(lvl)):
lvl=lvl-1
    endm

    xIf 123,STATUS,A
        clrf    TMR3H,A
        xIf 75,STATUS,A
            clrf    TMR3H,A
        xElse
            setf    TMR3L,A
        xEndIf
    xElse
        setf    TMR3H,A
    xEndIf
追我者格杀勿论 2024-11-03 14:22:45

不要使用从一个宏到另一个宏的跳转,这是危险的

无需使用独特的标签。
在 MPLAB 下有两种方法可以做到这一点:

1) 使用 LOCAL 伪指令的情况

_f macro name
 LOCAL true_name
      btfsc   EQUAL,0
      goto    true_name
      goto    name  
true_name:
endm

2) 使用 $ 作为当前存储器地址指针的情况。

_f macro name
      btfsc   EQUAL,0
      goto    $+1
      goto    name
endm

Do not use jumps from one macro to another, it is dangerous.

There is no need to use unique labels.
Two ways haw to do this under MPLAB:

1)Case with LOCAL directive

_f macro name
 LOCAL true_name
      btfsc   EQUAL,0
      goto    true_name
      goto    name  
true_name:
endm

2)Case with $ as current memory address pointer.

_f macro name
      btfsc   EQUAL,0
      goto    $+1
      goto    name
endm
悲歌长辞 2024-11-03 14:22:45

我用 MPLAB 变量解决了这个问题,下面是一个测试寄存器和文字之间相等性的示例:

_f_equal_literal macro register,literal,name
    movlw literal
    subwf register,0
    btfss STATUS,2 ;bit indicating result is zero
    goto _false#v(name)
    endm

_lse macro name
    goto _next#v(name)
_false#v(name):
    endm

_ndif macro name
_next#v(name):
    endm

请注意,我没有使用 goto _true#v(name)_true#v (name): 标签,您只需确定是否需要 btfss 还是 btfsc

您可以使用单个 _lse_ndif 宏,并为 _f 语句使用多个宏。

GJ 的解决方案没有 next 标签,因此 true 分支将执行 false 分支。


您需要为每个 if-else-endif 构造定义一个变量。
如果变量名描述了 if-else-endif 的用途,它甚至可能有用。

示例:

变量testing_something=123

_f_equal_literal some_register,some_value,testing_something
                ...       

_lse testing_something
                ...        

_ndif testing_something

I kinda solved this problem with MPLAB variables, here's an example for testing equality between a register and a literal:

_f_equal_literal macro register,literal,name
    movlw literal
    subwf register,0
    btfss STATUS,2 ;bit indicating result is zero
    goto _false#v(name)
    endm

_lse macro name
    goto _next#v(name)
_false#v(name):
    endm

_ndif macro name
_next#v(name):
    endm

Notice that I didn't use goto _true#v(name) and _true#v(name): label, you'll just have to figure if you need btfss or btfsc.

You can have a single _lse and _ndif macro, and have multiple macros for _f statements.

GJ's solution doesn't have a next label, so the true branch will execute the false branch.


You need to define a variable for each if-else-endif construct.
It might even useful if the variable name describes what the if-else-endif is used for.

Example:

variable testing_something=123

_f_equal_literal some_register,some_value,testing_something
                ...       

_lse testing_something
                ...        

_ndif testing_something
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文