Apunte c a bajo nivel - Empezando a programar PDF

Title Apunte c a bajo nivel - Empezando a programar
Author Marcos Goyret
Course Informática
Institution Universidad de Buenos Aires
Pages 16
File Size 348.6 KB
File Type PDF
Total Downloads 64
Total Views 164

Summary

Empezando a programar...


Description

Universidad de Buenos Aires Facultad De Ingenier´ıa

Programando en C a Bajo Nivel [75.40] Algoritmos y Programaci´on I 1er Cuatrimestre 2011 C´atedra: Ing. Pablo Guarna

Autor: Bernardo Ortega Moncada

Versi´on 3.0

Programando en C a Bajo Nivel

1er Cuatrimestre 2011

´Indice 1. Introducci´ on

2

2. Representaci´ on de N´ umeros en Base Binaria 2.1. Complementos A1 de un N´ umero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2

3. Sentencias Bit a Bit en C 3.1. Operaci´on AND (Bit a Bit) (&) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2. Operaci´on OR (Bit a Bit) (|) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3. Operaci´on XOR (bit a bit) ( ∧ ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4. Operaci´on Complemento A1 a la Base ( ∼ ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5. Desplazamiento de Bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.1. Desplazamiento de Bits a la Derecha ( >> ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.2. Desplazamiento de Bits a la Izquierda ( < < ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6. Operador Ternario (? :) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6.1. Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.7. Campos de Bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.7.1. Limitaciones de Campos de Bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.8. Ventajas y Desventajas de Operar Bit a Bit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3 4 5 5 6 6 7 7 8 8 9 9

4. El Preprocesador de C 4.1. ¿Que Es Un Macro? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2. Ejemplos de Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.1. Inclusi´on de Archivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.2. Creaci´on de Archivos de Cabecera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.3. Creaci´on de Macros como Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.4. Creaci´on de Macros como Funci´on . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3. Otras Directivas del Preprocesador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1. #undef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.2. #if , #else , #elif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.3. #error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4. Ventajas y Desventajas de Usar Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10 10 11 11 11 11 12 14 14 14 14 15

Autor: Bernardo Ortega Moncada

2 2

1

Programando en C a Bajo Nivel

1.

1er Cuatrimestre 2011

Introducci´ on

Este apunte esta orientado para que el lector pueda apreciar como uno puede trabajar en el lenguaje de programaci´on C con sentencias de Bajo Nivel y utilizar herramientas que pueden ser ´utiles a la hora de programar sentencias que podr´ıan simplificar lineas operando a bajo nivel. Este apunte es de car´ acter informativo, no significa que lo vayan a usar en esta materia, pero quiz´as en alguna posterior. Esta demas aclarar que para leer este apunte se necesita un conocimiento b´ asico previo del Lenguaje. Todas estas operaciones que se muestran en el apunte, tambi´en son v´alidas en el Lenguaje C++

2.

Representaci´ on de N´ umeros en Base Binaria

Como uno ya sabe, los n´ umeros en la computadora no se expresan de la misma forma que un ser humano escribe. Ya que la computadora trabaja de forma binaria y solo puede comprender si algo es verdadero o falso, si hay informaci´on o no, por lo tanto si uno esta trabajando con n´umeros que ocupan 1 Byte, uno sabe que 1 Byte esta compuesto por 8 bits, lo cual un bit solo puede almacenar 1 o 0. Por lo tanto si nosotros a modo de ejemplo tenemos el n´umero, la computadora ve a este n´ umero de la siguiente manera: Representaci´ on Decimal 0|10 2|10 7|10 25|10 255|10

Representaci´ on Binaria en 8 bits 00000000|2 00000010|2 00000111|2 00011001|2 11111111|2

= = = = =

Pero tenemos que saber que un n´ umero representado en binario posee 2 bits muy importantes. El bit mas Significativo (MSB, por sus siglas en ingles) y El Bit Menos Significativo (LSB, por sus siglas en ingles). Una observaci´on a tener en cuenta es que el MSB tambi´en es considerado Bit de Signo, siempre y cuando se use la representaci´ on MyBS (M´odulo y Bit de Signo). se considera al 1 como el signo negativo se considera al 0 como el signo positivo Por ejemplo, tenemos un numero representado en su forma binaria, podemos apreciar cuales son los bits significativos: 1 ↑ MSB

2.1.

0

0

1

0

1

0

1 ↑ LSB

Complementos A1 de un N´ umero

El complemento A1 de un numero representado en forma binaria, consiste en negar (o invertir) bit a bit la expresi´on del n´ umero, en lineas generales consiste en cambiar los 0’s por 1’s y viceversa. Esta herramienta es muy poderosa en el ´ambito de la computaci´ on ya que nos permite representar un n´umero de forma negativa, ya que como sabemos, la computadora no reconoce los n´ umeros negativos. Veamos el siguiente ejemplo de como calcular el complemento A1 a la base de un numero binario cualquiera: 01100100 ⇒

3.

|10011011 {z } Complemento A1

Sentencias Bit a Bit en C

Uno puede hacer una serie de operaciones l´ogicas bit a bit con el lenguaje C, e incluso realizar complementos A1, o desplazamientos de Bits a la derecha o a la izquierda. Estas operaciones son muy comunes en el lenguaje de bajo nivel denominado Assembler (Ensamblador). A continuaci´on se muestra una tabla con algunas de las operaciones a bajo nivel que podemos realizar:

Autor: Bernardo Ortega Moncada

2

Programando en C a Bajo Nivel

Operador & | ∧ ∼ >>

i n t main ( ) { cha r a = 2 3 ; cha r b = 9 0 ; cha r r e s u l t a d o ; printf ( ’ ’a = % d

b = % d ’ ’ ,a , b ) ;

resulta do = a & b ; p r i n t f ( ’ ’ R e s ulta do = % d ’ ’ , re s u l t a d o ) ; return 0; }

Una aplicaci´on u´til para este operador, es si queremos averiguar si un bit de cierto n´umero es 1 o 0, por ejemplo, se tiene el n´ umero a = 75 y se quiere averiguar si el cuarto bit de dicho n´umero es 1 o 0. Para eso tenemos que aplicar el operador & al n´ umero a con un n´ umero cuya representaci´on binaria sea 00001000, dicho n´ umero es el 8. Veamos como queda la operaci´on primero: 01001011 & 00001000 00001000 Entonces el c´odigo nos quedar´ıa de la siguiente forma: Autor: Bernardo Ortega Moncada

3

Programando en C a Bajo Nivel

1er Cuatrimestre 2011

Ejemplo2: Operaci´ on L´ ogica AND Bit a Bit

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

#i n c l u d e < s t d i o . h> i n t main ( ) { cha r a = 7 5 ; cha r b = 8 ; cha r r e s u l t a d o ; printf ( ’ ’a = % d

b = % d ’ ’ ,a , b ) ;

i f ( a & b) p r i n t f ( ’ ’ e l cu a rt o b i t de l a v a r i a b l e a e s 1 \ n ’ ’ ) ; else p r i n t f ( ’ ’ e l cu a rt o b i t de l a v a r i a b l e a e s 0 \ n ’ ’ ) ; return 0; }

3.2.

Operaci´ on OR (Bit a Bit) (|)

Si recordamos que la operaci´on OR (Bit a Bit) esta definida por la siguiente tabla de verdad: A 0 0 1 1

B 0 1 0 1

A|B 0 1 1 1

Como trabajamos con variables que ocupan 1 Byte (8 bits) la operaci´on AND Bit a Bit para estos casos se comportar´ıa de la siguiente manera: Supongamos que tenemos una variable a = 23 y otra variable b = 90, su representaci´on en binario de ambas seria: a = 00010111 y b = 01011010 por lo tanto: 00010111 | 01011010 01011111 El resultado nos da un n´ umero en binario cuya expresi´ on es 01011111|2 , que en decimal es conocido como 95|10 . Ejemplo: Operaci´ on L´ ogica OR Bit a Bit

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

#i n c l u d e < s t d i o . h> i n t main ( ) { cha r a = 2 3 ; cha r b = 9 0 ; cha r r e s u l t a d o ; printf ( ’ ’a = % d

b = % d ’ ’ ,a , b ) ;

resulta do = a | b ; p r i n t f ( ’ ’ R e s ulta do = % d ’ ’ , re s u l t a d o ) ; return 0; }

Autor: Bernardo Ortega Moncada

4

Programando en C a Bajo Nivel

3.3.

1er Cuatrimestre 2011

Operaci´ on XOR (bit a bit) ( ∧ )

Si recordamos que la operaci´on XOR (Bit a Bit) esta definida por la siguiente tabla de verdad: A 0 0 1 1

B 0 1 0 1

A∧B 0 1 1 0

Como trabajamos con variables que ocupan 1 Byte (8 bits) la operaci´on XOR Bit a Bit para estos casos se comportar´ıa de la siguiente manera: Supongamos que tenemos una variable a = 23 y otra variable b = 90, su representaci´on en binario de ambas seria: a = 00010111 y b = 01011010 por lo tanto: 00010111 ∧ 01011010 01001101 El resultado nos da un n´ umero en binario cuya expresi´ on es 01001101|2 , que en decimal es conocido como 77|10 . Ejemplo: Operaci´ on L´ ogica XOR Bit a Bit

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

#i n c l u d e < s t d i o . h> i n t main ( ) { cha r a = 2 3 ; cha r b = 9 0 ; cha r r e s u l t a d o ; printf ( ’ ’a = % d

b = % d ’ ’ ,a , b ) ;

resulta do = a ˆ b ; p r i n t f ( ’ ’ R e s ulta do = % d ’ ’ , re s u l t a d o ) ; return 0; }

3.4.

Operaci´ on Complemento A1 a la Base ( ∼ )

Supongamos que tenemos una variable a = 23 su representaci´on binaria seria: a = 00010111 por lo tanto: 00010111



11101000

El resultado nos da un n´ umero en binario cuya expresi´on es 11101000|2 , que en decimal es conocido como −24|10 . Hay que tener en cuenta que el MSB se considera como bit de signo Ejemplo: Complemento A1 a la base

1 #i n c l u d e < s t d i o . h> 2 3 i n t main ( ) 4 { 5 cha r a = 2 3 ; 6 cha r r e s u l t a d o ; 7 8 printf ( ’ ’a = % d ’ ’ ,a ); 9

Autor: Bernardo Ortega Moncada

5

Programando en C a Bajo Nivel

10 11 12 13 14 15 }

1er Cuatrimestre 2011

r e s u l t a d o = ˜a ; p r i n t f ( ’ ’ R e s ulta do = % d ’ ’ , re s u l t a d o ) ; return 0;

3.5.

Desplazamiento de Bits

Este tema no es facil de entender al principio, pero para que quede claro, uno puede hacer corrimientos de N Bits, con N ∈ N, es decir N = 1, 2, . . .. Esta operaci´on sirve b´asicamente para modificar un n´ umero a nivel Bit. Los corrimientos de Bits, pueden ser en dos direcciones: Corrimiento hacia la derecha Corrimiento hacia la izquierda 3.5.1.

Desplazamiento de Bits a la Derecha ( >> )

Supongamos que tenemos un Byte llamado a = 01101001 ⇒ 105|10 , a este n´ umero se le puede ser corrimientos de bits de la siguiente manera: N´ umero 01101001 01101001 01101001 01101001 01101001

Cantidad de Bits de Corrimiento 1 2 3 4 5

Resultado 00110100 ⇒ 52|10 00011010 ⇒ 26|10 00001101 ⇒ 13|10 00000110 ⇒ 6|10 00000011 ⇒ 3|10

Por lo tanto la funci´on para aplicarlo en el Lenguaje C, es: numero >> cantidad bits de corrimiento; Ejemplo: Desplazamiento a la Derecha de Bits

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

#i n c l u d e < s t d i o . h> i n t main ( ) { cha r a = 1 0 5 ; cha r r e s u l t a d o ; printf ( ’ ’a = % d ’ ’ ,a ); r e s u l t a d o = a >> 1 ; p r i n t f ( ’ ’ R e s ulta do = % d ’ ’ , re s u l t a d o ) /∗ imp rime 52 ∗/ ; r e s u l t a d o = a >> 2 ; p r i n t f ( ’ ’ R e s ulta do = % d ’ ’ , re s u l t a d o ) /∗ imp rime 26 ∗/ ; return 0; }

En pocas palabras, los corrimientos de Bits hacia la derecha, consisten en realizar la divisi´on Entera del n´ umero al cual se le realiza dicho corrimiento, es decir: numero >> cantidad bits de corrimiento; ≈ numero % (cantidad bits de corrimiento + 1);

Autor: Bernardo Ortega Moncada

6

Programando en C a Bajo Nivel

3.5.2.

1er Cuatrimestre 2011

Desplazamiento de Bits a la Izquierda ( < < )

Supongamos que tenemos un Byte llamado a = 01101001 ⇒ 105|10 , a este n´umero se le puede ser corrimientos de bits de la siguiente manera: 01101001 01101001 01101001 01101001 01101001

1 2 3 4 5

11010010 ⇒ 210|10 10100100 ⇒ 420|10 01001000 ⇒ 840|10 10010000 ⇒ 1680|10 00100000 ⇒ 3360|10

Nota: Pueden apreciar que los valores obtenidos en la base decimal no coinciden en lo absoluto con su representaci´ on binaria, esto se debe al overflow que existe al realizar un desplazamiento de bits, lo cual para realizar esto, hay que tener sumo cuidado!! Por lo tanto la funci´on para aplicarlo en el Lenguaje C, es: numero i n t main ( ) { cha r a = 1 0 5 ; cha r r e s u l t a d o ; printf ( ’ ’a = % d ’ ’ ,a ); r e s u l t a d o = a /∗ p ar a l o s a r c h i v o s de c a b e c e ra p r e d e f i n i d o s en C∗ / #i n c l u d e ‘ ‘ m i a r c h i v o c a b e c e r a . h ’ ’ /∗ pa ra l o s a r c h i v o s de c a b e c e r a c re a d os p or uno mismo ∗ / i n t main ( ) { p r i n t f ( ’ ’ Hola Mundo \n ’ ’ ) ; return 0; }

4.2.2.

Creaci´ on de Archivos de Cabecera

Uno puede crear sus propios archivos de cabecera para poder simplificar el c´odigo fuente en el archivo “main.c”, b´asicamente es el caso an´ alogo cuando uno creaba UNITS en PASCAL Para eso, utilizamos las siguientes sentencias: #ifndef (verifica si el macro no fue creado) #ifdef (verifica si el macro fue creado) #define (crea el macro) #include (si es necesario incluir otros archivos de cabecera) #endif (marca el fin de un #ifndef o #ifdef) lo cual para utilizarlo en el Lenguaje C, tenemos que crear un archivo “.h” : Ejemplo: Creaci´ on de un header file propio

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

/∗ s i no e s t a d e f i n i d o e l macro #i f n d e f MIARCHIVOCABECERA H #d e f i n e MIARCHIVOCABECERA H

MIARCHIVOCABECERA H , l o c r e a y l u e g o l la m a e l a r c h i v o s t d i o . h ∗ /

#i n c l u d e < s t d i o . h> /∗ i n c l u y o un a r c h i v o ∗ /

/∗ s i ya e s t a d e f i n i d o e l macro #i f d e f MIARCHIVOCABECERA H #i n c l u d e < s t d i o . h> #i n c l u d e < s t r i n g . h> #i n c l u d e #e n d i f /∗ f i n d e l #i f d e f ∗ /

MIARCHIVOCABECERA H , i n c l u y e mas a r c h i v o s ∗ /

/∗ ac a p uedo d e f i n i r t i p o s de d a t o s ∗ / /∗ ac a p uedo d e f i n i r l a s f i r m a s de f u n c i o n e s / p r o c e d i m i e n t o s ∗ / #e n d i f /∗ f i n d e l #i f n d e f ∗ /

4.2.3.

Creaci´ on de Macros como Constantes

Estos tipos de Macros son conocidos como Macro Objetos. Para poder definir un Macro Objeto en C, se tiene que tener presente como est´ a compuesto. Para eso, veamos la estructura “gen´erica” de un Macro Objeto:

Autor: Bernardo Ortega Moncada

11

Programando en C a Bajo Nivel

1er Cuatrimestre 2011

Estructura de un Macro Objeto

1 #d e f i n e

< l i s t a de t ok e ns a re em pl a z a r en e l codig o >

Veamos un ejemplo de como se construye un Macro Objeto: Ejemplo: Construcci´ on de un Macro Objeto

1 2 3 4 5 6 7 8 9 10 11

#i n c l u d e < s t d i o . h> #d e f i n e PI 3 .1 4159 #d e f i n e SALUDO ‘ ‘ Hola Mundo ’ ’ i n t main ( ) { p r i n t f ( ’ ’ % f ’ ’ , PI ) ; /∗ Es to imprime 3 .1 4 1 5 9 po r p a n t a l l a ∗ / p r i n t f (SALUDO) ; /∗ Es to imprime Ho la Mundo p or p a n t a l l a ∗ / return 0; }

Podemos apreciar que: es PI es 3.14159 En definitiva creamos un Macro Objeto llamado PI, que en cualquier parte del c´odigo donde aparezca “PI”, ser´a reemplazado por 3.14159. Esta ventaja de crear este tipo de Constantes, es que no ocupan lugar en memoria, sino que son reemplazados en tiempo de compilaci´on, haciendo que el programa sea un poco mas liviano!! 4.2.4.

Creaci´ on de Macros como Funci´ on

Estos tipos de Macros son conocidos como Macro Funciones (valga la redundancia). Para poder definir una Macro Funci´on en C, se tiene que tener presente como est´a compuesto. La estructura gen´erica de una Macro Funci´on no difiere casi en nada a la de un Macro Objeto, s´olo tiene una diferencia y es que toda sentencia dentro de una Macro Funci´on tiene que ir entre par´entesis ( ) aunque una gran ventaja es que pueden hacerse macros multilinea, es decir, que pueden hacer macros con mas de una linea de c´odigo, siempre y cuando antepongan el s´ımbolo “\” al final de cada linea. Veamos un ejemplo de como crear una Macro Funci´on, como por ejemplo, una Macro Funci´on que calcule si un n´ umero es mas grande que otro. Ejemplo: Construcci´ on de una Macro Funci´ on

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

#i n c l u d e < s t d i o . h> #d e f i n e MAX( a , b ) ( ( a > b ) ? a : b ) i n t main ( ) { i n t num1 ; i n t num2 ; pri ntf ( s ca nf ( ’ printf ( s ca nf ( ’

’ ’ i n g r e s e un numero \n ’ ’ ) ; ’ % d ’ ’ ,&num1 ) ; ’ ’ i n g r e s e o t r o numero \n ’ ’ ) ; ’ % d ’ ’ ,&num2 ) ;

p r i n t f ( ’ ’ El maximo e nt re % d y % d e s : % d \n ’ ’ , num1 , num2 ,MAX( num1 , num2 ) ) ; return 0; }

El u ´nico problema que presenta realizar una Macro Funci´on de esta manera, es que eval´ ua 2 veces a cualquiera de las 2 variables (en este caso a o b), dependiendo la condici´on que cumpla, lo cual no es del todo prolijo y hay que tener sumo cuidado cuando uno quiere hacer una Macro Funci´on que modifique una variable, ya que podr´ıa modificarla dos veces y no ser´ıa un resultado del todo agradable. Si se esta trabajando con ANSI C, este problema es inevitable, lo cual no hay manera de salvar este problema. Por lo tanto si se quiere realizar Macro Funciones en ANSI C, hay que tener mucho cuidado y pensarlo dos veces si esa funci´on conviene o no hacerla en Macro. Si se trabaja en otra estandarizaci´on de C, como por ejemplo C99, uno puede salvar este problema con una sentencia llamada “tipeof()”. Autor: Bernardo Ortega Moncada

12

Programando en C a Bajo Nivel

1er Cuatrimestre 2011

Dicha sentencia lo que hace es averiguar el tipo de dato que compone la variable que se le introduzca, y as´ı evita que haya una sobrevaluaci´on de dicha variable (igual a esto hay que tomarlo con pinzas, ya que le estar´ıamos quitando portabilidad al programa). Entonces el ejemplo anterior quedar´ıa como: Soluci´ on al problema

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

#i n c l u d e < s t d i o . h> #d e f i n e MAX( a , b ) \ ({ typeof ( a ) a = (a ); \ typeof (b) b = (b ); \ a > b ? a : b ; }) i n t main ( ) { i n t num1 ; i n t num2 ; pri ntf ( s ca nf ( ’ printf ( s ca nf ( ’

’ ’ i n g r e s e un numero \n ’ ’ ) ; ’ % d ’ ’ ,&num1 ) ; ’ ’ i n g r e s e o t r o numero \n ’ ’ ) ; ’ % d ’ ’ ,&num2 ...


Similar Free PDFs