Autor Tema: Desreferenciando caracteres en una struct...  (Leído 6448 veces)

0 Usuarios y 4 Visitantes están viendo este tema.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Desreferenciando caracteres en una struct...
« Respuesta #30 en: 13 de Febrero de 2016, 00:20:32 »
Lamento elgarbe por desvirtuarte el tema y espero que Bruno le guste el ASM xD

Jugando ahora si con las compilaciones..

Bruno, Cree el codigo que me dijiste, en realidad hice esto en CCS (TI tiene su propio compilador), NO ES GCC pero es lo que mas tenia a mano. Y es para un ARMv7-M ( M4F )
Una cosa mas.. puede que los resultados no sean exactos en la parte con optimizacion, especialmente en la parte de volatile, por que la funcion que cree Explota() en si no sirve para nada. Y que tal ves eso es lo que hace que quite esta funcion. Mas adelante voy a crear otra funcion Explota() y veremos la diferencia.

Código: C
  1. #include <stdint.h>
  2.  
  3. void Explota(void);
  4.  
  5. volatile uint8_t activarBomba = 0;
  6.  
  7. void main(void) {
  8.  
  9.         while(1)
  10.         {
  11.             activarBomba = 0;
  12.             if(activarBomba)
  13.             {
  14.                 Explota();
  15.             }
  16.  
  17.         }
  18. }
  19.  
  20. void Explota(void)
  21. {
  22.         int i = 3;
  23.         int j = 1;
  24.         i += j;
  25.         j += i;
  26. }
  27.  
  28. static void IntDefaultHandler(void)
  29. {
  30.         activarBomba = 1;
  31. }

--------------------------------------
Luego de creado el C, compilado con distintas versiones y optimizaciones , procedi a hacerle un dissasembly con el objdump, a la derecha estan los comentarios intentando traducirlo a "C", obtuve lo siguiente:

Sin optimizaciones (CON volatile): (Si quieren omitan estos 2 que son largos y procedan al resultado)

Código: ASM
  1. 00000498 <main>:                                ; void main(void) {
  2.  498:   b508            push    {r3, lr}        ;
  3.  49a:   ea4f 0808       mov.w   r8, r8          ;
  4.  49e:   46c0            nop                     ;
  5.  4a0:   f240 2114       movw    r1, #532        ; while(1) {
  6.  4a4:   2000            movs    r0, #0          ;
  7.  4a6:   f2c2 0100       movt    r1, #8192       ;  
  8.  4aa:   7008            strb    r0, [r1, #0]    ; activaBomba = 0;
  9.  4ac:   f240 2014       movw    r0, #532        ;
  10.  4b0:   f2c2 0000       movt    r0, #8192       ;
  11.  4b4:   7800            ldrb    r0, [r0, #0]    ;  <-- lee de memoria
  12.  4b6:   2800            cmp     r0, #0          ; if(activaBomba)
  13.  4b8:   d0f2            beq.n   4a0 <main+0x8; activaBomba es 0 salta a 0x4A0
  14.  4ba:   f000 f801       bl      4c0 <Explota>   ; activaBomba es 1 salta a 0x4C0 ( Explota )
  15.  4be:   e7ef            b.n     4a0 <main+0x8>  ; } Fin del while(1)
  16.  
  17. 000004c0 <Explota>:                             ; void Explota(void) {
  18.  4c0:   f1ad 0d08       sub.w   sp, sp, #8      ; // Espacio para las variables
  19.  4c4:   2003            movs    r0, #3          ; i = 3;
  20.  4c6:   9000            str     r0, [sp, #0]    ;
  21.  4c8:   2001            movs    r0, #1          ; j = 1;
  22.  4ca:   9001            str     r0, [sp, #4]    ;
  23.  4cc:   9900            ldr     r1, [sp, #0]    ;
  24.  4ce:   9801            ldr     r0, [sp, #4]    ;
  25.  4d0:   1840            adds    r0, r0, r1      ; j += i;
  26.  4d2:   9000            str     r0, [sp, #0]    ;
  27.  4d4:   9901            ldr     r1, [sp, #4]    ;
  28.  4d6:   9800            ldr     r0, [sp, #0]    ;
  29.  4d8:   1840            adds    r0, r0, r1      ; i += j ;
  30.  4da:   9001            str     r0, [sp, #4]    ;
  31.  4dc:   b002            add     sp, #8          ; // Retorno el Stack Pointer al lugar de antes
  32.  4de:   4770            bx      lr              ; } // Fin Explota();
  33.  
  34. 00000540 <IntDefaultHandler>:
  35.  540:   f240 2114       movw    r1, #532        ; Interrupcion() {
  36.  544:   2001            movs    r0, #1          ;
  37.  546:   f2c2 0100       movt    r1, #8192       ;
  38.  54a:   7008            strb    r0, [r1, #0]    ; activaBomba = 1;
  39.  54c:   4770            bx      lr              ; }

--------------------------------------------

Sin optimizaciones ( SIN volatile )

Código: ASM
  1. 00000498 <main>:                                ; void main(void) {
  2.  498:   b508            push    {r3, lr}
  3.  49a:   ea4f 0808       mov.w   r8, r8
  4.  49e:   46c0            nop                     ;
  5.  4a0:   f240 2114       movw    r1, #532        ; while(1) {
  6.  4a4:   2000            movs    r0, #0          ;
  7.  4a6:   f2c2 0100       movt    r1, #8192       ;
  8.  4aa:   7008            strb    r0, [r1, #0]    ; activaBomba = 0;
  9.  4ac:   f240 2014       movw    r0, #532        ;
  10.  4b0:   f2c2 0000       movt    r0, #8192       ;
  11.  4b4:   7800            ldrb    r0, [r0, #0]    ;  <-- lee de memoria
  12.  4b6:   2800            cmp     r0, #0          ; if (activaBomba) {
  13.  4b8:   d0f2            beq.n   4a0 <main+0x8; Igual a 0: Comienza el while de nuevo
  14.  4ba:   f000 f801       bl      4c0 <Explota>   ; Igual a 1: Explota
  15.  4be:   e7ef            b.n     4a0 <main+0x8>  ; } Fin del while } Fin de main
  16.  
  17. 000004c0 <Explota>:                             ; void Explota(void) {
  18.  4c0:   f1ad 0d08       sub.w   sp, sp, #8      ;
  19.  4c4:   2003            movs    r0, #3
  20.  4c6:   9000            str     r0, [sp, #0]    ; i = 3;
  21.  4c8:   2001            movs    r0, #1
  22.  4ca:   9001            str     r0, [sp, #4]    ; j = 1
  23.  4cc:   9900            ldr     r1, [sp, #0]
  24.  4ce:   9801            ldr     r0, [sp, #4]
  25.  4d0:   1840            adds    r0, r0, r1      ; j += i;
  26.  4d2:   9000            str     r0, [sp, #0]
  27.  4d4:   9901            ldr     r1, [sp, #4]
  28.  4d6:   9800            ldr     r0, [sp, #0]
  29.  4d8:   1840            adds    r0, r0, r1      ; i += j;
  30.  4da:   9001            str     r0, [sp, #4]
  31.  4dc:   b002            add     sp, #8
  32.  4de:   4770            bx      lr              ; } Fin Explota()
  33.  
  34. 00000540 <IntDefaultHandler>:                   ; void Interrupt() {
  35.  540:   f240 2114       movw    r1, #532        ;
  36.  544:   2001            movs    r0, #1
  37.  546:   f2c2 0100       movt    r1, #8192       ; 0x2000
  38.  54a:   7008            strb    r0, [r1, #0]    ; activaBomba = 1;
  39.  54c:   4770            bx      lr              ; }


Resultado: Hasta aqui se puede ver que SIN o CON volatile , si uno NO usa las optimizaciones es lo mismo. Y el codigo definitivamente es HORRIBLE.

----------------------------------------------

Optimizacion maxima y optimizado a velocidad , SIN volatile

Código: ASM
  1. 000004e0 <IntDefaultHandler>:                   ; void Interrupt() {
  2.  4e0:   f240 2114       movw    r1, #532        ;
  3.  4e4:   2001            movs    r0, #1
  4.  4e6:   f2c2 0100       movt    r1, #8192       ;
  5.  4ea:   7008            strb    r0, [r1, #0]    ; activaBomba = 1
  6.  4ec:   4770            bx      lr
  7.  4ee:   46c0            nop                     ; }
  8.  
  9. 00000520 <main>:                                ; void main() {
  10.  520:   e7fe            b.n     520 <main>      ;  while(1); } // Fin de main

Resultado: Esta fue la mas reveladora. el main, esta formado por un while(true) nomas. Se observa ademas que Explota() desaparecio, ni siquiera existe. Ya que lo unico que hacia era poner una crear 2 varaibles dentro del scope de la funcion sumarlas y nada mas, es decir no se usaban para nada. Y el optimizador procedio a eliminarlas.

---------------------------------------------

Optimizacion maxima y optimizado a velocidad , CON volatile

Código: ASM
  1. 000004e0 <IntDefaultHandler>:                   ; void Interrupt(void) {
  2.  4e0:   f240 2114       movw    r1, #532        ;
  3.  4e4:   2001            movs    r0, #1
  4.  4e6:   f2c2 0100       movt    r1, #8192       ;
  5.  4ea:   7008            strb    r0, [r1, #0]    ; activaBomba = 1
  6.  4ec:   4770            bx      lr
  7.  4ee:   46c0            nop                     ; }
  8.  
  9. 00000510 <main>:                                ; void main(void) {
  10.  510:   f240 2114       movw    r1, #532        ; 0x214
  11.  514:   2200            movs    r2, #0
  12.  516:   f2c2 0100       movt    r1, #8192       ; 0x2000
  13.  51a:   ea4f 0808       mov.w   r8, r8
  14.  51e:   46c0            nop                     ;
  15.  520:   700a            strb    r2, [r1, #0]    ; while(1) {
  16.  522:   7808            ldrb    r0, [r1, #0]    ; activaBomba=0; R0 = ???? pero que no lleva a ningun lado
  17.  524:   e7fc            b.n     520 <main+0x10> ; }

Resultado: Con volatile cambia, Esta ves pone nuestra variable en 0, pero imagino que debido a que Explota() es una funcion sin "sentido" por lo que explique antes, lo elimino. Y por ende el if() quedaba vacio dentro, por lo cual procedio tambien procedio a eliminarlo.

EDIT: Por favor leer la respuesta de BrunoF luego de este post, explicando esta instruccion
Del ASM lo unico que no puedo identificar es que esta tomando y poniendo en R0, ya que en 0x214 hay una instruccion y no un dato:

Código: ASM
  1. 214:    0783            lsls    r3, r0, #30

De todas formas no usa R0 dentro del loop del while(1) y queda como una instruccion "extra", tal ves sea por el pipeline y no tener intruccion-salto-intruccion-salto.

------------------------------------------------------------------------

Para probar el tema de que pasaria si tenemos realmente una funcion buena, voy a cambiar Explota() por :

Código: C
  1. void Explota(void)
  2. {
  3.         activarBomba = 0;
  4. }

Asi de esta forma no lo "optimiza" (es decir elimina por completo ) y ver si procede a dejar el if() esta ves.

Luego de compilado me encuentro con lo siguiente:
- La rutina de interrupcion no cambia.
- Explota() no aparece
- Solo cambio el main()

Código: ASM
  1. 000004f8 <main>:                                ; void main(void) {
  2.  4f8:   f240 2114       movw    r1, #532        ;
  3.  4fc:   2200            movs    r2, #0
  4.  4fe:   f2c2 0100       movt    r1, #8192       ;
  5.  502:   ea4f 0808       mov.w   r8, r8
  6.  506:   46c0            nop                     ;
  7.  508:   700a            strb    r2, [r1, #0]    ; while(1) { activaBomba = 0
  8.  50a:   7808            ldrb    r0, [r1, #0]    ; <- Toma directo de memoria
  9.  50c:   2800            cmp     r0, #0          ; if(activaBomba)
  10.  50e:   d0fb            beq.n   508 <main+0x10> ; Si es 0, vuelve al while(1)
  11.  510:   700a            strb    r2, [r1, #0]    ; activaBomba = 0; // Esto de Explota();
  12.  512:   e7f9            b.n     508 <main+0x10> ; } // Fin del while } Fin del main

Resultado: El optimizador hizo de Explota() una funcion inline. Es decir puso el activarBomba=0; en la rutina de main. Pero esta ves ahora si procede a realizarse el if.
Comprobando lo que habia dicho antes :P

Activar la optimizacion te puede borrar una funcion si no posee sentido. Volatile evita la optimizacion sobre la variable y por ende termina realizando lo que debe.
Ademas hace uso de mas registros del core, sin optimizacion se ve que no sale de R0 y R1, con optimizacion llego a usar R2 ( creo que hasta R7 usa con optimizacion si no mal recuerdo y hasta R3 sin optimizacion en programas mas demandantes ).
« Última modificación: 13 de Febrero de 2016, 14:20:40 por KILLERJC »

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re:Desreferenciando caracteres en una struct...
« Respuesta #31 en: 13 de Febrero de 2016, 01:59:46 »
Muy interesante KILLER...Si querés mudo esto a otro hilo para no ensuciarle más este a Leo.

Código: ASM
  1. 4e0:   f240 2114       movw    r1, #532        ;
  2. 4e4:   2001            movs    r0, #1
  3. 4e6:   f2c2 0100       movt    r1, #8192       ;

Pasa que movw carga sólo los 16 bits de la parte baja, y movt sólo los 16 bits de la parte baja de r1. Por ende el valor final del registro r1 sería: 0x20000214

Todavía te debo mis comentarios sobre las formas de lograr o no generar código seguro.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Desreferenciando caracteres en una struct...
« Respuesta #32 en: 13 de Febrero de 2016, 02:14:07 »
Citar
Si querés mudo esto a otro hilo para no ensuciarle más este a Leo.

Si Leo lo decide asi. Adelante. Sino seguimos, yo no tengo problemas para ir a cualquier lado.

Citar
Pasa que movw carga sólo los 16 bits de la parte baja, y movt sólo los 16 bits de la parte baja de r1. Por ende el valor final del registro r1 sería: 0x20000214

Exactamente, eso me pasa por no ponerme a ver las instrucciones. Las demas las tenia de memoria, pero esas no me acordaba exactamente que eran, hacia ya desde octubre que no tocaba el ASM de ARM ( http://www.todopic.com.ar/foros/index.php?topic=45280.0 )  , y no quise abrir el cheatsheet de las instrucciones. ahora que lo veo:

MOVT : Move Top , 16 bit parte alta
MOVW: Move Wide, 16 parte baja

Pense que iba a hacer uso de la flash para almacenar la direccion y tomarla con un offset, pero por velocidad (y tener a mano el set completo de Thumb-2 ) decidio ir por esa opcion.
Distinto hubiera sido en un M0+ que no soporta todo el set de Thumb-2 y como no puede cargar todo el literal, lo mejor seria tomarlo de la flash.

Del objdump:
Citar
20000214 g     O .data   00000001 .hidden activarBomba

Y en el micro que tengo la RAM esta mapeada de 0x2000.0000 a 0x2006.FFFF

Citar
Todavía te debo mis comentarios sobre las formas de lograr o no generar código seguro.

Cuando tengas tiempo, lo escribis. Mientras, yo espero  :D
« Última modificación: 13 de Febrero de 2016, 14:23:59 por KILLERJC »