Essa questão recente sobre assembly chamou minha atenção, não pelas instruções obviamente redundantes, mas pelas sys_write
saídas.
O programa tenta gerar todos os 256 caracteres ASCII e faz isso começando com ASCII 48, passando de 255 a 0 e terminando com 47.
A saída que o solicitante gentilmente fornece é:
└─$ ./example_displayascii
0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~��������������������������������������������������������������������������������������������������������������������������������
Eu poderia aceitar que os 128 códigos ASCII estendidos fossem impressos dessa forma, mas o que aconteceu com os códigos de 0 a 31, e especialmente os códigos de 32 a 47, que claramente devem ser caracteres imprimíveis!
Minhas perguntas:
- O que o Linux normalmente faz quando confrontado
sys_write
com os códigos (de controle) de 0 a 31? - E especificamente, o que acontece quando alguém termina uma linha com o par 10, 13 em vez do normal 10 apenas?
sys_write()
não interpreta os dados de forma alguma. No que lhe diz respeito, são apenas dados binários que ele passa para o driver do dispositivo.Alguns drivers de dispositivo podem processar os dados mais adiante antes de enviá-los ao dispositivo. Por exemplo, drivers de terminal tratam
\n
especialmente quandoONLCR
o modo é definido, traduzindo-o para\r\n
.Por padrão,
\r
não é processado especialmente. Então, se você escrever\n\r
, o que realmente será escrito é\r\n\r
.Existem alguns outros modos de saída que o driver do terminal obedece, que podem afetar outros caracteres de controle. Você pode ver uma lista completa em Modos de Saída na especificação POSIX. A maioria deles raramente é usada; por exemplo, todos os modos relacionados à adição de atrasos eram necessários para terminais de impressão que eram comuns na década de 1970, pois tinham pouco buffer e podiam descartar caracteres que eram recebidos enquanto esperavam o movimento do cabeçote de impressão.
Como os caracteres de controle são interpretados após serem escritos depende do próprio dispositivo terminal. A maioria dos caracteres de controle não tem significado especial para terminais e não produzirá nenhuma saída. Mas eu já vi terminais no passado que exibiriam um caractere contendo o código numérico.
A
write()
chamada do sistema é a mesma que você usa para escrever dados binários em arquivos não terminais. POSIXopen
/read
/write
/close
são como ISO Cfopen
/fread
/fwrite
/fclose
. As funções stdio do C apenas fazem buffering em torno das chamadas do sistema do mesmo nome. (E se qualquer tradução binária vs. texto acontecer, o que não acontece em um sistema POSIX como GNU/Linux, é nos wrappers stdio do C, não nas chamadas do sistema POSIX.)É assim que a saída se parece com o stdout conectado ao tty no Konsole, o emulador de terminal equivalente ao xterm do KDE no modo UTF-8, usando Monospace 12pt. (Arch GNU/Linux.) O XTerm e emuladores de terminal modernos como o Konsole e o GNOME-Terminal emulam basicamente um VT-100 .
Pressionei enter uma vez após executá-lo, pois ele deixou o cursor não no início de uma linha quando saiu, então há um espaço em branco na frente do primeiro prompt
bash
impresso. Usei o mouse para selecionar o prompt e o texto, mas não o prompt final que incluí na captura de tela; é por isso que o fundo é um cinza mais claro para essa parte. O espaço em branco brilhante à esquerda do primeiro prompt após a execução não foi devido à seleção do mouse, esse é um efeito real de algum caractere.Copiado/colado como texto (apenas da seleção do mouse da imagem anterior).
Interessante; até mesmo o espaço em branco brilhante é copiado. Eu não esperava que isso sobrevivesse ao copiar/colar e ao markdown do Stack Overflow.
Nada de especial em um terminal; CR envia o cursor para a coluna mais à esquerda, mas ele já estava lá depois de um LF (avanço de linha
\n
=10
).