More 8032 / 8051 trickery

Don't worry, the (serial) printf handler is coming. In the meantime, some more hard to spot Mediatek 8032/8051 (Geez, couldn't at least agree on the base architecture name, and use declinations that make sense?) compiler trickery with lcall:

ROM:C32C                 lcall   ROM_B613
ROM:C32F lcall copy_4_bytes_to_xRAM ; input: DPTR = dest xRAM address
ROM:C32F ; PC = src bytes address
ROM:C32F ; ---------------------------------------------------------------------------
ROM:C332 .byte 0x00,0xC,0x00,0x00 ; 0
ROM:C336 ; ---------------------------------------------------------------------------
ROM:C336 mov DPTR, #0xFFFC
ROM:C339 lcall ROM_B613
ROM:C33C lcall copy_4_bytes_to_xRAM ; input: DPTR = dest xRAM address
ROM:C33C ; PC = src bytes address
ROM:C33C ; ---------------------------------------------------------------------------
ROM:C33F .byte 0,0xC,0,0 ; 0
ROM:C343 ; ---------------------------------------------------------------------------
ROM:C343 mov R6, #0x12
ROM:C345 mov R7, #0

When people extensively start/have to use instructions in other ways than they were designed for (shouldn't all lcalls' return flow of execution pcik up right after the instruction itself?), you know that you have a poorly designed CPU, no matter what people manage to achieve with it.

Yeah, it's another lcall'ed function that doesn't return where it's supposed to and breaks our nice disassembly flow. Thanks for making us having to manually edit our subroutine ends in IDA Pro, morons!

So, how does it work this time? Similarly to the previous trick actually:

ROM:B498 ; =============== S U B R O U T I N E =======================================
ROM:B498 ; input: DPTR = dest xRAM address
ROM:B498 ; PC = src bytes address
ROM:B498 copy_4_bytes_to_xRAM: ; CODE XREF: ROM:2A49p
ROM:B498 ; ROM:2A77p ...
ROM:B498 mov R0, DPL
ROM:B49A mov B, DPH ; DPTRd [DPHd DPLd] -> B R0 = Dest Pointer
ROM:B49D pop DPH
ROM:B49F pop DPL ; DPTRs [DPHs DPLs] = Src Pointer
ROM:B4A1 lcall copy_byte
ROM:B4A4 lcall copy_byte
ROM:B4A7 lcall copy_byte
ROM:B4AA lcall copy_byte
ROM:B4AD clr A
ROM:B4AE jmp @A+DPTR ; DPTRs (= original return PC) has
ROM:B4AE ; End of function copy_4_bytes_to_xRAM ; been incremented 4 times at this stage
ROM:B4AF ; =============== S U B R O U T I N E =======================================
ROM:B4AF copy_byte: ; CODE XREF: copy_4_bytes_to_xRAM+9p
ROM:B4AF ; copy_4_bytes_to_xRAM+Cp ...
ROM:B4AF clr A
ROM:B4B0 movc A, @A+DPTR ; read [DPTRs]
ROM:B4B1 inc DPTR ; DPTRs++ (as well as [DPTRs] -> A)
ROM:B4B2 xch A, DPH
ROM:B4B4 xch A, B ; DPTRs <-> DPTRd (B R0)
ROM:B4B6 xch A, DPH
ROM:B4B8 xch A, R0
ROM:B4B9 xch A, DPL
ROM:B4BB xch A, R0 ; A is still [DPTRs] at this stage
ROM:B4BC movx @DPTR, A ; [DPTRs] -> [DPTRd]
ROM:B4BE xch A, DPH ; DPTRs <-> DPTRd
ROM:B4C0 xch A, B
ROM:B4C2 xch A, DPH
ROM:B4C4 xch A, R0
ROM:B4C5 xch A, DPL
ROM:B4C7 xch A, R0
ROM:B4C8 ret
ROM:B4C8 ; End of function copy_byte

Gotta love these scores of xch instructions. Kind of the 3 cups & one red ball street magician classic. The only thing you need to know though, is that all a sequence like the following 3 lines does:
xch A, register1
xch A, register2
xch A, register1

is simply exchanging the content of register 1 & register 2, and keeping A unchanged.

I won't say this isn't a nice trick to access a small amount of data right within your program, but I'll take my general purpose register generous 68000 any time over your crappy 8051. It's a wonder really: How comes there are so few consumer devices using embedded 68000, when it would be so much more efficient for embedded applications? If you're gonna play with these kind of intel x32/x51 hurdles, it won't be that much different to go RISC all the way!

No comments:

Post a Comment