Aunque las instrucciones de bucle en la imagen no están claras

1

En un esfuerzo por ahorrar espacio, trato de reducir el código C generado con inline asm (""); Mirando el desmontaje original y el buen código de trabajo no entiendo la línea 0x17E4.

nulo MENU_BUTTON (uchar Parm) {

    // This loop ends when the enter key is pressed
    while EnterOpen(){                 // SW3 = RE2

       if ArrowUpClosed(){             //    RE0 
           while ArrowUpClosed(){};
            asm("call MBD");
            if ArrowUpOpen()       
                  LCDGotoPos(ArrowUp[index]);
        };
        if ArrowDownClosed(){          // SW3 RE1
            while ArrowDownClosed(){};
            asm("call MBD");
            if ArrowDownOpen()
                 LCDGotoPos(ArrowDown[index]);
        };
        if ArrowRightClosed(){          // SW4 RC1
            while ArrowRightClosed(){};
            asm("call MBD");
            if ArrowRightOpen()
                   LCDGotoPos(ArrowRight[index]);
        };
        if ArrowLeftClosed(){           // SW5 RC0
            while ArrowLeftClosed(){};
            asm("call MBD");
            if ArrowLeftOpen()
                   LCDGotoPos(ArrowLeft[index]);
        };
    };
    Pause(300);
    return;
    // a little trick to save space
    asm("MBD:");
    delay();
}; // End of MenuButtons.


    // This loop ends when the enter key is pressed
    while EnterOpen(){                 // RE2
    0x178E: BCF STATUS, 0x5
    0x178F: BCF STATUS, 0x6
    0x1790: BTFSS PORTE, 0x2
    // jumping out of the loop as expected
    0x1791: GOTO 0x7E5    
    // returns to the beginning? but during execution goes to 0x1792.
    // The way I expect
    0x17E4: GOTO 0x78E                 
    // during execution 
    //if ArrowUpClosed()             //   RE0 
    0x1792: BTFSC PORTE, 0x0

    //other code
    } // end of while EnterOpen

    //    Pause(300);
    0x17E5: MOVLW 0x8
    
pregunta Decapod

1 respuesta

2

Advertencias: Ha pasado más de una década desde que habitualmente escribí el código de ensamblaje PIC (y utilicé su compilador de C; tampoco estoy seguro de si mi licencia ya es válida). Tampoco dijo qué compilador es. Usando, así que no puedo ir a buscar una copia y ver qué genera. Y ni siquiera sé si está usando un PIC16 o un PIC18 (diferentes criaturas, con el PIC18 con mejores arreglos para el código de ensamblaje). Finalmente, asumo que usted está bastante al tanto de las cosas con el PIC y eso en algunos aspectos. maneras en que podrá responder a preguntas específicas sobre su código de ensamblaje debido a su trabajo actual en comparación con mi conocimiento de hace una década (y más).

Suposiciones:

  1. Es una parte de la familia PIC16 (o inferior) y no un PIC18.
  2. Cuando escribe el código de ensamblaje, está utilizando un ensamblador real y no un código de máquina de codificación manual.
  3. No has estado observando de cerca el código de máquina generado.
  4. La confusión no declarada está sobre la dirección allí.

Suponiendo que los anteriores sean correctos, sospecho que puede haber perdido la atención de que la instrucción GOTO solo usa 11 bits para la dirección. Solo se puede bifurcar dentro de la "página" del código actual, donde los bits de la dirección superior permanecen sin cambios en la bifurcación a una nueva dirección.

Cuando escribes en ensamblaje, usualmente usas etiquetas. Incluso si usó direcciones absolutas, el ensamblador sigue haciendo "la matemática" para asegurarse de que la dirección que especifique esté "al alcance". De modo que ni siquiera sabrías de una manera u otra lo que está pasando a menos que observes detenidamente el código de máquina que genera.

Permítame documentar lo que veo arriba (junto con una columna faltante que sinceramente deseo que también incluyera también ):

Address    Machine Code    Code Lines             Description
0x178E                     BCF STATUS, 0x5        These two lines make sure that data access
0x178F                     BCF STATUS, 0x6            is on page 0 where PORTE is at.
0x1790                     BTFSS PORTE, 0x2       Skip GOTO if the loop should continue.
0x1791                     GOTO 0x7E5             Go out of loop to 0x17E5 (past the GOTO.)
0x1792                     BTFSC PORTE, 0x0       "if ArrowUpClosed()"
0x1793                                            <>
0x1794                                            <>
  ...                                             ...
0x17E1                                            <>
0x17E2                                            <>
0x17E3                                            <>
0x17E4                     GOTO 0x78E             Branch to address 0x178E (start of loop.)
0x17E5                     MOVLW 0x8

Si observa que solo hay 11 bits en la instrucción de máquina codificada para el GOTO, entonces puede ver por qué el "0x17E5" o "0x178E" completo no se puede codificar en la palabra de la máquina. Sin embargo, ese hecho no impide que el ensamblador y / o el compilador sepan que la dirección puede ser alcanzada correctamente (o no, lo que indica que se necesita más código para hacer una transferencia más distante).

El código del compilador funciona, creo que dices. También dice que cuando escribió un código de ensamblaje propio, también funcionó. Creo que ambos son ciertos. Pero el problema puede ser simplemente que no te has dado cuenta de cómo funciona un ensamblador (lo que es más importante, cómo funciona un enlazador) para generar el código correcto o generar errores.

El ensamblador y el compilador de C generarán un archivo de objeto que contiene lo que equivale a "cadenas" de valores de byte literales + registros de "parche" periódicos que instruyen al enlazador exactamente dónde y exactamente cómo corregir bits y piezas de esos literales cadenas, durante la fase de vinculación cuando el código realmente se coloca en algún lugar. Para el código generado por el ensamblaje, estoy bastante seguro de que este es un proceso muy simple y el vinculador se quejará si escribe instrucciones que requieran una codificación fuera de rango. Para el compilador de C, no estoy tan seguro de la complejidad que se extiende al enlazador. Pero es posible que el compilador de C no quiera preocuparse acerca de si un poco de código se extiende a través de una página de códigos y en su lugar simplemente proporciona al enlazador suficiente información adicional para que el enlazador pueda hacer la determinación y "extenderse automáticamente" una cadena de bytes según sea necesario (lo que hace que el proceso de vinculación sea más complejo pero también lleva a una menor confusión del codificador C típico).

He tenido mi opinión al respecto. Podría ser que malinterpreté totalmente tu dilema aquí. Acabo de despertarme y quién sabe si estoy caminando dormido a través de esto. Pero ahí está. ¿Quizás podrías aclarar el dispositivo, etc., también?

Para aquellos interesados en alguna historia sobre el compilador XC8 C, así como también información sobre las diferencias de optimización en las versiones PRO, encontré este enlace inmediatamente útil. Por eso, puedo ver que el compilador XC8 es básicamente el código del compilador Hi-Tech, con "impedimentos" adicionales para "mejorar" las motivaciones para comprar la versión PRO de su conjunto de herramientas del compilador. Interesantes detalles allí.

    
respondido por el jonk

Lea otras preguntas en las etiquetas