使用 NEC 78K0R 中返回地址(从堆栈读取)处的数据传递参数

逆向工程 拆卸 nec-78k0r
2021-06-19 11:37:03

我正在对 NEC 78K0R 进行一些拆卸。大多数函数都有在寄存器中传递的参数,但有一些函数使用我以前从未见过的方法传递编译时定义的参数。

指令的执行来自闪存。

函数 0x4c4 的调用方式如下:

027d9        fdc404      CALL            !4C4H
027dc        02          ?               ?
027dd        75          MOV             D,A

返回地址设置为 0x27dc 并放入堆栈。

函数本身如下:

// Entry point from call
004c4        c1          PUSH            AX
004c5        c3          PUSH            BC
004c6        c5          PUSH            DE
004c7        c7          PUSH            HL

// Get the stack pointer into HL
004c8        aef8        MOVW            AX,SP
004ca        16          MOVW            HL,AX
004cb        c7          PUSH            HL

// Preserve the ES (extended segment) register used for addressing
004cc        8efd        MOV             A,ES
004ce        c1          PUSH            AX

// Retreive SP + 0x0A - this is the ES part of the return address
004cf        8c0a        MOV             A,[HL+0AH] 
004d1        9efd        MOV             ES,A

// Retreive SP + 0x8 - this is the lower two bytes of return address
004d3        ac08        MOVW            AX,[HL+8H] 
004d5        16          MOVW            HL,AX

// Take the contents of memory from the return address into A
004d6        118b        MOV             A,ES:[HL]

// Not relevant to question
004d8        74          MOV             E,A
004d9        c0          POP             AX
004da        9efd        MOV             ES,A
004dc        5500        MOV             D,#0H

// HL is the original return address - shift up one to skip to instruction and store back into stack
004de        a7          INCW            HL
004df        17          MOVW            AX,HL
004e0        c6          POP             HL
004e1        bc08        MOVW            [HL+8H],AX

因此,简而言之 - 参数 02 存储在闪存中的下一个地址。这是通过使用堆栈中的返回地址来检索的,然后堆栈中的返回地址加一,以便我们进入下一条真正的指令。

该函数会改变堆栈的内容,但我认为这与问题无关。

我以前没有见过这种方法 - 很好奇。我不知道为什么要这样做 - 与执行以下操作相比,需要很多说明:

MOV A,#2
CALL !4c4H
<use A as parameter>

有没有人对为什么这样做有任何见解?

编辑

根据要求,整个功能:

004c4        c1          PUSH            AX
004c5        c3          PUSH            BC
004c6        c5          PUSH            DE
004c7        c7          PUSH            HL
    004c8        aef8        MOVW            AX,SP
    004ca        16          MOVW            HL,AX
    004cb        c7          PUSH            HL
        004cc        8efd        MOV             A,ES
        004ce        c1          PUSH            AX
            004cf        8c0a        MOV             A,[HL+0AH] 
            004d1        9efd        MOV             ES,A
            004d3        ac08        MOVW            AX,[HL+8H] 
            004d5        16          MOVW            HL,AX
            004d6        118b        MOV             A,ES:[HL]
            004d8        74          MOV             E,A
        004d9        c0          POP             AX
        004da        9efd        MOV             ES,A
        004dc        5500        MOV             D,#0H
        004de        a7          INCW            HL
        004df        17          MOVW            AX,HL
    004e0        c6          POP             HL
    004e1        bc08        MOVW            [HL+8H],AX
    004e3        17          MOVW            AX,HL
    004e4        25          SUBW            AX,DE
    004e5        bef8        MOVW            SP,AX
    004e7        c5          PUSH            DE
        004e8        14          MOVW            DE,AX
        004e9        320c00      MOVW            BC,#0CH
        004ec        8b          MOV             A,[HL]
        004ed        99          MOV             [DE],A
        004ee        a7          INCW            HL
        004ef        a5          INCW            DE
        004f0        b3          DECW            BC
        004f1        6171        XOR             A,A
        004f3        616a        OR              A,C
        004f5        616b        OR              A,B
        004f7        dff3        BNZ             $4ECH
    004f9        c2          POP             BC
    004fa        aef8        MOVW            AX,SP
    004fc        040c00      ADDW            AX,#0CH
    004ff        14          MOVW            DE,AX
    00500        3620fe      MOVW            HL,#0FE20H
    00503        fd6104      CALL            !461H
00506        c6          POP             HL
00507        c4          POP             DE
00508        c2          POP             BC
00509        c0          POP             AX
0050a        d7          RET      

从上面调用的子 461:

            00461        c1          PUSH            AX
            00462        c3          PUSH            BC
        00463        61dd        PUSH            PSW
            00465        17          MOVW            AX,HL
            00466        25          SUBW            AX,DE
            00467        de18        BNC             $481H
            00469        37          XCHW            AX,HL
            0046a        03          ADDW            AX,BC
            0046b        37          XCHW            AX,HL
            0046c        35          XCHW            AX,DE
            0046d        03          ADDW            AX,BC
            0046e        35          XCHW            AX,DE
            0046f        61cd        POP             PSW
            00471        b7          DECW            HL
            00472        b5          DECW            DE
            00473        8b          MOV             A,[HL]
            00474        99          MOV             [DE],A
            00475        b3          DECW            BC
            00476        6171        XOR             A,A
            00478        616a        OR              A,C
            0047a        616b        OR              A,B
            0047c        dff3        BNZ             $471H
        0047e        ee1000      BR              $!491H
        00481        61cd        POP             PSW
        00483        c5          PUSH            DE 
        00484        c7          PUSH            HL
            00485        8b          MOV             A,[HL]
            00486        99          MOV             [DE],A
            00487        a7          INCW            HL
            00488        a5          INCW            DE
            00489        b3          DECW            BC
            0048a        13          MOVW            AX,BC
            0048b        6168        OR              A,X
            0048d        dff6        BNZ             $485H
        0048f        c6          POP             HL
        00490        c4          POP             DE
    00491        c2          POP             BC
    00492        c0          POP             AX
    00493        d7          RET  

还有通话的前/后:

024fe        c5          PUSH            DE
024ff        fdc404      CALL            !4C4H
02502        06          
02503        9d24        MOV             0FFE24H,A
02505        33          XCHW            AX,BC
02506        bd20        MOVW            0FFE20H,AX
1个回答

这种方法(函数调用后跟数据)经常用于实现开关/表跳转,尤其是在闪存空间有限的平台上(因此他们更喜欢不内联开关代码而是使用辅助例程)。我已经看到它在 ARM、8051 和其他一些 CPU 上完成。由于开关数据(值和偏移量)不会改变,因此将其放入代码闪存空间是有意义的。

编辑:感谢完整列表。很明显,该值用于递减 SP,然后将 12 字节的已保存寄存器复制到那里,然后在sub 461H.

猜测,这会设置调用者的函数框架(为本地变量分配空间)。至于为什么它是代码字节而不是直接参数,我只有一个理论:节省闪存空间,因为与MOV(至少 2 个字节)或MOV + PUSH(至少 3 个字节)指令相反,只需要一个字节

我建议找出用于此代码的编译器(瑞萨电子?KPIT?)并在运行时库中搜索此函数。符号在这里应该有所帮助。

EDIT2:sub 461 似乎memmove(DE, HL, BC)带有复制方向检测。所以它将 N 个字节从 FE20 复制到新分配的堆栈空间中。奇怪的东西。