Ultimamente, tenho tentado aprender um pouco de programação de Embedded / Assembly aqui, além de tentar aprender o nível mais baixo (portões e outros).
Uma coisa me intriga ... é como "obtemos" conjuntos de instruções. Eu entendo um pouco como portões / TTL e tais obras, mas não vejo como chegamos a partir disso para mover, adicionar, clr etc ...?
Provavelmente é uma pergunta estúpida ... mas, quero dizer, penso nos primeiros microprocessadores / controladores e penso ... como exatamente eles projetaram um conjunto de instruções e o fizeram funcionar?
edit: Eu acho que para o Clarity, finjo que estou falando sobre o primeiro microprocessador, como eles passaram do binário para realmente criar um conjunto de instruções?
Respostas:
O coração de uma CPU é a ALU . Ele é responsável por executar uma instrução (como MOV), que é apenas uma série predefinida de dígitos binários, além de levar 0, 1 ou 2 operandos e executar a operação aplicável neles. A instrução mais simples pode ser um NOP (nenhuma operação) que essencialmente não faz nada. Outra operação típica é ADD (adiciona dois valores).
A ALU lê e grava dados de e para "registradores". Esses são pequenos locais de memória internos à CPU. Parte da instrução (2 a 3 bits para cada entrada, dependendo de quantos registros você possui) indica qual registro deve ser lido. Existem unidades na CPU externa à ALU que manipulam o carregamento dos dados necessários (e as instruções) da memória para os registradores e gravam o resultado dos registradores novamente na memória. O local para escrever o resultado também será codificado em outros 2 ou 3 bits.
A escolha de "códigos op", que é o número binário que representa uma operação, não é arbitrária. Opcodes bem escolhidos reduzem a complexidade da ALU. Cada bit ou grupo de bits tende a ativar e desativar determinadas portas lógicas na ALU. Por exemplo, uma instrução ADD teria que habilitar o estágio de saída para escolher o resultado da lógica de adição interna. Da mesma forma, uma instrução MUL escolheria o resultado da lógica de multiplicação. Dependendo do design, é bem provável que os circuitos somador e multiplicador realizem sua operação nos operandos de entrada, e é apenas a seleção de saída (o que é gravada nos bits de saída da ALU) que muda.
fonte
Aceitarei sua pergunta literalmente e discutirei principalmente microprocessadores, não computadores em geral.
Todos os computadores possuem algum tipo de código de máquina. Uma instrução consiste em um código de operação e um ou mais operandos. Por exemplo, a instrução ADD para o Intel 4004 (o primeiro microprocessador) foi codificada como 1000RRRR, onde 1000 é o código de operação para ADD e RRRR representou um número de registro 0-15 (0000-1111 em binário).
Todas as outras instruções que fazem referência a um dos 16 registradores de 4 bits (como INC, ISZ, LD, SUB, XCHG) também usam os 4 bits baixos para codificar o número do registro e várias codificações dos 4 bits principais para especificar o código de operação. Por exemplo, ADD, SUB, LD e XCHG usam os códigos de opção 1000, 1001, 1010 e 1011 (todos em binário) combinados com o campo de registro. Assim, você pode ver como um padrão é usado para simplificar a lógica.
Os primeiros programas de computador foram escritos à mão, codificando manualmente os zeros e zeros para criar um programa em linguagem de máquina. Este foi então programado em uma ROM (memória somente leitura). Agora, os programas geralmente são gravados em memória Flash apagável eletricamente, no caso de microcontroladores, ou ficam sem memória RAM, se forem microprocessadores. (O último ainda precisa de algum tipo de memória somente leitura para inicializar.)
A linguagem de máquina torna-se entediante rapidamente, e por isso foram desenvolvidos programas assembler que pegam uma linguagem assembler mnemônica e a traduzem, geralmente uma linha de código de montagem por instrução, em código de máquina. Então, em vez de 10000001, escreveríamos ADD R1.
Mas o primeiro montador teve que ser escrito em código de máquina. Em seguida, ele poderia ser reescrito em seu próprio código assembler e a versão em linguagem de máquina usada para montá-lo pela primeira vez. Depois disso, o programa pode se montar (isso é chamado de inicialização).
Como o primeiro microprocessador foi desenvolvido muito tempo após a instalação de mainframes e minicomputadores, e o 4004 não era realmente adequado para executar um assembler, a Intel provavelmente escreveu um assembler que rodava em um de seus grandes computadores e traduziu o código do assembly para o 4004 em uma imagem binária que pode ser programada nas ROMs.
fonte
Um computador em um nível muito baixo pode ser representado por um caminho e controle de dados . Pesquisá-los juntos no Google pode oferecer muita leitura, pois é fundamental na arquitetura / design digital.
Eu farei o meu melhor para resumir:
Como mencionado aqui, no coração temos uma ALU - o que precisa ser conhecido sobre a ALU (e outras partes da CPU) é que ela é reconfigurável para diferentes operações. Mais especificamente, temos a capacidade de reconfigurar o caminho dos dados , que é como os parâmetros são buscados, qual operação fazer e onde são armazenados posteriormente. Imagine ser capaz de manipular essas três coisas - esse é o nosso controle .
Então, como fazemos isso? Como já mencionado novamente, podemos tirar proveito da lógica digital de baixo nível e criar multiplexadores para diferentes caminhos. Os multiplexadores são controlados usando um conjunto de bits para entrada - de onde são retirados esses bits? Codificado a partir das próprias instruções. A dica: Instruções como mov, add, etc são apenas um conjunto de bits que informam à CPU como configurar seu caminho de dados para uma operação específica. O que você está lendo (mov, add) é a forma legível por humanos (linguagem assembly) e nosso programa define um procedimento de caminhos de dados e operações.
Peço desculpas se isso é uma simplificação excessiva de processos mais complexos para aqueles que têm mais conhecimento nessa área. Para sua informação, a troca de pilhas da engenharia elétrica seria um ótimo local para fazer essa pergunta, pois lida com uma lógica de nível muito baixo.
fonte
se entendi sua pergunta, não entendo como bin / hex ou assembly estão relacionados.
Eu suponho que a questão da sua pergunta é como chego dos portões básicos, AND, OR, NOT a instruções como mover, carregar, armazenar, adicionar, etc.
Eu tenho meu próprio conjunto de instruções de ensino que criei do zero, com alguns detalhes de como adicionar e subtrair funcionam de portas básicas e coisas assim http://github.com/dwelch67/lsasim .
Procure o livro Code (something something something) da Petzold. Pode começar do básico ao básico, mas você caminha lentamente do nada para computadores e eletrônicos até o binário, o hex e os portões básicos, etc.
Você está perguntando sobre como construir uma do zero hoje, ou como eles fizeram isso no passado? Hoje você começaria com uma definição do conjunto de instruções. você apenas senta e escreve, pensa nos tipos de instruções que você deve ter, carrega, armazena, move e tudo, e depois quantos registros, qual o tamanho dos registros, isso afeta em parte o tamanho das instruções, você acha sobre o tamanho da instrução ...
Deixe-me parar e perguntar como você escreve um programa? Começando com uma tela em branco em um editor de texto? Você tem alguma idéia da tarefa que está tentando resolver as variáveis de que precisa, as funções, a linguagem de programação etc. um pouco disso (tornar os arquivos de cabeçalho com definições e enumerações reutilizáveis e estruturas e outras coisas) e um pouco da outra coisa (apenas código, preencha as funções com variáveis e código). E você circula pelas diferentes tarefas; no final, sente que possui um equilíbrio de tamanho de código, velocidade, legibilidade, qualidade, funcionalidade etc. Não é diferente no design de hardware. os designers de hardware também usam linguagens de programação (vhdl, verilog) e passam pelo mesmo processo,
Assim como a criação de um programa de software, você equilibra os desejos, o desempenho, o tamanho, os recursos, etc. Você pode ter algumas regras de design impostas a você, que você queria ou que seu chefe o fez fazer, etc. No design inicial da implementação, você pode descobrir que possui alguns erros grandes e precisar voltar ao design inicial e alterar o conjunto de instruções, grandes ou pequenas alterações. Pode chegar ao ponto de ter um compilador e um processador simulado para descobrir que você realmente precisava de algumas instruções específicas que melhoram drasticamente a qualidade do código compilado, do desempenho etc.
Então, você inventou algumas instruções definidas do zero, usou alguma experiência com o design de hardware para agrupar instruções semelhantes com padrões de bits semelhantes, para que possam ser decodificadas com mais facilidade, não apenas para a programação da linguagem de hardware, mas economizando energia e portas e tudo o mais. coisa boa. Hoje em dia você faria algum tipo de simulador, meu entendimento é que o ARM era um simulador de software primeiro e depois os designs de hardware vieram depois, não sei se isso é verdade, mas continuo com essa história. Isso depende da equipe em que algumas equipes podem ser apenas pessoas de hardware e querem apenas entrar em programação no hdl, algumas como eu podem querer fazer um pouco de ambas. Atualmente, existem bons simuladores de linguagem de hardware, para que você não precise construir nenhum hardware que compile e simule e faça grande parte da sua depuração com um programa / pacote de simulação de hardware. a equipe de software pode desenvolver montadores e compiladores para o conjunto de instruções e usar programas de alimentação ram e rom simulados para o processador simulado e testá-lo. simulamos uma inicialização completa do linux em um processador em que trabalhei há pouco tempo, levamos muitas horas, mas funcionou (encontrei um bug de cache na lógica dessa maneira).
Então agora, pelo que eu realmente acho que você estava perguntando. Como você passa dos portões básicos para um processador com um conjunto de instruções. Os portões básicos E, OU, NÃO são realmente analógicos, eles não têm um conceito de tempo, você não pode mudar instantaneamente a tensão nas entradas e, à medida que muda a tensão, as saídas começam a mudar. as portas são feitas de transistores e os transistores são amplificadores, multiplicam a entrada por algum número e permitem que tanta corrente flua do outro lado. quando os usamos como portas lógicas, na verdade, estamos super saturando-os, a tensão de entrada é tão alta ou baixa que o transistor só pode acionar tensão máxima ou nenhuma tensão (corrente). basicamente o transitor é transformado em um interruptor. Para encurtar a história, não há conceito de tempo. Para ter um conjunto de instruções, precisamos que as instruções aconteçam para que possamos sequenciar o programa, precisamos ter um conceito de que agora estamos nessa instrução e, no próximo intervalo de tempo, trabalharemos nessa instrução. Assim como o jogo de transformar um amplificador em um interruptor, você joga jogos semelhantes usando portas lógicas básicas com um relógio. os relógios vêm de cristais mágicos em uma lata (não vale a pena entrar aqui) que produzem voltagens que se acendem e se apagam a uma taxa fixa. use essa tensão nas equações lógicas e você poderá começar a sequenciar as coisas. os relógios vêm de cristais mágicos em uma lata (não vale a pena entrar aqui) que produzem voltagens que se acendem e se apagam a uma taxa fixa. use essa tensão nas equações lógicas e você poderá começar a sequenciar as coisas. os relógios vêm de cristais mágicos em uma lata (não vale a pena entrar aqui) que produzem voltagens que se acendem e se apagam a uma taxa fixa. use essa tensão nas equações lógicas e você poderá começar a sequenciar as coisas.
pense muito brevemente nesta tabela de verdade:
em binário:
concentrando-se apenas no lsbit, um somador de um bit, a tabela verdade acima descreve um somador de um bit. Também descreve um portão XOR. Uma entrada é verdadeira ou a outra, mas não ambas.
Para obter mais de um bit, é necessário observar os bits de transporte transportados e executados e é necessário um somador de três bits, dois operandos e um transporte com duas saídas, carry e resultado. Depois de ter esses três somadores de entrada e dois de saída, você pode fazer a cascata da largura que desejar. Mas isso ainda é analógico, os portões mudam instantaneamente.
Como você transforma esse somador analógico em uma instrução ADD, você tem alguma lógica que analisa a instrução que está como entrada para esses portões que você organizou. alguns bits da instrução dizem que esta é uma instrução add, outros dizem que um operando é esse e tal registro, talvez o registro 7, outros bits podem dizer que o outro operando é o registro 4. e, dependendo da arquitetura que você pode ter outro registro definido na instrução que diz colocar o resultado no registro 2. Agora, mais lógica vê isso, pois preciso que o conteúdo do registro 7 seja roteado para uma entrada do alu adder e as entradas do registro 4 sejam roteadas para o adicionador, e você encaminha a saída do somador para registrar 2. Como o relógio faz parte dessa lógica, existe um período de tempo desde o início do período do relógio até o início do próximo período do relógio, onde todos os sinais analógicos se acalmam e resolvem a equação lógica a que estão conectados. Não muito diferente de quando você liga um interruptor, você muda o estado das luzes de dizer desligado para ligado. leva um período de tempo para que a luz aqueça e, basicamente, entre em estado estacionário. Não é muito diferente aqui.
Existe alguma lógica que diz coisas como se esse período de clock for a fase de execução de uma instrução AND, no próximo período de clock eu salvarei o resultado no registro de saída. ao mesmo tempo, buscarei a próxima instrução, etc. Portanto, para processadores modernos em que a execução de alu geralmente é apenas um período de relógio, porque a lógica analógica pode resolver as equações lógicas tão rapidamente. Os processadores mais antigos que você teve que contar até certo número deixam o somador conectado, aguarde x número de ciclos de clock para que a lógica do somador resolva; em seguida, faça uma amostra do resultado da saída, alimente as entradas diferentes de alu, aguarde x número de ciclos de clock por para resolver, repita para sempre ou até que a energia se apague.
O que quero dizer com equações lógicas? apenas que, se você quiser, pode pensar nisso em termos de portas AND, OR, NOT. Para cada bit de entrada no circuito do somador, existe uma equação, provavelmente uma equação muito longa que inclui o relógio, que inclui os chinelos (bits de memória individuais / únicos) que contêm a instrução atual (mais as equações que alimentam cada um desses bits de memória) e assim por diante. Tome uma única função de software que você escreveu, no idioma em que a escreveu, assumindo que essa é uma função que recebe as entradas, executa uma tarefa e, em seguida, finaliza e retorna um resultado. Pense em todas as combinações possíveis de entradas e quais são os diferentes caminhos de execução por meio dessa função. Você pode ter escrito em alguma linguagem de alto nível, mas provavelmente poderia reescrevê-la para ser mais primitiva e mais primitiva usando muitas estruturas aninhadas se-então-outro. e desça para a linguagem assembly talvez. Não muito diferente das equações de que estou falando, o programador de hardware não programa nessas equações muito longas, assim como você provavelmente não programa em árvores se-então-muito longas na linguagem assembly, quando a linguagem de programação escolhida economiza muito disso. Assim como o compilador que você usa transforma seu pequeno código-fonte em um conjunto longo e cheio de argumentos, existe um compilador que pega o código da linguagem de programação de hardware e o transforma em equações lógicas.
Agora voltando ao primeiro processador (que hoje consideraríamos um microcontrolador, mas era um processador). Você fez tudo isso no papel e não usou linguagens de programação de hardware; na verdade, escreveu as equações lógicas, mas escolheu com mais cuidado os padrões de bits das instruções para tornar o número de portas e os fios para conectá-los tão simples tão prático. No papel, você precisava criar manualmente uma longa lista de portas lógicas com fio e depois desenhar os componentes reais em uma versão ampliada da máscara de silicone. Até hoje, os chips são feitos usando o que é semelhante a um processo fotográfico ou serigráfico em termos de laymans, para que você faça essas cópias azuis e reduza-as e depois as aplique nas camadas de silicone.
aqui novamente, no dia em que todos tinham um controle melhor sobre a montagem, e você não apenas terminava fazendo alguma programação de montagem, como também não possuía um editor de texto nem um montador, que precisaria escrever seus primeiros programas manualmente em papel e, em seguida, usando um manual de referência, convertido manualmente para código de máquina, uns e zeros. Em alguns desses computadores, talvez você precise carregar o ram pressionando os interruptores, inverter os bits de endereço, inverter os bits de dados até que correspondam aos números do seu papel, aumentar o tempo do relógio para cima e para baixo e carregar um local de memória com um byte de uma instrução do seu programa, repita algumas centenas de vezes mais e espero que você não cometa erros.
Da mesma forma que o primeiro digamos que o compilador C provavelmente foi escrito em algum outro idioma, ele se tornou auto-hospedado ao ser reescrito em C e compilado pelo primeiro compilador C e novamente por si só. Em seguida, os compiladores C foram usados para inventar outras linguagens de programação que se tornaram auto-hospedadas. Nós inventamos sistemas operacionais e editores de texto que se baseavam em si mesmos, e é tudo magia negra deixada para algumas pessoas atrás da cortina no canto ...
sim, por muito tempo, é uma grande questão que precisa de anos de estudo e experiência para realmente entender. olhe para o meu lsasim, não pretendo ser especialista em nada, mas é um conjunto de instruções, existe um simulador que executa a instrução escrita em C e outra implementação do processador implementada em uma linguagem de programação de hardware que pode ser simulado usando diferentes ferramentas. Além de um montador bruto e algumas outras ferramentas e tal. Talvez, examinando parte disso, em particular o código da linguagem de programação de hardware, possa fechar a lacuna no que eu suponho que você estava perguntando. Se eu não tiver preenchido essa lacuna ou tiver feito uma tangente longa, por favor, avise-me que removerei essa resposta por acaso (supondo que eu seja capaz de não sair muito na troca de programadores).
fonte
As CPUs operam com 0 e 1. Todas as instruções tinham uma sequência de bits que as definia. Este foi o código da máquina. É tão difícil para os humanos lerem e escreverem. Como primeiro passo, agrupamos os zeros e zeros em sequências de 4 bits e usamos 0 a F para representá-los. Isso reduziu os números que precisávamos memorizar, mas ainda não foi fácil lembrar o código hexadecimal para obter instruções.
Então começamos a usar a montagem que tinha "palavras" como MOV e ADD. O montador substituía as instruções pelo conjunto correto de 0 'e 1 convertendo a "listagem" do conjunto em código de máquina.
Eventualmente, desenvolvemos linguagens de nível "superior", em que "instruções" poderiam representar seqüências inteiras de código de máquina.
fonte
Recentemente, deparei-me com essa pergunta e mais ou menos um ano atrás, quando comecei a percorrer esse caminho; Eu teria achado que este é um recurso muito bom e uma página de referência em relação às minhas próprias questões relacionadas.
Parte 1: -Preface-
Um pouco sobre mim:
Em meados do final dos anos 80, quando eu ainda estava na escola, eu desmontava aparelhos de som, videocassetes e outros aparelhos eletrônicos que estavam entre os anos 50 e 80 e olhava para as placas de circuito e sempre quis saber como eles funcionavam. trabalho ... Como eles realmente adquiriram o sinal de transmissão, produzem áudio, vídeo, fazem isso e aquilo etc ... Eu reconhecia as partes individuais aqui e ali, como resistores, capacitores, diodos e transistores, mas não saber o que eles fizeram ou como eles funcionaram em uma idade tão jovem.
Ao longo dos anos, sempre fui excepcional em Matemática, Física e Química. Eu entendia matemática bastante e até conseguia ler alguns circuitos simples ou básicos do ensino médio e do ensino médio que vieram mais tarde, mas nunca consegui aprender sobre os portões lógicos e como eles foram construídos ... aprenda Álgebra Booleana no ensino médio com minha turma de Honras em lógica, probabilidade e estatística. Todas as minhas aulas de matemática e ciências eram honras. Não fiz Cálculo até meu segundo semestre em uma faculdade comunitária. Eu testei fora da faculdade de Álgebra e tomei Trigonometria como um curso de reciclagem. Meu nível mais alto de matemática da sala de aula é o Cálculo II de uma única variável.
Eu jogo videogame desde os 3 ou 4 anos de idade. Quando criança, eu tinha o Atari, o NES, o Sega Genesis e o PS1. Quando fiquei mais velho, entre o final da adolescência e o início dos 20, adquiri o PS2 e o SNES com títulos selecionados preferidos. Isso também não conta para jogos de PC que remontam ao Doom!
Eu sempre fui um ávido jogador de console e PC e isso não inclui jogos de pinball e arcade.
Recebi meu primeiro PC quando tinha cerca de 12 anos no Natal, no início dos anos 90. Os dias do DOS 6.0 e Win 3.11 ou OS / 2. Desde então, eu sempre estive familiarizado com a família de sistemas operacionais "Windows" e todos os sistemas que tive eram da arquitetura Intel. Eu tive uma experiência limitada com Apple ou Mac da escola ou faculdade, mas nunca tive o privilégio de trabalhar em sistemas Linux. Eu tenho o Cygwin e já tentei aprender bash, mas estou tão acostumado ao Dos ou à sintaxe do prompt de comando.
No início dos anos 90, eu pegava uma ou duas cópias do PC-World e digitava os trechos de código no QBasic que eu não conhecia muito bem e tentava fazer esses programas funcionarem. O único que obteve sucesso foi um programa para transformar as teclas pressionadas na linha inicial de teclas em diferentes sons de toque. Não quero dizer os toques de um telefone celular, quero dizer uma frequência contínua, desde que você mantenha a tecla pressionada.
Sempre foi uma paixão minha não apenas querer saber como os dispositivos eletrônicos funcionavam dentro da circunferência nos níveis digital e lógico, aprender a programar um computador, mas sempre tive o desejo de fazer meu próprio vídeo jogos Mesmo no início dos anos 90, eu queria fazer os jogos Frogger e Tetris ...
Essa se tornou minha principal motivação e desejo de enfrentar um dos tipos mais difíceis de programação ou desenvolvimento de software no campo da Ciência da Computação, que é o 3D Game Engine Design. Existem outros campos na Ciência da Computação que são igualmente difíceis, no entanto, qualquer mecanismo de jogo sofisticado incluirá normalmente ou quase todos eles, já que os componentes ou sub-motores individuais exigem suas técnicas e / ou propriedades.
Eu tinha alguma experiência em programação nos meus dias do ensino médio, mas isso estava limitado ao horrível Visual Basic. Comecei a aprender C / C ++ por volta de 2002 - 2003 até poucos anos depois de me formar no ensino médio, em 1999. Até hoje, não tenho nenhuma experiência na faculdade em Ciência da Computação ou Engenharia de Computação, mas através de dedicação e determinação, aprendi quase todos os conceitos existentes em computadores, hardware, programação, algoritmos, etc. e continuo aprendendo o máximo que posso ...
Durante os primeiros dias de aprendizado de C / C ++, eu tinha acesso à Internet, mas a Internet estava em seus estágios iniciais, sites como Amazon, Youtube, Facebook etc. ainda não existiam, ainda eram os dias de 56k modems dial-up que aumentam sua linha telefônica se você não tiver uma segunda linha dedicada. Levaria alguns minutos apenas para uma imagem renderizar na tela, não importa a reprodução contínua de vídeo.
Portanto, quando se tratava de pesquisar e aprender a programar em C ++, os recursos eram limitados e a maioria estava em formato de texto. Ao tentar abordar os projetos desde os primeiros dias de tutoriais na Internet, muitos desses projetos não estavam totalmente completos, os escritores eram profissionais ou estudantes universitários e fizeram muitas suposições de que o leitor já estava familiarizado com muitos dos conceitos necessários, como compilação , vinculação e depuração e integração de biblioteca.
Para alguém que não sabe nada sobre esses tópicos, fica perplexo porque não sabe o que deu errado, nem como corrigi-lo e como fazê-lo funcionar corretamente. Levei muitas horas de tentativa e erro naqueles dias com recursos muito limitados. Pedir ajuda, como podemos agora, com este site ou procurar explicações detalhadas que você pode encontrar na cppreference, não estava disponível! Se você, pessoalmente, não conhecia ninguém, não havia tantos que você poderia pedir ajuda!
À medida que o tempo passava, aprimorei alguns dos meus conhecimentos aqui e ali, e, eventualmente, a Internet melhorou para DSL, e agora a Internet de alta velocidade, os sites se tornaram mais interativos, os vídeos começaram a aparecer, a qualidade dos vídeos melhorou com o tempo, sites como como o YouTube começou a aparecer e as coisas se tornaram um pouco mais fáceis no lado da pesquisa. Mais e mais tutoriais se tornaram disponíveis, alguns eram bons e úteis onde outros ensinavam más práticas ...
Também passei bastante tempo encontrando e adquirindo as ferramentas necessárias para o desenvolvimento. Eu tive que aprender a sintaxe da linguagem, o compilador e o processo de compilação, vinculação, construção e depuração. Então tive que aprender sobre as diferentes bibliotecas e APIs disponíveis e como configurar meus projetos ou soluções para vincular todas essas dependências.
Ao longo dos anos, observei a linguagem C ++ crescer, evoluir e se adaptar ao longo do tempo. No começo, permaneceu praticamente o mesmo por muitos anos, mas nos últimos 10 anos mudou drasticamente nesse curto espaço desde o início.
Menciono tudo isso porque o C ++ é uma das linguagens mais difíceis de dominar por causa de sua versatilidade, poder, rico conjunto de recursos e a capacidade de permitir que você atinja seu próprio pé! E mesmo com todas as suas ressalvas, é uma das linguagens mais poderosas e preferidas usadas nos principais líderes do setor como padrão para esse tipo de desenvolvimento, porque quando é feita corretamente, é rápida, concisa, confiável e usa o menor pegada.
Desde então, sou autodidata em C / C ++ há muitos anos, com a intenção e o foco em aprender programação de gráficos 3D e design de mecanismos de jogos. Eu dediquei de 100 a 1.000 horas de pesquisa, pesquisa e muito mais na leitura, aprendizagem e aplicação desse conhecimento na criação de produtos e aplicativos úteis. Eu sempre tive vontade e desejo de aprender mais para melhorar minhas habilidades e habilidades.
Esse foi o primeiro estágio, então eu comecei a ler e trabalhar com o DirectX 9.c, o que fiz em C / C ++ e até C #. Então mudei para o DirectX 10 e o Legacy OpenGL 1.0. A partir deles vieram o DirectX 11 e o OpenGL 3.x - 4.xe agora tentei a minha mão no Vulkan.
Criei mecanismos de jogos bem-sucedidos, trabalhando com vários tutoriais on-line, tanto nos formatos de texto quanto de vídeo. Eu já afirmei que tinha uma sólida formação em matemática, mas estava limitada ao Cálculo I e II. Eu tive que me ensinar Vector Calculus, que eu tinha algum conhecimento da minha aula de Física baseada em cálculo na faculdade, mas quanto à Álgebra Linear com Transformações Afins e Geometria Analítica, eu tive que aprendê-las por conta própria quando certas equações, funções, métodos, algoritmos e conceitos eram necessários. Depois, tive que aprender a traduzi-los em código eficiente, legível, confiável e reutilizável, genérico e sem erros, possível, colocando centenas a milhares de horas de depuração.
Foi uma jornada maravilhosa aprender os tópicos e algoritmos que incluem gerenciamento de memória, contagem de referência, instanciação, recursão e muito mais que são usados em muitos, senão em todos os componentes de um mecanismo de jogo onde eles são vastos. Eu poderia listar todos eles aqui, mas isso seria informação suficiente para preencher 3 ou 4 respostas em espaço de resposta. No entanto, incluirei a lista dos tópicos gerais, não apenas os sub-tópicos.
Aqui estão os tópicos ou a lista de assuntos do que consiste em um mecanismo de jogo totalmente funcional, que inclui todas as várias técnicas de renderização, configurando os pipelines de renderização e sombreador, técnicas de sombreamento e iluminação via sombreadores, pré e pós-processamento, buffers de quadro, buffers de volta , carregamento de imagem, carregamento e análise de áudio e modelo, criando formas primitivas com propriedades de material de cor, textura e coordenadas normais com mapeamento manual de texturas, transformações de objetos, tipos de câmera, hierarquias de gráficos de cena, classes de gerente para texturas, áudio, fontes e shaders e gerenciamento de memória, sistema de registro com tratamento de exceções, técnicas de programação multithread e paralela, rede, mecanismo físico, detecção de colisão, gerador de partículas, animação, IA de jogo, geração de terreno, caixas de céu e domos de céu, renderização de água,folhagem e muito mais ..., GUIs com fonte texturizada para renderização de texto, sobreposições de HUD, inventários, geração de mapas e macro, sistema de estado e máquinas de estado e, finalmente, escrevendo um analisador para criar sua própria linguagem de script para automatizar muitos desses objetos a capacidade de alterar valores de dados no mecanismo sem precisar recompilar apenas carregando os arquivos de dados para preencher os objetos e estruturas de dados em seus respectivos contêineres na inicialização do aplicativo.e, finalmente, gravando um analisador para criar sua própria linguagem de script para automatizar muitos desses objetos e alterar os valores dos dados no mecanismo sem precisar recompilar apenas carregando nos arquivos de dados para preencher os objetos e estruturas de dados em seus respectivos contêineres na inicialização do aplicativo.e, finalmente, gravando um analisador para criar sua própria linguagem de script para automatizar muitos desses objetos e alterar os valores dos dados no mecanismo sem precisar recompilar apenas carregando nos arquivos de dados para preencher os objetos e estruturas de dados em seus respectivos contêineres na inicialização do aplicativo.
Ao longo dos anos, fiquei intrigado em querer aprender a linguagem assembly, pelo que eu queria aprender sobre compiladores, montadores e sistemas operacionais simples, quero dizer o funcionamento interno, como eles são construídos e projetados.
O tempo passou e então eu dei um passo para o lado e comecei a aprender a emulação de hardware. Eu me concentrei especificamente no NES, mas queria aprender a emulação de hardware de CPUs em geral. Isso me levou a aprender sobre o conjunto de instruções em que eu já conhecia o conceito e o que era, já que eu já estava familiarizado com a família x86 da Intel até certo ponto, mas agora eu tinha que aprender o conjunto de instruções 6502.
No entanto, mergulhando nisso, acabei fazendo mais pesquisas e comecei a aprender sobre a arquitetura do conjunto de instruções da perspectiva da engenharia. Isso me levou a aprender sobre como a CPU é construída a partir das portas lógicas e como as portas lógicas são construídas a partir de transistores junto com outros vários componentes elétricos. Acabei aprendendo sobre isso de duas perspectivas, de cima para baixo e de baixo para cima. Ambos os métodos foram muito eficazes e acho que aprender com os dois ajuda a criar essa ponte ou lacuna onde o software consome o hardware.
A partir disso, tive que atualizar minha Álgebra Booleana e acabei aprendendo sobre K-Maps, Tabelas de Implicação, Máquinas de Estado Mealy e Moore e várias outras coisas que relacionam Lógica Binária e Aritmética aos Portões Lógicos Físicos e Circuitos Integrados. E isso me leva ao passado ressentido, onde comecei a trabalhar com o Logisim e comecei a aprender HDL, VHDL, Verilog, etc.
Eu tenho aprendido tudo isso no meu tempo livre, quando pude nos últimos 15 a 18 anos.
Aqui estão alguns dos sites e links que me guiaram ao longo dos anos. Muitos desses sites são recentes, já que muitos dos sites de que aprendi originalmente não existem mais, perdi os links e não me lembro, ou os mecanismos de pesquisa os colocaram no fundo de suas listas de pesquisa ...
Idiomas - C ++
Tutoriais de gráficos 3D e sites de recursos
As séries e canais do YouTube cobrem os tópicos acima, além de hardware, computador e engenharia elétrica. Há muitos para listar, por isso vou listar alguns deles que acho mais úteis e úteis. Não fornecerei os links, mas você pode pesquisar no YouTube por esses canais.
E isso não leva em consideração alguns dos vários livros que tenho sobre esses tópicos.
-Nota- Não vote nisto, pois isso é apenas uma mensagem para o leitor de minha própria experiência pessoal e é nulo de qualquer tentativa de responder ou fazer referência à pergunta original. Nos próximos dias, quando eu tiver tempo; Vou adicionar uma resposta de acompanhamento para refletir sobre a pergunta do OP, fornecendo links úteis como referência e conjunto de recursos, e atualizarei essa resposta para incluir alguns links aqui e modificar esta nota. É tarde e, atualmente, não tenho tempo para revisar e editar o que já escrevi. Eu farei isso quando puder ".
fonte
No seu núcleo, uma CPU geralmente é apenas uma máquina de estado. Portanto, você precisará entender como portas lógicas e flip-flops ou registros se combinam para fabricar máquinas de estado.
Uma máquina de estado pega as entradas e o estado atual, executa-as através da lógica booleana (e potencialmente aritmética) e, em seguida, fornece saídas e um próximo estado. Uma das entradas pode ser o registro de instruções. Uma das saídas pode ser uma ativação e uma seleção para a fonte recarregar o registro de instruções, talvez também incrementar ou carregar outro registro atuando como um contador de programa. Com isso, além de alguma memória endereçável, você pode sequenciar as instruções.
Depois de ter uma maneira de sequenciar as instruções, você pode usar a lógica para decodificar esses bits de instrução, além do estado atual, em outro monte de bits de controle. Alguns desses bits de controle podem atuar como entradas para controlar um monte de lógica que pode executar lógica aritmética e de toda a palavra, chamada ALU. Outros bits podem carregar coisas ou selecionar entradas para a ALU. Outros bits podem dizer onde armazenar os resultados da ULA. Ou carregar registros de endereçamento. Ou escreva na memória ou em outras saídas. Etc.
Parte do projeto de um conjunto de instruções é apenas descobrir quais combinações de bits, quando decodificadas, controlam todos os registros e o seqüenciamento de máquinas de estados. Isso foi feito e (re) otimizou milhares de maneiras diferentes.
Existem pelo menos três níveis de livros universitários sobre esse assunto não trivial.
fonte