【问题标题】:How to push variable in sdcc inline assembly?如何在 sdcc 内联汇编中推送变量?
【发布时间】:2020-04-29 10:48:42
【问题描述】:

我在ThreadCreate()中有这个代码:

int tmpPSW = newThID << 3;
__asm
    PUSH A
    PUSH _tmpPSW
__endasm;

这会导致:

?ASlink-Warning-Undefined Global '_tmpPSW' referenced by module 'cooperative'

我不明白为什么。 tmpPSW 定义明确,但 sdcc 抱怨。我在这里做错了什么?还有其他方法可以在 sdcc 内联汇编中推送 C 变量吗?

这也可能是相关的。生成的.asm 文件包含分配信息:

;------------------------------------------------------------
;Allocation info for local variables in function 'ThreadCreate'
;------------------------------------------------------------
;fp                        Allocated to registers 
;newThMask                 Allocated to registers r6 r7 
;newThID                   Allocated to registers r5 
;startSP                   Allocated to registers r3 r4 
;tmp                       Allocated to registers 
;tmpPSW                    Allocated to registers 
;------------------------------------------------------------

这是否意味着我的寄存器用完了?如果是这样,我应该如何减轻这种情况?


编辑:

ThreadCreate()的来源:

// ThreadID is typedef&#039;ed as char
ThreadID ThreadCreate(FunctionPtr fp) {
    if (activeTh == 0b1111)
        return -1;

    // i.e. get rightmost bit 0 in bitmask
    // https://stackoverflow.com/a/42747608/6306190
    int newThMask = ~activeTh & (activeTh + 1);

    activeTh |= newThMask;

    ThreadID newThID = 0;
    while (newThMask >>= 1) { newThID++; }
    int startSP = (newThID ^ (1UL << 2)) << 4;

    int tmp = SP;
    SP = startSP;

    int tmpPSW = newThID << 3;
    __asm
        PUSH DPL          ;; push _fp (argument passed in as DPTR in SDCC)
        PUSH DPH          ;; push _fp
        MOV A, #0
        PUSH A            ;; ACC
        PUSH A            ;; B
        PUSH A            ;; DPL
        PUSH A            ;; DPH
        PUSH _tmpPSW      ;; PSW
    __endasm;

    savedSP[newThID] = SP;
    SP = tmp;
    return newThID;
}

ThreadCreate() 的生成程序集:

;------------------------------------------------------------
;Allocation info for local variables in function &#039;ThreadCreate&#039;
;------------------------------------------------------------
;fp                        Allocated to registers 
;newThMask                 Allocated to registers r6 r7 
;newThID                   Allocated to registers r5 
;startSP                   Allocated to registers r3 r4 
;tmp                       Allocated to registers 
;tmpPSW                    Allocated to registers 
;------------------------------------------------------------
;   cooperative.c:104: ThreadID ThreadCreate(FunctionPtr fp) {
;   -----------------------------------------
;    function ThreadCreate
;   -----------------------------------------
_ThreadCreate:
;   cooperative.c:110: if (activeTh == 0b1111)
    mov a,#0x0f
    cjne    a,_activeTh,00121$
    clr a
    cjne    a,(_activeTh + 1),00121$
    sjmp    00122$
00121$:
    sjmp    00102$
00122$:
;   cooperative.c:111: return -1;
    mov dpl,#0xff
    ret
00102$:
;   cooperative.c:119: int newThMask = ~activeTh & (activeTh + 1);
    mov a,_activeTh
    cpl a
    mov r6,a
    mov a,(_activeTh + 1)
    cpl a
    mov r7,a
    mov a,#0x01
    add a,_activeTh
    mov r4,a
    clr a
    addc    a,(_activeTh + 1)
    mov r5,a
    mov a,r4
    anl ar6,a
    mov a,r5
    anl ar7,a
;   cooperative.c:157: activeTh |= newThMask;
    mov a,r6
    orl _activeTh,a
    mov a,r7
    orl (_activeTh + 1),a
;   cooperative.c:160: while (newThMask >>= 1) { newThID++; }
    mov r5,#0x00
00103$:
    mov ar3,r6
    mov a,r7
    mov c,acc.7
    rrc a
    xch a,r3
    rrc a
    xch a,r3
    mov r4,a
    mov ar6,r3
    mov ar7,r4
    mov a,r3
    orl a,r4
    jz  00105$
    inc r5
    sjmp    00103$
00105$:
;   cooperative.c:161: int startSP = (newThID ^ (1UL << 2)) << 4;
    mov ar3,r5
    mov r4,#0x00
    mov r6,#0x00
    xrl ar3,#0x04
    mov a,r4
    swap    a
    anl a,#0xf0
    xch a,r3
    swap    a
    xch a,r3
    xrl a,r3
    xch a,r3
    anl a,#0xf0
    xch a,r3
    xrl a,r3
    mov r4,a
;   cooperative.c:163: int tmp = SP;
    mov r7,_SP
;   cooperative.c:164: SP = startSP;
    mov _SP,r3
;   cooperative.c:176: __endasm;
    PUSH    DPL ;; push _fp (argument passed in as DPTR in 390)
    PUSH    DPH ;; push _fp
    MOV A, #0
    PUSH    A ;; ACC
    PUSH    A ;; B
    PUSH    A ;; DPL
    PUSH    A ;; DPH
    PUSH    _tmpPSW ;; PSW
;   cooperative.c:178: savedSP[newThID] = SP;
    mov a,r5
    add a,r5
    add a,#_savedSP
    mov r1,a
    mov r4,_SP
    mov r6,#0x00
    mov @r1,ar4
    inc r1
    mov @r1,ar6
;   cooperative.c:179: SP = tmp;
    mov _SP,r7
;   cooperative.c:180: return newThID;
    mov dpl,r5
;   cooperative.c:181: }
    ret

【问题讨论】:

  • 从我使用 sdcc 开始,它就不支持从程序集中访问局部变量。您需要分配给全局变量,然后在程序集中使用它。
  • 生成的带有tmpPWS的程序集文件中还有哪些其他行? -- 注意int 在 8051 上是 16 位的,你宁愿使用uint8_t。 -- 8051中没有指令PUSH A,需要PUSH ACC
  • @thebusybee sourceasmThreadCreate()。谢谢提醒!我完全忘记了那些特质。
  • 下次请edit你的问题,而不是把代码放在其他地方。

标签: c embedded inline-assembly 8051 sdcc


【解决方案1】:

编译器优化了您的变量,因为从编译器的角度来看,它从未被使用过。将生成的程序集与源代码进行比较即可看到这一点。

您可以尝试其他选项。因为我没有安装 SDCC,我只能建议:

  • 创建变量volatile
  • 创建变量static,因为PUSH 的一种风格适用于内部RAM 中的地址。
  • 因为内联汇编在很大程度上依赖于周围的代码和编译器,您也可以在汇编部分使用newThID,并在那里进行移位。

注 1:生成的程序集演示了如果您不加思索地使用int,机器代码会变得多么慢。将变量限制为最小的适当数据类型。

注意 2:不要将变量设为全局变量。 static 在不全局公开变量的情况下做你想做的事:将它放在 RAM 中以便可以访问它。

【讨论】:

  • 为什么你会期望自动存储中的int tmpPSW 有一个 asm 符号名称,即使它没有被优化掉?例如volatile int 在自动存储中? (或者 8051 没有可用于自动存储的调用堆栈,导致编译器在非递归/重入函数中使用静态内存进行 C 自动存储?我也不使用 8051)。您建议的实际答案似乎是将其放入静态存储中,例如作为static 本地人。或者最好只在 asm 中做。这些对我来说很有意义。
  • 由于没有像SP + offset 这样的寻址模式(甚至没有任何&lt;reg&gt; + offset 用于RAM),通常自动变量位于寄存器或覆盖RAM 中。两者都可以通过PUSH 访问。 -- 如果使用内置SP的话,栈真的很小,只有几十个字节。编译器倾向于避免自动变量使用此堆栈。如果不添加特定于编译器的关键字,函数通常是不可重入的。
  • 好吧,这就是我想我从Why do C to Z80 compilers produce poor code? 记得的内容。所以我的真正意思是,本地范围int tmpPSW 基本上不能有_tmpPSW 的asm 符号名称,因为相同的名称可以在多个函数中使用。除非编译器重写你的内联汇编以匹配......当然,这种推理也适用于本地范围的static int;两个函数都可以有static int tmpPSW;,甚至在同一个函数中有两个作用域; gcc/clang 使用 func 名称作为静态局部变量的 asm 名称的一部分。
  • 一些汇编器非常聪明,在每个函数中都使用了一种局部作用域。不过,我不了解 SDCC。
  • 它是如何工作的?对于像 NASM 这样的汇编程序,函数范围的标签具有特殊的名称,前缀为 .。如果只是 _tmpPSW 用于访问静态本地,那意味着您需要特殊的语法来访问 global 符号,不是吗?或者你猜_ 是某些 8051 汇编器的本地标签前缀?非常值得怀疑,因为它是 C 标识符的有效部分。
猜你喜欢
  • 2013-07-23
  • 1970-01-01
  • 2022-01-16
  • 2019-12-31
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多