[Revisión general del diseño y la aplicación de sistemas integrados]

Tabla de contenido

1. Asamblea

1.1 Ejemplos

1.1.1 En un determinado proyecto, se requiere establecer el valor de una variable entera cuya dirección absoluta es 0x987a a 0x3434. El compilador es un compilador ANSI puro. Escriba código para realizar esta tarea.

int *ptr;
ptr = (int *)0x987a;
*ptr = 0x3434;

1.1.2 Suponga que el valor de una variable entera cuya dirección absoluta es 0x9527 en un determinado sistema es 0x1633. Por favor escribe código para hacer esto.

int *ptr;
ptr = (int *)0x9527;
*ptr = 0x1633;

1.1.3 Escriba la instrucción ARM correspondiente al código C.

C代码:
if(a > b)
	a++;
else
	b++;

ARM指令:
CMP R0,R1        ; R0 与R1 比较
ADDHI R0,R0,#1        ; 若R0>R1,则R0=R0+1
ADDLS R1,R1,#1        ;若R0<=R1,则R1=R1+1
C代码为:
        If((a!=10)&&(b!=20))=a+b;
        
 对应的ARM 指令如下,其中R0 为a,R1为b。
        CMP R0,#10            ; 比较R0 是否为10
        CMPNE R1,#20        ; 若R0 不为10,则比较R1 是否20
        ADDNE R0,R0,R1        ; 若R0 不为10 且R1 不为20,指令执行,R0=R0+R1

1.1.4 Escriba las funciones de las siguientes instrucciones ARM.

MOV R1,#0x10; 				将0x10存入R1
MOV R0,R1; 					将R1内的数据存入R0
MOVS R3,R1,LSL #2; 	将R1内的数据左移两位后存入R3
MOV PC,LR; 					将LR 的值复制到 PC

1.1.5 Los bucles infinitos se utilizan a menudo en sistemas integrados, ¿cómo escribir bucles infinitos en lenguaje C?

while(1){}
for(;;){}
Loop:
...
goto Loop;

1.6 El siguiente código es una función de bucle C simple, que contiene una llamada de puntero de matriz en el bucle.

void increment(int *restrict b,    int *restrict c)
{
	int i;
	for(i = 0; i < 100; i++)
 {
 	c[i] = b[i] + 1;
 }
}

Vuelva a escribir el segmento de código anterior para lograr las siguientes funciones:
――El desenrollado de bucle 100 veces se convierte en 50 veces (desenrollado de bucle), lo que reduce el número de saltos
  ; Instrucciones;
  -- Se ajustó el orden de ejecución de diferentes operaciones de código, reduciendo el situación de estancamiento de la tubería;
  -- El bucle cambió de ++ bucle a -- bucle. De esta forma, se puede usar el bit de condición de la instrucción ARM y se reduce una instrucción de juicio para cada ciclo.

void increment(int *b, int *c)
{
	int i;
 int *pb, *pc;
 int b3, b4;
 pb = b - 1;
 pc = c - 1;
 b3 = pb[1];
 for (i = (100 / 2); i != 0; i--)
 {
 	b4 = *(pb += 2);
 	pc[1] = b3 + 1;
 	b3 = pb[1];
		*(pc += 2) = b4 + 1;
	}
} 

1.7 Suponga que la dirección IP de la placa de desarrollo ARM de destino es 192.168.1.166 y la dirección IP del host es 192.168.1.10. Primero escriba un programa en el host para ordenar 10 números enteros de mayor a menor (escriba el código fuente completo ). Luego describa brevemente el proceso de compilar el programa, descargarlo en la máquina de destino, modificar los permisos de archivo y ejecutar el programa.

#include <stdio.h> 
void main() 
{
	void sort(int x[ ],int n);   
  	int *p,i,a[10]; 
  	p=a; 
  	for(i=0;i<10;i++) 
  		scanf(“%d”,p++); 
  	p=a; 
   sort(p,10); 
   for(p=a,i=0;i<10;i++) 
   {
   		printf(“%d ”,*p);
   		 p++;
   	} 
   printf("\n");
} 
void sort(int x[],int n)  
{
	int i,j,k,t; 
  	for(i=0;i<n-1;i++) 
  	{
  		k=i; 
     	for(j=i+1;j<n;j++) 
       		if(x[j]>x[k]) 
       		k=j; 
           if(k!=i) 
			{
				t=x[i];
				x[i]=x[k];
				x[k]=t;
			} 
	}
} 

2. Clasificación de burbujas

2.1 Ejemplos

2.1.1 Use instrucciones en lenguaje ensamblador ARM para escribir un segmento de programa que implemente la función de clasificación de burbuja.

	AREA Sort,CODE,READONLY		;declare for code area
	ENTRY					;entry for the whole code
start						;main code flag
	MOV R4,#0				;clear r4
	LDR R6,=src				;r6 point to the begining of numbers
	ADD R6,R6,#len			;r6 point to the end of numbers  
outer					 	;outer loop begining
	LDR R1,=src				;r1 point to the begining of numbers 
inner						;inner loop begining
	LDR R2,[R1]				;get the number in address of r1
	LDR R3,[R1,#4]			;get the number in address next to r1
	CMP R2,R3				;compare two numbers we gotten
	STRGT R3,[R1]			;if the first > the second 
	STRGT R2,[R1,#4]			;exchange the position of two numbers
	ADD R1,R1,#4				;the point of r1 move
	CMP R1,R6				;compare position current  and ending
	BLT inner				;if not meet the ending go on to loop
	ADD R4,R4,#4				;global counter +1
	CMP R4,#len				;compare the current position
	SUBLE R6,R6,#4			;if not meet the ending
	BLE outer				;go on to loop
	AREA Array,DATA,READWRITE ;   decare for data area
src	DCD 2,4,10,8,14,1,20	  	;init the original numbers
len	EQU 7*4					;get the length of numbers
	END						;end of whole code

LDR
L significa que LOAD
se entiende como: Cargar desde la memoria al registro.
LDR R1, [R2]
R1 [registro] <——[R2] [memoria RAM]
copia el contenido de la memoria de R2 al registro R1.

Instrucción LDR:

Ejemplo 1: ldr r0, 0x12345678 // es almacenar el valor en la dirección 0x12345678 en r0. Y mov no puede hacer este trabajo, mov solo puede mover datos entre registros o mover datos inmediatos a registros.
Ejemplo 2: ldr r0, r1 // significa poner el valor en el registro r1 en r0
Ejemplo 3: ldr r0, [r1] // [r1] significa la dirección de la memoria correspondiente al valor en r1, entonces el número en r1 se usa como Crear una dirección, coloque el valor en esta dirección en r0.

Directiva LDR:

Ejemplo 1 (dato inmediato): ldr r0, =0x12345678
De esta forma se escribe en r0 la dirección 0x12345678. Por lo tanto, la pseudoinstrucción ldr es similar a mov. Es solo que la instrucción mov limita la longitud del valor inmediato a 8 bits, es decir, no puede exceder los 512. La directiva ldr no tiene esta limitación. Si se utiliza la pseudoinstrucción ldr, el valor inmediato que le sigue no supera los 8 bits, entonces la pseudoinstrucción ldr se convierte en una instrucción mov durante el ensamblado real. Ejemplo 2 (etiqueta): ldr r0, =_start: Asigne el valor de la etiqueta especificada a r0. Aquí se obtiene
la dirección absoluta de la etiqueta _start. Esta dirección absoluta (dirección de enlace) se determina durante la vinculación.
Ocupa dos espacios de 32 bits, uno es la instrucción y el otro es la dirección absoluta de _start almacenada en el grupo literal.
Aquí hay una comparación, adr r0, _start y ldr r0, =_start
tienen el mismo propósito, quieren darle la dirección de la etiqueta a r0, la diferencia es que una es una dirección relativa y la otra es una dirección absoluta. El propósito es el mismo, pero el resultado no es necesariamente el mismo. Si los resultados son los mismos depende de si el valor de la PC es el mismo que la dirección del enlace.

FUERZA

S significa ALMACENAR
se entiende como: Almacenar de un registro a memoria
STR R1, [R2]
R1 [registro] ——> [R2] memoria RAM]
copian el contenido del registro R1 a la memoria de R2.

LDM

El significado de L sigue siendo LOAD (copia mutua de registro de conexión y memoria continua)
entendido como: Carga de memoria en registro.
Aunque parece ser una actualización de LDR, debe tenerse en cuenta que la dirección de esta instrucción es diferente a la de LDR y se ejecuta de izquierda a derecha. Esta instrucción asigna los datos en la pila en la memoria al registro en lotes, es decir, la operación pop; el puntero de la pila generalmente corresponde a SP, tenga en cuenta que SP es el registro R13, pero la dirección de memoria en R13 se usa realmente, solo Esta instrucción no está escrita como [R13]. Al mismo tiempo, la ubicación del registro y la dirección de memoria en la instrucción LDM ha cambiado en relación con las dos instrucciones anteriores. Lo siguiente

Ejemplo:
LDMFD SP! , {R0, R1, R2}
en realidad puede entenderse como: LDMFD [SP]!, {R0, R1, R2}
significa: 3 segmentos de dirección consecutivos señalados por sp (debe ser 3*4 = 12 bytes (porque r0, r1 y r2 son todos de 32 bits)) copie los datos en los tres registros r0, r1 y r2 (si no entiende este lugar, puede consultar el principio de mi artículo. enlace con diagramas detallados)

STM

El significado de S sigue siendo STORE, y se usa en pares con LDM. Su formato de instrucción también es similar, es decir, es diferente de STR, y el puntero de pila está escrito a la izquierda, y el grupo de registros está escrito en la derecha.

STMFD SP!, {R0}
De manera similar, esta instrucción también puede entenderse como: STMFD [SP]!, {R0}
significa: guardar R0 en la pila (la dirección a la que apunta sp).
Obviamente, estas dos instrucciones de operación de pila también tienen una característica, es decir, el grupo de registros está escrito en la parte posterior (derecha) y el puntero de pila está escrito en el frente (izquierda), y en realidad usa la dirección de memoria en el puntero de pila, que es diferente de las dos Instrucciones anteriores se diferencian.

2.1.1 Escriba un programa en lenguaje C que implemente la ordenación de matrices y llame al segmento del programa de ordenación por burbuja escrito en lenguaje ensamblador.

int i, j, tmp;
int b[]={18,24,12,59,101,96,34};
for(i = 0; i < 6; i++)
{
	for(j = i + 1; j < 7 ; j++)
	{
		if(b[i] > b[j])
		{
			tmp = b[i];
			b[i] = b[j];
			b[j] = tmp;
		}
	}
}
i = 0;
while(i++ < 7)
	printf("%d ", b[i - 1]);
	
C语言调用汇编
#include<stdio.h>
extern viod Sort(int b[]);
int main()
{
   int b[]={18,24,12,59,101,96,34};
   Sort(int b[]);
}

3. Función de comando, resultado

3.1 Ejemplos

3.1.1 Escriba un archivo MAKE de acuerdo con los requisitos. Los requisitos incluyen: use el compilador cruzado arm-linux-gcc, el archivo de origen es led8.c, el archivo de destino es led8, use el archivo de encabezado led8.h y use las macro variables correspondientes.

CC		= arm-linux-gcc
INSTALL		= install
TARGET		= led8
all : $(TARGET)
$(TARGET): led8.c led8.h
	$(CC) -static $< -o $@
clean :
	rm -rf *.o $(TARGET) *~

3.1.2 Escriba un Makefile de acuerdo con los requisitos. Los requisitos incluyen: use el compilador cruzado arm-linux-gcc, el archivo de origen es helloworld.c, el archivo de destino es helloworld, use el archivo de encabezado cortexa8.h e incluya operación limpia.

CC		= arm-linux-gcc 
INSTALL		= install
TARGET		= helloworld 
all : $(TARGET)
$(TARGET): helloworld.c cortexa8.h 
	$(CC) -static $< -o $@
clean :
	rm -rf *.o $(TARGET) *~ 

Acho que você gosta

Origin blog.csdn.net/weixin_51911075/article/details/129161125
Recomendado
Clasificación