MIPS 4000

Lo dejo aqui pero he puesto el mismo post en desarrollo, creo que esta mejor alli.


Estoy aqui pegandome con el lenguaje ensamblador pero por mas que busco informacion no se como tomas el siguiente codigo:
Que pasa realmente en esta linea?
addiu $s0, $a0, loc_0 Estamos diciendo que s0= a0+ loc_0? pero no he encontrado informacion sobre operaciones con funciones en addiu todas dicen que es un valor immediato. He llegado a pensar que el valor de loc_0 es el valor v0 que devuelve la funcion. A contuniacion pongo lo que pone como loc 0, tampoco kiero una explicacion exaustiva, solo que valor tiene o que significa la expresion loc_0.
loc_0:
addiu $SP, -16
sw $ra, 12($sp)
lui $v1, 0
sw $s2, 8($sp)
lui $s2, 0
sw $s1, 4($sp)
addiu $s1, $v1, loc_40
sw $s0, 0($sp)
move $s0, $zero


Y la ultima pregunta es con respecto al delay slot, he estado leyendo que tras un salto siempre hay un delay slot.
En caso de por ejemplo tubieramos lo siguiente?
lui $sv1 = 0 o lui $sv1 = 1
bnez $v1, loc_24
addiu $s1, 4
lui $v1, 0
Existe delay slot tambien en un salto por condicional? o solo existen delays por las instrucciones j y derivados?
Si existe delay slot por condicional? en caso del caso rojo s1 valdria 4
y en el caso de verde ???? s1 valdria 1 o 4?
Quiero decir si el delay slot se lee o se salta cuando no se va a producir el salto???
Yo la verdad esta version del MIPS no la he trabajado, trabajé el MIPS 3000 en 1º de carrera, y no veiamos los Delay Slot, aun asi, hay dos tipos de Delay Slot, para 1 o para 3 instrucciones. Es importante saber cual de los dos es el que utiliza este procesador, ya que si no rellenas todos los huecos se ejecutaran instrucciones que no deben y si rellenas mas de la cuenta pueden no ejecutarse instrucciones que si deben ejecutarse, en otro caso si no puedes rellenar con instrucciones utiles puedes hacerlo con nop que es una instruccion que no modifica el estado del procesador.

Espero que te sirva de algo, es lo unico que puedo aportar.

Un saludo,
tchusami.
tchusami escribió:Yo la verdad esta version del MIPS no la he trabajado, trabajé el MIPS 3000 en 1º de carrera, y no veiamos los Delay Slot, aun asi, hay dos tipos de Delay Slot, para 1 o para 3 instrucciones. Es importante saber cual de los dos es el que utiliza este procesador, ya que si no rellenas todos los huecos se ejecutaran instrucciones que no deben y si rellenas mas de la cuenta pueden no ejecutarse instrucciones que si deben ejecutarse, en otro caso si no puedes rellenar con instrucciones utiles puedes hacerlo con nop que es una instruccion que no modifica el estado del procesador.

Espero que te sirva de algo, es lo unico que puedo aportar.

Un saludo,
tchusami.


Vaya muchas gracias, algo es algo!!y sabes en que casos se dan los delay slot de 3 instrucciones?

De esto addiu $s0, $a0, loc_0 no te acuerdas de nada no?
El addiu es una simple suma inmediata sin signo ni overflow, así que ese loc_0 que tienes es una constante que estará definida en algún lado, y no un registro.

En la otra cuestión, sí hay un delay con esa instrucción de salto, por lo que s1 valdrá 4 siempre.
anonimeitor escribió:El addiu es una simple suma inmediata sin signo ni overflow, así que ese loc_0 que tienes es una constante que estará definida en algún lado, y no un registro.

En la otra cuestión, sí hay un delay con esa instrucción de salto, por lo que s1 valdrá 4 siempre.

muxas gracias
Loc 0:
addiu $SP, -16
sw $ra, 12($sp)
lui $v1, 0
sw $s2, 8($sp)
lui $s2, 0
sw $s1, 4($sp)
addiu $s1, $v1, loc_40
sw $s0, 0($sp)
move $s0, $zero

Loc 0 esta definido asi, su valor sera v0?? O como puedo calc su valor?
Con una explicacion x encima me vale
loc_0 es la posición donde está el addiu $SP, -16, así que s1, inicialmente, apunta a esa dirección de memoria, pues v1 es 0. Es un valor fijo que se calcula al compilar, pues hasta entonces no vas a saber dónde se va a situar ese código. Precisamente por eso se pone loc_0, para que sea el compilador quien se encargue de poner el valor inmediato sin signo.
anonimeitor escribió:loc_0 es la posición donde está el addiu $SP, -16, así que s1, inicialmente, apunta a esa dirección de memoria, pues v1 es 0. Es un valor fijo que se calcula al compilar, pues hasta entonces no vas a saber dónde se va a situar ese código. Precisamente por eso se pone loc_0, para que sea el compilador quien se encargue de poner el valor inmediato sin signo.


Vaya genial muchas gracias, eres un crack ^^. Entonces lo que hace es meter en s1 la direccion de loc_0 (en este caso 0x00000000). Claro claro muy clarificador muchas gracias de nuevo.

Esto que dices es muy importante claro, porque como no se sabe que direcciones va a tomar, entonces nunca encontraremos una direccion en la memoria escrita a cal y canto sino a traves de las etiquetas, me equivoco?
¿Cómo que 0x00000000? Tendrá un valor determinado, que es la posición donde está escrita la instrucción de la etiqueta.

Al compilar el código y descompilarlo con alguna de las utilidades que hay, saldrá algo así:
... (lo que haya antes)
1234: addiu $SP, -16
1238: sw $ra, 12($sp)
123C: lui $v1, 0
1240: sw $s2, 8($sp)
1244: lui $s2, 0
1248: sw $s1, 4($sp)
124C: addiu $s1, $v1, 0x1234
1250: sw $s0, 0($sp)
1254: move $s0, $zero
... (lo que haya después)


Y loc_0 será 0x1234, pero es un valor que no interesa en absoluto, por eso se hace referencia a él con una etiqueta.
EN el codigo esta asi escrito.


LOAD:00000000 loc_0: # CODE XREF: start+1Cp
LOAD:00000000 # LOAD:00000820p
LOAD:00000000 # DATA XREF: ...
LOAD:00000000 addiu $sp, -0x10
LOAD:00000004 sw $ra, 0xC($sp)
LOAD:00000008 lui $v1, 0
LOAD:0000000C sw $s2, 8($sp)
LOAD:00000010 lui $s2, 0
LOAD:00000014 sw $s1, 4($sp)
LOAD:00000018 addiu $s1, $v1, loc_40
LOAD:0000001C sw $s0, 0($sp)
LOAD:00000020 move $s0, $zero
.
.
.
.
.
.
.
.
.
.
.
.
LOAD:0000073C
LOAD:0000073C .globl start
LOAD:0000073C start:
LOAD:0000073C
LOAD:0000073C var_10 = -0x10
LOAD:0000073C var_C = -0xC
LOAD:0000073C
LOAD:0000073C addiu $sp, -16
LOAD:00000740 lui $a0, 0
LOAD:00000744 sw $s0, 0($sp)
LOAD:00000748 addiu $s0, $a0, loc_0
LOAD:0000074C sw $ra, 4($sp)
LOAD:00000750 jal nullsub_5
LOAD:00000754 move $a0, $s0
LOAD:00000758 jal loc_0
LOAD:0000075C nop
LOAD:00000760 lui $a1, 0
LOAD:00000764 li $t1, 1
LOAD:00000768 lui $v1, 0
LOAD:0000076C addiu $a0, $a1, aScekermit # "SceKermit"
LOAD:00000770 move $a2, $zero
LOAD:00000774 move $a3, $zero
LOAD:00000778 li $a1, 0x100
LOAD:0000077C lui $v0, 0
LOAD:00000780 sw $t1, dword_D4
LOAD:00000784 jal nullsub_2
LOAD:00000788 sw $zero, dword_D0
LOAD:0000078C move $a0, $s0
LOAD:00000790 lui $a1, 0
LOAD:00000794 jal nullsub_4
LOAD:00000798 sw $v0, dword_CC
LOAD:0000079C move $v0, $zero
LOAD:000007A0 lw $ra, 4($sp)
LOAD:000007A4 lw $s0, 0($sp)
LOAD:000007A8 jr $ra
LOAD:000007AC addiu $sp, 16
LOAD:000007AC # End of

No pongo todo que tiene funciones para aburrir xDDD. yo tampoco tengo muy claro para que lo hace porque poco despues usa un jal nullsub_5 que dentro solo un :
jr $ra
nop,

la variable entra como a0 en la funcion pero ademas de no usarla para nada, no la guarda en la pila asique sencillamente se pierde en la nada.
Esa da la impresión que lo que hace es poner esa dirección en la pila, como si fuese un parámetro, para ser tratado de alguna forma.
anonimeitor escribió:Esa da la impresión que lo que hace es poner esa dirección en la pila, como si fuese un parámetro, para ser tratado de alguna forma.


Encontre un error, la culpa es del decompilador, realmente lo que pone es un 0, pero IDA PRO pone un loc_0 pensando que es una direccion y no un valor, he tenido que usar varios prxtool para darme cuenta ^^. (porque muchos crasheaban).
Pero muchas gracias por la informacion.
Manda huevos, que diría uno. Pues me parece un fallo bastante gordo del IDA.
anonimeitor escribió:Manda huevos, que diría uno. Pues me parece un fallo bastante gordo del IDA.



Bueno a ver si te pasas por aqui y ves esta duda.
Estoy intentando decompilar una subrutina de un programa, en este caso es memcpy, el caso es que he reversado todo el codigo, pero es que no le encuentro mucho sentido.
La funcion memcpy es una función para copiar datos en la RAM, que recibe 3 valores, el primero es el destino de los datos, el segundo de los valores es el origen de los datos y el tercero el tamaño.

Pues siguiendo y reservando el código entiendo todo, pero no encuentro realmente la acción, en ningún momento invoca o hace ninguna instrucción que escriba en la ram.
Lo que hace es comprobar que los valores sean correctos, si no lo son da un return con unos valores y si son correctos carga los valores en un registro at (que es un registro reservado al ensamblador y ya).
¿no existe una sentencia en MIPS que sirva para escribir unos datos en la memoria ram, en una ubicación concreta?


En definitiva esto sustitulle a escribir el valor en la ram???

0x0000D8F4: 0x88A10003 '....' - lwl $at, 3($a1)
0x0000D8F8: 0x98A10000 '....' - lwr $at, 0($a1)
0x0000D8FC: 0xB8810000 '....' - swr $at, 0($a0)
Normalmente todo suele estar alineado a 4 bytes, que es una de las cosas que da rapidez a estos micros, pero en ocasiones los datos no tienen por qué estarlo, así que por eso se emplean lwl/lwr/swr/swl. Como es lógico, al hacer un memcpy los offsets origen y destino no tienen por qué ser múltiplos de 4, y es el motivo de estas cosas tan aparentemente "extrañas".

Si $a1 apunta a los datos A-B-C-D-E-F-G-... (con letras, para verlo más claro), se hace lo siguiente:
  • primero lee 32 bits de $a1 en $at:
    - "lwl $at, 3($a1)" coge el word a la izquierda de $a1+3, es decir, los bytes 3 y 2, C-D, y lo pone en la parte baja de $at
    - "lwr $at, 0($a1)" coge el word a la derecha de $a1+0, es decir los bytes 0 y 1, A-B, y lo pone en la parte alta de $at
    - ahora ya tenemos A-B-C-D en $at
    (aquí ya se ve lo "raro" de estas instrucciones, pues una lee "hacia adelante" y otra "hacia atrás", pero siempre van a ir juntas porque una lee el word superior del registro y otra el inferior, y da igual el orden en el que se pongan ambas instrucciones)
  • luego guarda los 32 bits de $at en $a0 usando el mismo sistema (imagino que te has comido el swl, que es totalmente necesario)
Y si no me he equivocado en mucho, creo que eso es lo que hace. No recuerdo si el dato se guarda en $at como A-B-C-D o hay algún valor al revés, pero como sólo suelen usarse los lwl/lwr justo antes de los swl/swr y para poco más, no me interesa mucho saberlo.
anonimeitor escribió:Normalmente todo suele estar alineado a 4 bytes, que es una de las cosas que da rapidez a estos micros, pero en ocasiones los datos no tienen por qué estarlo, así que por eso se emplean lwl/lwr/swr/swl. Como es lógico, al hacer un memcpy los offsets origen y destino no tienen por qué ser múltiplos de 4, y es el motivo de estas cosas tan aparentemente "extrañas".

Si $a1 apunta a los datos A-B-C-D-E-F-G-... (con letras, para verlo más claro), se hace lo siguiente:
  • primero lee 32 bits de $a1 en $at:
    - "lwl $at, 3($a1)" coge el word a la izquierda de $a1+3, es decir, los bytes 3 y 2, C-D, y lo pone en la parte baja de $at
    - "lwr $at, 0($a1)" coge el word a la derecha de $a1+0, es decir los bytes 0 y 1, A-B, y lo pone en la parte alta de $at
    - ahora ya tenemos A-B-C-D en $at
    (aquí ya se ve lo "raro" de estas instrucciones, pues una lee "hacia adelante" y otra "hacia atrás", pero siempre van a ir juntas porque una lee el word superior del registro y otra el inferior, y da igual el orden en el que se pongan ambas instrucciones)
  • luego guarda los 32 bits de $at en $a0 usando el mismo sistema (imagino que te has comido el swl, que es totalmente necesario)
Y si no me he equivocado en mucho, creo que eso es lo que hace. No recuerdo si el dato se guarda en $at como A-B-C-D o hay algún valor al revés, pero como sólo suelen usarse los lwl/lwr justo antes de los swl/swr y para poco más, no me interesa mucho saberlo.


Creo que entiendo el codigo:
A ver si no me equivoco:
a0 = 0x88000000 (direccion de destino)
a1 = 0x12345678

Empieza:
guardar en at por la izq= 1234
guardar en at por la derecha = 5678
guardar at (0x12345678) en (0x88000000) desplazado 0 porque queremos que sea en 0x88000000.
Osea que lo que hace es guardar la direccion de la ram en un registro (a0), ejecuta el comando swl y swr y los pone en (a0), que es equivalente a guardarlo en esa direccion ^^.
Creo que entre tu y un libro me he aclarado muchas gracias ^^. Eres un crack.
No, a1 es otra dirección, y 0x12345678 sería lo que hay allí.

Inicialmente, por ejemplo:
0x81000001: lo que hubiese
0x82000006: 0, 1, 2, 3, ...

a1 = 0x82000006 (origen)
a0 = 0x81000001 (destino)

después de las operaciones, lwl/lwr/swl/swr:
0x81000001: 0, 1, 2, 3, ...
0x82000006: 0, 1, 2, 3, ...
15 respuestas