Описание ассемблера для Explay m3 =============================================================== вспомогательные проги для взлома прошивки к М3 (все с исходниками) SDK комплект разработчика для написания приложений на плеере М3 эмулятор, исполнитель прошивки на бейсике интерпретатор прошивки новый дизасемблер прошивки от 1 фев2007 компилятор с бейсика в машинный код исходники сегмента 8С000000-8С002999 (BOOT) =============================================================== Документацию качать отсюда: SPCA-533A.pdf [http://mxhaard.free.fr/spca50x/Doc/Sunplus/spca533a/SPCA-533A.pdf] vmips.pdf [http://www.dgate.org/vmips/doc/vmips.pdf] spim_documentation.pdf [http://www.cs.wisc.edu/~larus/SPIM/spim_documentation.pdf] HP_AppA.pdf [http://www.cs.wisc.edu/~larus/HP_AppA.pdf] psABI_mips3.0.pdf [ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/psABI_mips3.0.pdf] MPS.user.manual.1.22.pdf [http://downloads.sourceforge.net/mps/MPS.user.manual.1.22.pdf?modtime=1079913600&big_mirror=0] pcspim.zip - это эмулятор R3000 какой то непонятный. www.cs.wisc.edu/~larus/SPIM/pcspim.zip [http://www.cs.wisc.edu/~larus/SPIM/pcspim.zip] ------------------------------------------------- старый дизасемблер прошивки преобразует в понятный язык, даже кто не знает ассемблер поймет. половина инструкций и сопроцессор 1 не используется. в сопроцессоре 0 используются только регистры: Status 12 interrupt mask and enable bits Cause 13 exception type and pending interrupt bits EPC 14 address of instruction that caused exception ? 20 не знаю и нет описания пока Exceptions and interrupts cause a MIPS processor to jump to a piece of code, at address 80000180 Есть там обработчик прерываний с переходом на 8С010800 язык мипс р3000 знать не надо, прошивка дизасемблирует в почти язык высокого уровня, и написана в виде понятных обозначений на Си и бейсика. осталось только понять логику и адресацию, где память экрана, где данных, пока не ясно, всего 243000 инструкций, #B0000000 порты как память генерирует примерно такой код: 8C000000 lui $sp #D001 | $sp = #D001.0000 8C000004 addiu $sp $sp #8000 | $sp = $sp + #8000 8C000008 lui $gp #8C01 | $gp = #8C01.0000 8C00000C jal #8C000180 | 8C000010 addiu $gp $gp #A8C0 | CALL #8C000180 ; $gp = $gp + #A8C0 8C000018 lui $t3 #8C00 | $t3 = #8C00.0000 8C00001C addiu $t3 $t3 #0200 | $t3 = $t3 + #0200 8C000020 jalr $t3 $ra | 8C00002C lui $t4 #8C00 | CALL $t3 ; $t4 = #8C00.0000 8C000030 addiu $t4 $t4 #0450 | $t4 = $t4 + #0450 8C000034 jalr $t4 $ra | CALL $t4 8C000040 j #8C000040 | JMP #8C000040 .... 8C00023C sw $at $v0 #1010 | ( $at + #1010 ) = $v0 запись регистра в память .... 8C000240 lw $gp $v1 #80FC | $v1 = ( $gp + #80FC) загрузить из памяти размещение прошивки в памяти 0000.0000 -> 8C00.0000 загрузчик 0000.4000 -> 8C01.0000 основной код дальнейшая адресация будет дана в памяти плеера а не в прошивке. есть таблицы адресов для переходов. много 8C0025F0-8C0028B4 первая таблица для загрузчика. Если что то не ясно, в исходниках есть мини описание команд, или в HP_AppA.pdf смотреть надо что к чему. регистры 32 разрядные 32 штуки $zero=0, $at службный, $v0-1 для возврата значения из функций $a0-3 аргументы, $t0-9, $s0-7, $k0-1 для ОС, $gp - сегмент данных $sp указатель стека, $fp указатель фрейма, $ra адрес возврата. $lo $hi -регистры для деления умножения word=32 halword=16 byte=8 адресация индексная везде. в знаковых инструкциях , старший бит (знак) копируется влево до 31 бита. ----------------- Вот хорошая ссылка на дизассемблирование прошивки камеры на MIPS http://www.maushammer.com/systems/cvscamcorder/firmware-disassembly.html http://www.maushammer.com/systems/cvscamcorder/dismipper-0.9.zip здесь исходники и примеры как надо искать и описывать функции в прошивке, камера и плеер примерно одинаковы по функциям, можно по аналогии ломать, когда будет нормальное описалово, и разобран код больше чем наполовину, тогда можно будет улучшать код. вот еще некоторая дока по R3000 и кое какое описание аналогичных http://psxdev.narod.ru/docs.htm B000.0000 это память аппаратно отображенная на устройства = порты ------------------R2000-------------------------- add rd,rs,rt # R[rd] = R[rs] + R[rt] addu rd,rs,rt # R[rd] = R[rs] + R[rt] addi rd,rs,K # R[rd] = R[rs] + K addiu rd,rs,K # R[rd] = R[rs] + K sub rd,rs,rt # R[rd] = R[rs] - R[rt] subu rd,rs,rt # R[rd] = R[rs] - R[rt] mult rs,rt # HI = (R[rs]*R[rt])63-32 # LO = (R[rs]*R[rt])31-0 multu rs,rt # HI = (R[rs]*R[rt])63-32 # LO = (R[rs]*R[rt])31-0 div rs,rt # HI = (R[rs]%R[rt]) # LO = (R[rs]/R[rt]) divu rs,rt # HI = (R[rs]%R[rt]) # LO = (R[rs]/R[rt]) slt rd,rs,rt # if R[rs] < R[rt] then R[rd] = 1 # else R[rd] = 0 sltu rd,rs,rt # -"- slti rd,rs,K # if R[rs] < K then R[rd] = 1 # else R[rd] = 0 sltiu rd,rs,K # -"- and rd,rs,rt # R[rd] = R[rs] & R[rt] andi rd,rs,K # R[rd] = R[rs] & K or rd,rs,rt # R[rd] = R[rs] | R[rt] ori rd,rs,rt # R[rd] = R[rs] | K nor rd,rs,rt # R[rd] = ~(R[rs] | R[rt]) xor rd,rs,rt # R[rd] = R[rs] ^ R[rt] xori rd,rs,K # R[rd] = R[rs] ^ K sll rd,rt,K # R[rd] = R[rt] << K srl rd,rt,K # R[rd] = R[rt] >> K sra rd,rt,K # R[rd] = R[rt] >> K sllv rd,rt,rs # R[rd] = R[rt] << R[rs] srlv rd,rt,rs # R[rd] = R[rt] >> R[rs] srav rd,rt,rs # R[rd] = R[rt] >> R[rs] lui rt,K # R[rt]31-16 = K # R[rt]15-0 = 0 lb rt,diff(rs) # R[rt]7-0 = M[diff+R[rs]] # R[rt]31-8 = (M[diff+R[rs]]7)24 lbu rt,diff(rs) # R[rt]7-0 = M[diff+R[rs]] # R[rt]31-8 = (0)24 lh rt,diff(rs) # R[rt]15-0 = M.h[diff+R[rs]] # R[rt]31-16 = (M.h[diff+R[rs]]15)16 lhu rt,diff(rs) # R[rt]15-0 = M.h[diff+R[rs]] # R[rt]31-16 = (0)16 lw rt,diff(rs) # R[rt] = M.w[diff+R[rs]] sb rt,diff(rs) # M[diff+R[rs]] = R[rt]7-0 sh rt,diff(rs) # M.h[diff+R[rs]] = R[rt]15-0 sw rt,diff(rs) # M.w[diff+R[rs]] = R[rt] mfhi rd # R[rd] = HI mflo rd # R[rd] = LO mthi rs # HI = R[rs] mtlo rs # LO = R[rs] beq rs,rt,label # if R[rs] == R[rt] then PC = label bne rs,rt,label # if R[rs] != R[rt] then PC = label bgez rs,label # if R[rs] >= 0 then PC = label bgtz rs,label # if R[rs] > 0 then PC = label blez rs,label # if R[rs] <= 0 then PC = label bltz rs,label # if R[rs] < 0 then PC = label j label # PC = label jr rs # PC = R[rs] jal label # R[31] = PC + 4 # PC = label jalr rs # R[31] = PC + 4 # PC = R[rs] bgezal rs,label # temp = PC # if R[rs] >= 0 then PC = label # R[31] = temp+4 bltzal rs,label # temp = PC # if R[rs] < 0 then PC = label # R[31] = temp+4 break n # =int N syscall # =int 21 ------------------------------------------------------ 0xb0000000 - 0xb0000fff This area holds the 128 device descriptors which describe the hardware devices that are available in the system. For details: See Section 6.4.1 [Device descriptors], page 29. This area is read-only, meaning that writes have no effect. 0xb0001000 - 0xb0001fff This area holds the kernel boot parameters as a 0-terminated (C-style) string. This area is read-only, meaning that writes have no eect. 0xb0002000 - 0xb0007fff This area is reserved for future use. This area is read-only, meaning that writes have no effect. 0xb0008000 - 0xbfffffff This area holds the actual I/O ports and any additional memory areas for the devices. Whether writing to a certain address has any eect depends on the device and port/area in question. OFFSET SIZE DESCRIPTION 0x00 1 word Device type code. Type code 0 is not used by any devices, and it means that this descriptor is unused and should be ignored. See Section 6.4.2 [Device type codes], page 30. 0x04 1 word Device I/O address base. All I/O port osets of a device are relative to this address. 0x08 1 word The length of the device's I/O address area in bytes. This will always be a multiple of 4, since all ports are 32 bits wide. 0x0C 1 word The number of the IRQ that the device generates. Possible values are from 0 to 5. A value of -1 (0xffffffff) means the device will not generate any IRQs. 0x10 8 bytes Vendor string. These bytes are used to describe the model of the device or some other information intended to be read by humans. The operating system may safely ignore the contents of these bytes. These bytes may contain any values and need not be 0-terminated. 0x18 2 words Reserved. The contents of these word should be considered undefened. ------------------------------------------------------ таблица для дизасемблера, вторая колонка: 32 битная маска, третья колонка: 6 полей 6-5-5-5-5-6 бит, ??-номер регистра, ##-данные RS RT RD регистры по порядку в 2,3,4 полях madd 70000000 1C????000000 movz 0000000A 00??????000A movn 0000000B 00??????000B mfc0 40000000 1000????0000 mtc0 40800000 1004????0000 bltz 04000000 01??00###### blez 18000000 06??00###### bgtz 1C000000 07??00###### bgez 04010000 01??01###### srav 00000007 00??????0007 xor 00000026 00??????0026 xori 38000000 0E????###### sub 00000022 00??????0022 subu 00000023 00??????0023 div 0000001A 00????00001A divu 0000001B 00????00001B mult 00000018 00????000018 multu 00000019 00????000019 sra 00000003 0000????##03 srl 00000002 0000????##02 srlv 00000006 00??????0006 sll 00000000 0000????##00 sllv 00000004 00??????0004 nor 00000027 00??????0027 or 00000025 00??????0025 slti 28000000 0A????###### sltiu 2C000000 0B????###### slt 0000002A 00??????002A sltu 0000002B 00??????002B ori 34000000 0D????###### sh A4000000 29????###### sb A0000000 28????###### sw AC000000 2B????###### mthi 00000011 00??00000011 mtlo 00000013 00??00000013 mfhi 00000010 000000??0010 mflo 00000012 000000??0012 lw 8C000000 23????###### lh 84000000 21????###### lhu 94000000 25????###### lb 80000000 20????###### lbu 90000000 24????###### lui 3C000000 0F00??###### j 08000000 02########## jal 0C000000 03########## jalr 00000009 00??00??0009 jr 00000008 00??00000008 bne 14000000 05????###### beq 10000000 04????###### andi 30000000 0C????###### and 00000024 00??????0024 addu 00000021 00??????0021 addiu 24000000 09????###### addi 20000000 08????###### add 00000020 00??????0020 остальные команды не используются break #1C 0007000D непонятная команда? ext 7C000000 1F?????????? пока нет описания что такое, но попадается часто документация есть на mips.com (регистрация нужна) http://www.mips.com/content/Documentation/MIPSDocumentation/ProcessorArchitecture/doclibrary http://www.mips.com/content/Documentation/MIPSDocumentation/ProcessorCores/doclibrary обнаружена существенная ошибка из-за которой не сходилась логика, оказалось что все команды переходы имеют слот задержки - инструкция после перехода выполняется последовательно в паре вместе с переходом если он есть, она как бы первая в новой очереди конвеера команд. поэтому все CALL JUMP JMP на самом деле ниже на 4 байта и относительная адресация реально JMP +1 (+4 байта) поэтому код: 8C00055C beq $a0 $v0 #0012 | 8C000560 addiu $v0 0 #001D | JMP #8C0005A4 if $a0 = $v0 ; $v0 = #001D ($v0 = #001D - выполняется сразу после перехода) m:000598 jr $ra | $sp = : 8 ::00059C addiu $sp $sp #0008 | JUMP (return) ::0006C0 jal #8C0020E4 | $a2 = #0001 ::0006C4 addiu $a2 0 #0001 | CALL #8C0020E4 ------------------------------------------------------------ разобранные процедуры: //обозначения: (p****=#B000****) (m****=#8C00****)// c:000180| (#8C0029A8) = #8C000310 ; (#8C0029C0) = #8C000310 | (#8C0029AC) = #8C0025F0 ; (#8C0029BC) = #8C0025F0 | (#8C0029B0) = #8C0029A0 ; (#8C0029C4) = #8C00BF30 ------------------------------------------------------------- c:000200| byte(p1000) = 1 ; byte(p5023) = 1 //copy CODE to RAM? | $v1 = byte(p00B1) & 00000010 //2bit | (p1010) = #01A00401 | GOTO n_240 if $v1 // 2 bit byte(p00B1) | $v1 = (m29A4) ; $a1 = (m29A0) ; $a0 = (m29A8) // v1<-a0..a1 | for($v1 < $a1){($v1) = ($a0) ; $v1 += 4 ; $a0 += 4} | $v1 = (m29B8) ; $a1 = (m29B4) // v2<-a1..a2 | for($v1 < $a1){($v1) = ($a0) ; $v1 += 4 ; $a0 += 4} n240 | $v1 = (m29BC); $a1 = (m29B0) ; $a0 = (m29AC) // v1<-a0..a1 | for($v1 < $a1){($v1) = ($a0) ; $v1 += 4 ; $a0 += 4} | $a0 = (m29C4) //a1..a2<-0 | if(#8C0029C8 < $a0){for($v1 < $a0 ){($v1) = 0 ; $v1 += 4}} ----------------------------------------------------------------- C:002574| if($a1 < 0){$a0 = -$a0; $a1 = -$a1 ; if($a0 > 0)$a1--;} | GOTO_CALL c002484 if $a3 >= 0 t | $a2 = -$a2 ; $a3 = -$a3; if($a2 > 0)$a3--; | GOTO_CALL c002484 ---------------------------------------------------------- t | $t7 = $ra ; $t6 = $a1 ^ $a3 | CALL 8C002574 m:0025B4| if ($t6 < 0){$v0 = -$v0 ; $v1 = -$v1 ; if($v0 > 0)$v1--;} | GOTO $t7 //ret t | $t7 = $ra ; $t6 = $a1 | CALL 8C002574 | $v0 = $a0 ; $v1 = $a1 | LOOP m_0025B4 ----------------------------------------------------------------- C:001860| $sp -= 24 ; (Stek10) = $s0 | $s0 = $a0 //a0 pointer string+chr(0) | GOTO n_001894 if sign_byte($s0) = 0 //end string n:00187C| $a0 = byte($s0) ; $s0 ++ n1840| LOOP n_1840 if byte(p1016) & 00100000 = 0 //6bit wait | byte(p1015) = $a0 //usb? | LOOP n_00187C if sign_byte($s0) n:001894| $s0 = (Stek10) ; $sp += 24 ----------------------------------------------------------------- последнее обновление 1февраля 2007г