dal 2015 - visita n. 2627
ColoriMacro
ColoriMacro

 

I colori sul terminale e le macro


Gli esercizi di questa sezione hanno un duplice scopo:


Il primo problema lo risolviamo con le sequenze di escape. In sostanza inviando una stringa opportuna al terminale è possibile reimpostare gli attributi colore. Questa stringa, in particolare, che chiameremo foba (foreground background) è composta da 9 byte ed ha la seguente struttura:


1Bh5Bh33h----3Bh34h----6Dh00h
esc[3 ;4 mnull
012345678

I byte nelle posizioni 3 e 6 rappresentano i colori di foreground e di background rispettivamente, e vanno impostati secondo la seguente tabella:


30h0nero
31h1rosso
32h2verde
33h3ocra
34h4blu
35h5fucsia
36h6celeste
37h7bianco


Ad esempio per impostare i colori rosso/blu (rosso su fondo blu) occorrerà definire una stringa che contenga in posizione 3 il byte 31h ed in posizione 6 il byte 34h, come illustrato di seguito:

	foba	db 1Bh,5Bh,33h,31h,3Bh,34h,34h,6Dh,00h
oppure
	foba	db 1Bh,"[31;44m",0


Tornando al problema del testo colorato sul terminale, una prima soluzione viene proposta nel listato seguente nel quale sono presenti delle macro sviluppate nell'ultimo listato. Per mia convenzione, i nomi delle macro asm iniziano con il carattere @ in modo che sia facile individuarle nel listato del programma. Si noti la presenza della direttiva %include che consente l'aggancio del file con le macro.

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
; txtcol_1.asm 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;compilare con nasm+gcc

%include "macrobase.mac"

global	main
extern  printf

section .data
foba	db 1Bh,"[37;40m",0
cls     db 1Bh,"[2J",1Bh,"[1;1f",0
crlf	db 0Dh,0Ah,0
msg20 	db "Scritta in verde su fondo nero",0
msg02 	db "Scritta in nero su fondo verde",0
msg71 	db "Scritta in bianco su fondo rosso",0

section .text
main: 	@outterm   cls			; Clear del terminale
	
	@fixcol    2,0			; Imposta Verde/Nero
	@outterm   msg20		; Emette Messaggio
	@outterm   crlf			; Ritorno a capo
	
	@fixcol    0,2			; Imposta Nero/Verde
	@outterm   msg02	
	@outterm   crlf
	
	@fixcol    7,1			; Imposta Bianco/Rosso
	@outterm   msg71	
	@outterm   crlf
	
	@fixcol	   7,0			; Ripristina Bianco/Nero
    	ret
; EOF ::::::::::::::::::::::::::::::::::::::::::::::::::::::


La prima delle macro utilizzate, @fixcol, imposta i colori attivi e necessita di 2 parametri che rappresentano ordinatamente il codice colore di foreground e quello di background. La seconda macro, @outterm, serve ad emettere un messaggio di tipo AsciiZ presente come unico parametro.
Si noti nell'area dati la presenza di un'altra stringa di sequenze di escape, cls la quale serve ad effettuare il clear dello schermo ("[2J") ed il riposizionamento del cursore in alto a sinistra ("[1;1f").
Una normalissima stringa AsciiZ, crlf, serve infine per comandare il ritorno a capo tramite una @outterm.

La seconda soluzione del problema viene proposta con l'uso delle syscall e quindi le due macro precedenti, che facevano uso della printf, sono state modificate in @fixcol2 e @outterm2, in modo da essere indipendenti dalla libc. La compilazione può pertanto essere effettuata con l'uso del linker ld. Il programa segue, per il resto, l'impostazione di quello precedente.

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
; txtcol_2.asm 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;compilare con nasm+ld

%define STDOUT 1
%define SYSCALL_EXIT  1
%define SYSCALL_WRITE 4

%include "macrobase.mac"

global  _start				;necessario per il linker ld

	section .data
foba	db 1Bh,"[37;40m",0
cls     db 1Bh,"[2J",1Bh,"[1;1f",0
crlf	db 0Dh,0Ah,0
msg20 	db "Scritta in verde su fondo nero",0
msg02 	db "Scritta in nero su fondo verde",0
msg71 	db "Scritta in bianco su fondo rosso",0

	section .text
_start: 
	@outterm2 cls			; Clear del terminale
	
	@fixcol2  2,0			; Imposta Verde/Nero
	@outterm2 msg20			; Emette Messaggio
	@outterm2 crlf			; Ritorno a capo
	
	@fixcol2  0,2			; Imposta Nero/Verde
	@outterm2 msg02	
	@outterm2 crlf
	
	@fixcol2  7,1			; Imposta Bianco/Rosso
	@outterm2 msg71	
	@outterm2 crlf
	
	@fixcol2  7,0			; Ripristina Bianco/Nero
	@exit     0			; uscita normale, code=0
; EOF ::::::::::::::::::::::::::::::::::::::::::::::::::::::


Ecco una immagine della schermata che si ottiene con i programmi presentati in questa sezione.



Ed, in ultimo, il listato delle macro utilizzate dai programmi precedenti e che viene collegato tramite la direttiva %include "macrobase.mac"

.

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
; macrobase.mac
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

%macro	@outterm  1
	push 	  dword %1		;Passa il Ptr Stringa
    	call 	  printf
	add       esp,4			;Riallinea lo Stack
%endmacro

%macro	@fixcol   2
	mov	  byte [foba+3],%1+30h
	mov	  byte [foba+6],%2+30h
	@outterm  foba
%endmacro

%macro	@fixcol2  2
	mov	  byte [foba+3],%1+30h
	mov	  byte [foba+6],%2+30h
	@outterm2 foba
%endmacro

%macro	@outterm2 1
        mov     ecx, %1			; Puntatore stringa AsciiZ
	mov	esi,ecx			; Utilizza Puntatore esi per usare la lodsb
	xor	edx,edx			; Azzera contatore lunghezza (edx)
	dec	edx			; 
%%lp:	inc	edx
	lodsb
	or	al,al
	jnz	%%lp
        mov     eax, SYSCALL_WRITE      ; write function
        mov     ebx, STDOUT             ; Arg1: file descriptor
        int     80h                     ; syscall kernel to write
%endmacro

%macro	@exit	  1
	mov       EBX, %1               ; exit code=%1
        mov       EAX, SYSCALL_EXIT     ; exit function
        int       80h                   ; syscall kernel to take over
%endmacro
;EOF :::::::::::::::::::::::::::::::::::::::::::::::::::


Si noti nella @outterm2 la presenza di una etichetta (label) locale %%lp contrassegnata dal prefisso %%. Una tale scelta evita errori, in compilazione, quando la macro viene usata più di una volta.
Nella @outterm2 viene effettuato il calcolo della lunghezza della stringa, passata come parametro in edx, dal momento che la SYSCALL_WRITE vuole in edx proprio questo valore.



Complementi

Con le sequenze di escape è, però, possibile aggiungere una serie di attributi per migliorare ancora di più l'output a colori. Per raggiungere lo scopo guardiamo il parametro colore di foreground come fosse un byte strutturato nella maniera seguente:


BHRUIcBcGcR
76543210

I bit di posto 0,1,2 (cR,cG,cB) determinano il colore secondo la classica tripletta RGB. Gli altri bit costituiscono attributi aggiuntivi che vanno opportunamente interpretati.


Ad esempio, per ottenere un colore ocra intenso (giallo) e sottolineato il byte dovrà essere così impostato:



00011011
76543210

valore che sarà passato come parametro colore di foreground in una qualunque base numerica: 00011011b, 1Bh, 27 comprensibile dall'assemblatore.

La nuova macro @fixcol3 che interpreterà questo byte avrà il compito di comporre una precisa sequenza di escape di lunghezza variabile in funzione degli attributi aggiunti alla tripletta RGB. La macro utilizzerà una nuova stringa dati chiamata fobax, che conterrà al suo interno:


L'attivazione di ciascun attributo comporta l'aggiunta delle seguenti coppie di byte/carattere alla sequenza di escape:

I:	db  3Bh,31h	o	db  ";1"	o	dw  313Bh
U:	db  3Bh,34h	o	db  ";4"	o	dw  343Bh
R:	db  3Bh,37h	o	db  ";7"	o	dw  373Bh
H:	db  3Bh,38h	o	db  ";8"	o	dw  383Bh
B:	db  3Bh,35h	o	db  ";5"	o	dw  353Bh

L'intera sequenza dovrà essere chiusa da:

	db  6Dh,0	o	db  "m",0	o	dw  006Dh

Ecco la macro @fixcol3 che realizza l'interprete del parametro colore foreground:

%macro	@fixcol3  2
        mov	  al,%1			;;Lettura parametro foreground
	mov	  ah,al			;;Impostazione colore foreground
	and 	  ah,07h
	add	  ah,30h
	mov	  [foba+3],ah
	mov	  byte [foba+6],%2+30h	;;Impostazione colore background
	mov	  esi,7			;;Inizio Interprete attributi
	test	  al,08h		;;Test su "I"
	mov	  bx,313Bh
	call      %%work
	test	  al,10h		;;Test su "U"
	mov	  bx,343Bh
	call      %%work
	test	  al,20h		;;Test su "R"
	mov	  bx,373Bh
	call      %%work
	test	  al,40h		;;Test su "H"
	mov	  bx,383Bh
	call      %%work
	test	  al,80h		;;Test su "B"
	mov	  bx,353Bh
	call      %%work
	jmp	  %%exit
;.......................................;;Routine accodamento
%%work: jz	  %%wxit		;;Esce se Test=0
	mov	  [foba+esi],bx		;;Accoda bx, se Test=1
	add	  esi,2
%%wxit:	ret
;.......................................
%%exit: mov	  bx,006Dh		;;Chiusura Sequenza Escape
	mov	  [foba+esi],bx
 	@outterm2 fobax			;;Emissione Sequenza
%endmacro

Inserendo la macro @fixcol3 nel file macrobase.mac è possibile compilare il programmino di prova txtcol_3.asm riportato di seguito.

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
; txtcol_3.asm 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;compilare con nasm+ld

%define STDOUT 1
%define SYSCALL_EXIT  1
%define SYSCALL_WRITE 4

%include "macrobase.mac"

global  _start				;necessario per il linker ld

	section .data
fobax   db 1Bh,"[0m"	
foba	db 1Bh,"[37;40m",0,0,0,0,0,0,0,0,0,0,0
cls     db 1Bh,"[2J",1Bh,"[1;1f",0
crlf	db 0Dh,0Ah,0
msg20 	db "Scritta in giallo sottolineato su fondo nero",0

	section .text
_start: 
	@outterm2 cls			; Clear del terminale
	
	@fixcol3  00011011b,0		; Imposta colori e attributi
	@outterm2 msg20			; Emette Messaggio
	@outterm2 crlf			; Ritorno a capo
	
	@fixcol3  7,0			; Ripristina Bianco/Nero
exit:   mov       EBX, 0                ; exit code, normal=0
        mov       EAX, SYSCALL_EXIT     ; exit function
        int       80h                   ; syscall kernel to take over

;::::::::::::::::::::::::::::::::::::::








Menù
Introduzione
I registri del Pentium
Il modello della memoria
Interazione CPU-RAM
I Servizi Linux - Int 80h
I File in Linux
Schema programma NASM
Esempi Write/Read
Esercizi
lods-stos-movs
gcc + nasm
Gestione Command Line
Stack
Stack-Esercizi
Libreria Funzioni Base
Esercizi con la Libreria
Libreria Macro Base
Test 5 esercizi


Sistemi di numerazione
Elementi Bistabili
Strutture di Controllo
Istruzioni JMP
Hello World
I/O di Testo
Command Line
Colori e Macro
Introduzione I/O
Porta Parallela


AppuntiAsm-386.html
Linux ELF Howto
Linux Assembly Howto
Il linguaggio PC Assembly
Assembly di Paul A.Carter
Assembly di Claudio Daffra



Quando non si ha ciò che si ama, bisogna amare quel che si ha.
Roger de Bussy-Rabutin

Valid CSS!
pagina generata in 0.005 secondi