mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Format markdown
This commit is contained in:
@@ -30,12 +30,12 @@ Este blog se desarrolla abiertamente en [GitHub]. Si tienes algún problema o pr
|
|||||||
## El Buffer de Texto VGA
|
## El Buffer de Texto VGA
|
||||||
Para imprimir un carácter en la pantalla en modo de texto VGA, uno tiene que escribirlo en el buffer de texto del hardware VGA. El buffer de texto VGA es un arreglo bidimensional con típicamente 25 filas y 80 columnas, que se renderiza directamente en la pantalla. Cada entrada del arreglo describe un solo carácter de pantalla a través del siguiente formato:
|
Para imprimir un carácter en la pantalla en modo de texto VGA, uno tiene que escribirlo en el buffer de texto del hardware VGA. El buffer de texto VGA es un arreglo bidimensional con típicamente 25 filas y 80 columnas, que se renderiza directamente en la pantalla. Cada entrada del arreglo describe un solo carácter de pantalla a través del siguiente formato:
|
||||||
|
|
||||||
Bit(s) | Valor
|
| Bit(s) | Valor |
|
||||||
------ | ----------------
|
| ------ | --------------------- |
|
||||||
0-7 | Código de punto ASCII
|
| 0-7 | Código de punto ASCII |
|
||||||
8-11 | Color de primer plano
|
| 8-11 | Color de primer plano |
|
||||||
12-14 | Color de fondo
|
| 12-14 | Color de fondo |
|
||||||
15 | Parpadeo
|
| 15 | Parpadeo |
|
||||||
|
|
||||||
El primer byte representa el carácter que debe imprimirse en la [codificación ASCII]. Para ser más específicos, no es exactamente ASCII, sino un conjunto de caracteres llamado [_página de códigos 437_] con algunos caracteres adicionales y ligeras modificaciones. Para simplificar, procederemos a llamarlo un carácter ASCII en esta publicación.
|
El primer byte representa el carácter que debe imprimirse en la [codificación ASCII]. Para ser más específicos, no es exactamente ASCII, sino un conjunto de caracteres llamado [_página de códigos 437_] con algunos caracteres adicionales y ligeras modificaciones. Para simplificar, procederemos a llamarlo un carácter ASCII en esta publicación.
|
||||||
|
|
||||||
@@ -44,16 +44,16 @@ El primer byte representa el carácter que debe imprimirse en la [codificación
|
|||||||
|
|
||||||
El segundo byte define cómo se muestra el carácter. Los primeros cuatro bits definen el color de primer plano, los siguientes tres bits el color de fondo, y el último bit si el carácter debe parpadear. Los siguientes colores están disponibles:
|
El segundo byte define cómo se muestra el carácter. Los primeros cuatro bits definen el color de primer plano, los siguientes tres bits el color de fondo, y el último bit si el carácter debe parpadear. Los siguientes colores están disponibles:
|
||||||
|
|
||||||
Número | Color | Número + Bit de Brillo | Color Brillante
|
| Número | Color | Número + Bit de Brillo | Color Brillante |
|
||||||
------ | ---------- | ---------------------- | -------------
|
| ------ | ---------- | ---------------------- | --------------- |
|
||||||
0x0 | Negro | 0x8 | Gris Oscuro
|
| 0x0 | Negro | 0x8 | Gris Oscuro |
|
||||||
0x1 | Azul | 0x9 | Azul Claro
|
| 0x1 | Azul | 0x9 | Azul Claro |
|
||||||
0x2 | Verde | 0xa | Verde Claro
|
| 0x2 | Verde | 0xa | Verde Claro |
|
||||||
0x3 | Cian | 0xb | Cian Claro
|
| 0x3 | Cian | 0xb | Cian Claro |
|
||||||
0x4 | Rojo | 0xc | Rojo Claro
|
| 0x4 | Rojo | 0xc | Rojo Claro |
|
||||||
0x5 | Magenta | 0xd | Magenta Claro
|
| 0x5 | Magenta | 0xd | Magenta Claro |
|
||||||
0x6 | Marrón | 0xe | Amarillo
|
| 0x6 | Marrón | 0xe | Amarillo |
|
||||||
0x7 | Gris Claro | 0xf | Blanco
|
| 0x7 | Gris Claro | 0xf | Blanco |
|
||||||
|
|
||||||
Bit 4 es el _bit de brillo_, que convierte, por ejemplo, azul en azul claro. Para el color de fondo, este bit se reutiliza como el bit de parpadeo.
|
Bit 4 es el _bit de brillo_, que convierte, por ejemplo, azul en azul claro. Para el color de fondo, este bit se reutiliza como el bit de parpadeo.
|
||||||
|
|
||||||
|
|||||||
@@ -46,28 +46,28 @@ Para ver la lista completa de excepciones, consulte la [wiki de OSDev][exception
|
|||||||
### La tabla de descriptores de interrupción
|
### La tabla de descriptores de interrupción
|
||||||
Para poder capturar y manejar excepciones, tenemos que configurar una llamada _tabla de descriptores de interrupción_ (IDT). En esta tabla, podemos especificar una función manejadora para cada excepción de CPU. El hardware utiliza esta tabla directamente, por lo que necesitamos seguir un formato predefinido. Cada entrada debe tener la siguiente estructura de 16 bytes:
|
Para poder capturar y manejar excepciones, tenemos que configurar una llamada _tabla de descriptores de interrupción_ (IDT). En esta tabla, podemos especificar una función manejadora para cada excepción de CPU. El hardware utiliza esta tabla directamente, por lo que necesitamos seguir un formato predefinido. Cada entrada debe tener la siguiente estructura de 16 bytes:
|
||||||
|
|
||||||
Tipo| Nombre | Descripción
|
| Tipo | Nombre | Descripción |
|
||||||
----|--------------------------|-----------------------------------
|
| ---- | ------------------------- | ----------------------------------------------------------------------- |
|
||||||
u16 | Puntero a función [0:15] | Los bits más bajos del puntero a la función manejadora.
|
| u16 | Puntero a función [0:15] | Los bits más bajos del puntero a la función manejadora. |
|
||||||
u16 | Selector GDT | Selector de un segmento de código en la [tabla de descriptores global].
|
| u16 | Selector GDT | Selector de un segmento de código en la [tabla de descriptores global]. |
|
||||||
u16 | Opciones | (ver abajo)
|
| u16 | Opciones | (ver abajo) |
|
||||||
u16 | Puntero a función [16:31] | Los bits del medio del puntero a la función manejadora.
|
| u16 | Puntero a función [16:31] | Los bits del medio del puntero a la función manejadora. |
|
||||||
u32 | Puntero a función [32:63] | Los bits restantes del puntero a la función manejadora.
|
| u32 | Puntero a función [32:63] | Los bits restantes del puntero a la función manejadora. |
|
||||||
u32 | Reservado |
|
| u32 | Reservado |
|
||||||
|
|
||||||
[tabla de descriptores global]: https://en.wikipedia.org/wiki/Global_Descriptor_Table
|
[tabla de descriptores global]: https://en.wikipedia.org/wiki/Global_Descriptor_Table
|
||||||
|
|
||||||
El campo de opciones tiene el siguiente formato:
|
El campo de opciones tiene el siguiente formato:
|
||||||
|
|
||||||
Bits | Nombre | Descripción
|
| Bits | Nombre | Descripción |
|
||||||
------|-----------------------------------|-----------------------------------
|
| ----- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||||
0-2 | Índice de tabla de pila de interrupción | 0: No cambiar pilas, 1-7: Cambiar a la n-ésima pila en la Tabla de Pila de Interrupción cuando se llama a este manejador.
|
| 0-2 | Índice de tabla de pila de interrupción | 0: No cambiar pilas, 1-7: Cambiar a la n-ésima pila en la Tabla de Pila de Interrupción cuando se llama a este manejador. |
|
||||||
3-7 | Reservado |
|
| 3-7 | Reservado |
|
||||||
8 | 0: Puerta de interrupción, 1: Puerta de trampa | Si este bit es 0, las interrupciones están deshabilitadas cuando se llama a este manejador.
|
| 8 | 0: Puerta de interrupción, 1: Puerta de trampa | Si este bit es 0, las interrupciones están deshabilitadas cuando se llama a este manejador. |
|
||||||
9-11 | debe ser uno |
|
| 9-11 | debe ser uno |
|
||||||
12 | debe ser cero |
|
| 12 | debe ser cero |
|
||||||
13‑14 | Nivel de privilegio del descriptor (DPL) | El nivel mínimo de privilegio requerido para llamar a este manejador.
|
| 13‑14 | Nivel de privilegio del descriptor (DPL) | El nivel mínimo de privilegio requerido para llamar a este manejador. |
|
||||||
15 | Presente |
|
| 15 | Presente |
|
||||||
|
|
||||||
Cada excepción tiene un índice de IDT predefinido. Por ejemplo, la excepción de código de operación inválido tiene índice de tabla 6 y la excepción de fallo de página tiene índice de tabla 14. Así, el hardware puede cargar automáticamente la entrada de IDT correspondiente para cada excepción. La [Tabla de Excepciones][exceptions] en la wiki de OSDev muestra los índices de IDT de todas las excepciones en la columna “Vector nr.”.
|
Cada excepción tiene un índice de IDT predefinido. Por ejemplo, la excepción de código de operación inválido tiene índice de tabla 6 y la excepción de fallo de página tiene índice de tabla 14. Así, el hardware puede cargar automáticamente la entrada de IDT correspondiente para cada excepción. La [Tabla de Excepciones][exceptions] en la wiki de OSDev muestra los índices de IDT de todas las excepciones en la columna “Vector nr.”.
|
||||||
|
|
||||||
@@ -162,10 +162,10 @@ En contraste, una función llamada puede sobrescribir registros _de uso_ sin res
|
|||||||
|
|
||||||
En x86_64, la convención de llamada C especifica los siguientes registros preservados y de uso:
|
En x86_64, la convención de llamada C especifica los siguientes registros preservados y de uso:
|
||||||
|
|
||||||
registros preservados | registros de uso
|
| registros preservados | registros de uso |
|
||||||
---|---
|
| ----------------------------------------------- | ----------------------------------------------------------- |
|
||||||
`rbp`, `rbx`, `rsp`, `r12`, `r13`, `r14`, `r15` | `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`, `r10`, `r11`
|
| `rbp`, `rbx`, `rsp`, `r12`, `r13`, `r14`, `r15` | `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`, `r10`, `r11` |
|
||||||
_guardados por el llamado_ | _guardados por el llamador_
|
| _guardados por el llamado_ | _guardados por el llamador_ |
|
||||||
|
|
||||||
El compilador conoce estas reglas, por lo que genera el código en consecuencia. Por ejemplo, la mayoría de las funciones comienzan con un `push rbp`, que respalda `rbp` en la pila (porque es un registro guardado por el llamado).
|
El compilador conoce estas reglas, por lo que genera el código en consecuencia. Por ejemplo, la mayoría de las funciones comienzan con un `push rbp`, que respalda `rbp` en la pila (porque es un registro guardado por el llamado).
|
||||||
|
|
||||||
|
|||||||
@@ -127,10 +127,10 @@ Por ejemplo, ¿qué ocurre si:
|
|||||||
|
|
||||||
Afortunadamente, el manual de AMD64 ([PDF][AMD64 manual]) tiene una definición exacta (en la Sección 8.2.9). Según él, una “excepción de doble fallo _puede_ ocurrir cuando una segunda excepción ocurre durante el manejo de un controlador de excepción previo (primera)”. El _“puede”_ es importante: Solo combinaciones muy específicas de excepciones conducen a un doble fallo. Estas combinaciones son:
|
Afortunadamente, el manual de AMD64 ([PDF][AMD64 manual]) tiene una definición exacta (en la Sección 8.2.9). Según él, una “excepción de doble fallo _puede_ ocurrir cuando una segunda excepción ocurre durante el manejo de un controlador de excepción previo (primera)”. El _“puede”_ es importante: Solo combinaciones muy específicas de excepciones conducen a un doble fallo. Estas combinaciones son:
|
||||||
|
|
||||||
Primera Excepción | Segunda Excepción
|
| Primera Excepción | Segunda Excepción |
|
||||||
------------------|------------------
|
| ------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
[División por cero],<br>[TSS No Válido],<br>[Segmento No Presente],<br>[Fallo de Segmento de Pila],<br>[Fallo de Protección General] | [TSS No Válido],<br>[Segmento No Presente],<br>[Fallo de Segmento de Pila],<br>[Fallo de Protección General]
|
| [División por cero],<br>[TSS No Válido],<br>[Segmento No Presente],<br>[Fallo de Segmento de Pila],<br>[Fallo de Protección General] | [TSS No Válido],<br>[Segmento No Presente],<br>[Fallo de Segmento de Pila],<br>[Fallo de Protección General] |
|
||||||
[Fallo de Página] | [Fallo de Página],<br>[TSS No Válido],<br>[Segmento No Presente],<br>[Fallo de Segmento de Pila],<br>[Fallo de Protección General]
|
| [Fallo de Página] | [Fallo de Página],<br>[TSS No Válido],<br>[Segmento No Presente],<br>[Fallo de Segmento de Pila],<br>[Fallo de Protección General] |
|
||||||
|
|
||||||
[División por cero]: https://wiki.osdev.org/Exceptions#Division_Error
|
[División por cero]: https://wiki.osdev.org/Exceptions#Division_Error
|
||||||
[TSS No Válido]: https://wiki.osdev.org/Exceptions#Invalid_TSS
|
[TSS No Válido]: https://wiki.osdev.org/Exceptions#Invalid_TSS
|
||||||
@@ -218,15 +218,15 @@ En `x86_64`, la TSS ya no contiene ninguna información específica de tarea. En
|
|||||||
|
|
||||||
La TSS de 64 bits tiene el siguiente formato:
|
La TSS de 64 bits tiene el siguiente formato:
|
||||||
|
|
||||||
Campo | Tipo
|
| Campo | Tipo |
|
||||||
------ | ----------------
|
| --------------------------------------------- | ---------- |
|
||||||
<span style="opacity: 0.5">(reservado)</span> | `u32`
|
| <span style="opacity: 0.5">(reservado)</span> | `u32` |
|
||||||
Tabla de Pilas de Privilegio | `[u64; 3]`
|
| Tabla de Pilas de Privilegio | `[u64; 3]` |
|
||||||
<span style="opacity: 0.5">(reservado)</span> | `u64`
|
| <span style="opacity: 0.5">(reservado)</span> | `u64` |
|
||||||
Tabla de Pila de Interrupciones | `[u64; 7]`
|
| Tabla de Pila de Interrupciones | `[u64; 7]` |
|
||||||
<span style="opacity: 0.5">(reservado)</span> | `u64`
|
| <span style="opacity: 0.5">(reservado)</span> | `u64` |
|
||||||
<span style="opacity: 0.5">(reservado)</span> | `u16`
|
| <span style="opacity: 0.5">(reservado)</span> | `u16` |
|
||||||
Dirección Base del Mapa de E/S | `u16`
|
| Dirección Base del Mapa de E/S | `u16` |
|
||||||
|
|
||||||
La _Tabla de Pilas de Privilegio_ es usada por la CPU cuando cambia el nivel de privilegio. Por ejemplo, si ocurre una excepción mientras la CPU está en modo usuario (nivel de privilegio 3), la CPU normalmente cambia a modo núcleo (nivel de privilegio 0) antes de invocar el controlador de excepciones. En ese caso, la CPU cambiaría a la 0ª pila en la Tabla de Pilas de Privilegio (ya que 0 es el nivel de privilegio de destino). Aún no tenemos programas en modo usuario, así que ignoraremos esta tabla por ahora.
|
La _Tabla de Pilas de Privilegio_ es usada por la CPU cuando cambia el nivel de privilegio. Por ejemplo, si ocurre una excepción mientras la CPU está en modo usuario (nivel de privilegio 3), la CPU normalmente cambia a modo núcleo (nivel de privilegio 0) antes de invocar el controlador de excepciones. En ese caso, la CPU cambiaría a la 0ª pila en la Tabla de Pilas de Privilegio (ya que 0 es el nivel de privilegio de destino). Aún no tenemos programas en modo usuario, así que ignoraremos esta tabla por ahora.
|
||||||
|
|
||||||
|
|||||||
@@ -277,16 +277,16 @@ pub fn _print(args: fmt::Arguments) {
|
|||||||
|
|
||||||
Bloquea el `WRITER`, llama a `write_fmt` en él y lo desbloquea implícitamente al final de la función. Ahora imagina que una interrupción ocurre mientras `WRITER` está bloqueado y el manejador de interrupciones intenta imprimir algo también:
|
Bloquea el `WRITER`, llama a `write_fmt` en él y lo desbloquea implícitamente al final de la función. Ahora imagina que una interrupción ocurre mientras `WRITER` está bloqueado y el manejador de interrupciones intenta imprimir algo también:
|
||||||
|
|
||||||
Timestep | _start | manejador_interrupcion
|
| Timestep | _start | manejador_interrupcion |
|
||||||
---------|------|------------------
|
| -------- | ------------------------ | -------------------------------------------------------------- |
|
||||||
0 | llama a `println!` |
|
| 0 | llama a `println!` | |
|
||||||
1 | `print` bloquea `WRITER` |
|
| 1 | `print` bloquea `WRITER` | |
|
||||||
2 | | **ocurre la interrupción**, el manejador comienza a ejecutarse
|
| 2 | | **ocurre la interrupción**, el manejador comienza a ejecutarse |
|
||||||
3 | | llama a `println!` |
|
| 3 | | llama a `println!` |
|
||||||
4 | | `print` intenta bloquear `WRITER` (ya bloqueado)
|
| 4 | | `print` intenta bloquear `WRITER` (ya bloqueado) |
|
||||||
5 | | `print` intenta bloquear `WRITER` (ya bloqueado)
|
| 5 | | `print` intenta bloquear `WRITER` (ya bloqueado) |
|
||||||
… | | …
|
| … | | … |
|
||||||
_nunca_ | _desbloquear `WRITER`_ |
|
| _nunca_ | _desbloquear `WRITER`_ |
|
||||||
|
|
||||||
El `WRITER` está bloqueado, así que el manejador de interrupciones espera hasta que se libere. Pero esto nunca sucede, porque la función `_start` solo continúa ejecutándose después de que el manejador de interrupciones regrese. Así, todo el sistema se cuelga.
|
El `WRITER` está bloqueado, así que el manejador de interrupciones espera hasta que se libere. Pero esto nunca sucede, porque la función `_start` solo continúa ejecutándose después de que el manejador de interrupciones regrese. Así, todo el sistema se cuelga.
|
||||||
|
|
||||||
|
|||||||
@@ -204,21 +204,21 @@ Como se indica por el atributo `repr`, las tablas de páginas necesitan estar al
|
|||||||
|
|
||||||
Cada entrada tiene un tamaño de 8 bytes (64 bits) y tiene el siguiente formato:
|
Cada entrada tiene un tamaño de 8 bytes (64 bits) y tiene el siguiente formato:
|
||||||
|
|
||||||
Bit(s) | Nombre | Significado
|
| Bit(s) | Nombre | Significado |
|
||||||
------ | ---- | -------
|
| ------ | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
0 | presente | la página está actualmente en memoria
|
| 0 | presente | la página está actualmente en memoria |
|
||||||
1 | escribible | se permite escribir en esta página
|
| 1 | escribible | se permite escribir en esta página |
|
||||||
2 | accesible por el usuario | si no se establece, solo el código en modo núcleo puede acceder a esta página
|
| 2 | accesible por el usuario | si no se establece, solo el código en modo núcleo puede acceder a esta página |
|
||||||
3 | caché de escritura a través | las escrituras van directamente a la memoria
|
| 3 | caché de escritura a través | las escrituras van directamente a la memoria |
|
||||||
4 | desactivar caché | no se utiliza caché para esta página
|
| 4 | desactivar caché | no se utiliza caché para esta página |
|
||||||
5 | accedido | la CPU establece este bit cuando se utiliza esta página
|
| 5 | accedido | la CPU establece este bit cuando se utiliza esta página |
|
||||||
6 | sucio | la CPU establece este bit cuando se realiza una escritura en esta página
|
| 6 | sucio | la CPU establece este bit cuando se realiza una escritura en esta página |
|
||||||
7 | página enorme/null | debe ser 0 en P1 y P4, crea una página de 1 GiB en P3, crea una página de 2 MiB en P2
|
| 7 | página enorme/null | debe ser 0 en P1 y P4, crea una página de 1 GiB en P3, crea una página de 2 MiB en P2 |
|
||||||
8 | global | la página no se borra de las cachés al cambiar el espacio de direcciones (el bit PGE del registro CR4 debe estar establecido)
|
| 8 | global | la página no se borra de las cachés al cambiar el espacio de direcciones (el bit PGE del registro CR4 debe estar establecido) |
|
||||||
9-11 | disponible | puede ser utilizado libremente por el sistema operativo
|
| 9-11 | disponible | puede ser utilizado libremente por el sistema operativo |
|
||||||
12-51 | dirección física | la dirección física alineada de 52 bits del marco o de la siguiente tabla de páginas
|
| 12-51 | dirección física | la dirección física alineada de 52 bits del marco o de la siguiente tabla de páginas |
|
||||||
52-62 | disponible | puede ser utilizado libremente por el sistema operativo
|
| 52-62 | disponible | puede ser utilizado libremente por el sistema operativo |
|
||||||
63 | no ejecutar | prohibir la ejecución de código en esta página (el bit NXE en el registro EFER debe estar establecido)
|
| 63 | no ejecutar | prohibir la ejecución de código en esta página (el bit NXE en el registro EFER debe estar establecido) |
|
||||||
|
|
||||||
Vemos que solo los bits 12–51 se utilizan para almacenar la dirección física del marco. Los bits restantes se utilizan como banderas o pueden ser utilizados libremente por el sistema operativo. Esto es posible porque siempre apuntamos a una dirección alineada a 4096 bytes, ya sea a una tabla de páginas alineada a la página o al inicio de un marco mapeado. Esto significa que los bits 0–11 son siempre cero, por lo que no hay razón para almacenar estos bits porque el hardware puede simplemente configurarlos en cero antes de usar la dirección. Lo mismo es cierto para los bits 52–63, ya que la arquitectura x86_64 solo admite direcciones físicas de 52 bits (similar a como solo admite direcciones virtuales de 48 bits).
|
Vemos que solo los bits 12–51 se utilizan para almacenar la dirección física del marco. Los bits restantes se utilizan como banderas o pueden ser utilizados libremente por el sistema operativo. Esto es posible porque siempre apuntamos a una dirección alineada a 4096 bytes, ya sea a una tabla de páginas alineada a la página o al inicio de un marco mapeado. Esto significa que los bits 0–11 son siempre cero, por lo que no hay razón para almacenar estos bits porque el hardware puede simplemente configurarlos en cero antes de usar la dirección. Lo mismo es cierto para los bits 52–63, ya que la arquitectura x86_64 solo admite direcciones físicas de 52 bits (similar a como solo admite direcciones virtuales de 48 bits).
|
||||||
|
|
||||||
|
|||||||
@@ -172,13 +172,13 @@ Ahora podemos calcular direcciones virtuales para las tablas de los cuatro nivel
|
|||||||
|
|
||||||
La tabla a continuación resume la estructura de la dirección para acceder a los diferentes tipos de marcos:
|
La tabla a continuación resume la estructura de la dirección para acceder a los diferentes tipos de marcos:
|
||||||
|
|
||||||
Dirección Virtual para | Estructura de Dirección ([octal])
|
| Dirección Virtual para | Estructura de Dirección ([octal]) |
|
||||||
------------------- | -------------------------------
|
| --------------------------- | --------------------------------- |
|
||||||
Página | `0o_SSSSSS_AAA_BBB_CCC_DDD_EEEE`
|
| Página | `0o_SSSSSS_AAA_BBB_CCC_DDD_EEEE` |
|
||||||
Entrada de Tabla de Nivel 1 | `0o_SSSSSS_RRR_AAA_BBB_CCC_DDDD`
|
| Entrada de Tabla de Nivel 1 | `0o_SSSSSS_RRR_AAA_BBB_CCC_DDDD` |
|
||||||
Entrada de Tabla de Nivel 2 | `0o_SSSSSS_RRR_RRR_AAA_BBB_CCCC`
|
| Entrada de Tabla de Nivel 2 | `0o_SSSSSS_RRR_RRR_AAA_BBB_CCCC` |
|
||||||
Entrada de Tabla de Nivel 3 | `0o_SSSSSS_RRR_RRR_RRR_AAA_BBBB`
|
| Entrada de Tabla de Nivel 3 | `0o_SSSSSS_RRR_RRR_RRR_AAA_BBBB` |
|
||||||
Entrada de Tabla de Nivel 4 | `0o_SSSSSS_RRR_RRR_RRR_RRR_AAAA`
|
| Entrada de Tabla de Nivel 4 | `0o_SSSSSS_RRR_RRR_RRR_RRR_AAAA` |
|
||||||
|
|
||||||
[octal]: https://en.wikipedia.org/wiki/Octal
|
[octal]: https://en.wikipedia.org/wiki/Octal
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user