我正在对 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