{"id":5,"date":"2024-10-01T06:28:32","date_gmt":"2024-10-01T06:28:32","guid":{"rendered":"https:\/\/blogs.oregonstate.edu\/gevkob\/?p=5"},"modified":"2024-10-01T06:37:38","modified_gmt":"2024-10-01T06:37:38","slug":"how-cpus-understand-0s-and-1s","status":"publish","type":"post","link":"https:\/\/blogs.oregonstate.edu\/gevkob\/2024\/10\/01\/how-cpus-understand-0s-and-1s\/","title":{"rendered":"How CPUs Understand 0s and 1s"},"content":{"rendered":"\n<p>I recently started an exciting project: building an NES emulator in C++. An emulator allows a computer to mimic the behavior of other hardware\u2014in my case, the Nintendo Entertainment System. It works by loading a copy of an NES game&#8217;s memory, and executing the program in a similar way a real NES would. This means replicating the behavior of the CPU, the PPU (Picture Processing Unit), and the APU (Audio Processing Unit). <\/p>\n\n\n\n<p>I chose to start with the brain of the system, the CPU. The NES used a variant of the MOS Technology 6502 CPU, a legendary 8-bit microprocessor found in other tech of the time, like the Commodore 64, Atari 5200, and the Apple II computer just to name a few. So, I sought out to learn how a CPU works.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Instruction Execution<\/h2>\n\n\n\n<p>CPUs execute instructions. The &#8220;8-bit&#8221; part means that data is processed in 8-bit chunks. The 6502 registers\u2014small, high-speed memory areas used to hold temporary variables\u2014are 8 bits wide, which means instructions typically manipulate 8-bit numbers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is an Instruction?<\/h3>\n\n\n\n<p>An instruction is a directive telling the CPU to do something like moving data around, perform a calculation, or jump to another section of the program. Here&#8217;s a snippet of 6502 assembly code to illustrate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>LDA #$01 ;Load the value 01 into the accumulator register\nTAX      ;Transfer value from accumulator to the X register\nINX      ;Increment the X register by one\nBRK      ;Break, or stop the program<\/code><\/pre>\n\n\n\n<p>We load a value into register A, transfer it into X, and then increment X. In a higher level language, the operation might look like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int A = 1;\nint X = A;\nX = X + 1;\n\/\/ End program<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Assembly vs. Machine Code<\/h3>\n\n\n\n<p>To make the CPU understand any given instruction, we have to decode or &#8220;disassemble&#8221; the instruction into machine code. Figuring out how to assemble and disassemble instructions sounds like a great weekend, but it&#8217;s not required for the CPU emulation. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Executing Machine Code<\/h3>\n\n\n\n<p>Looking back at the first line of the assembly snippet, <code>LDA #$01<\/code> can be written as <code>0xA9 0x01<\/code>. You may have guessed it, but <code>0xA9<\/code> maps to <code>LDA<\/code> and <code>0x01<\/code> to <code>01<\/code> respectively. <\/p>\n\n\n\n<p>To understand how, let&#8217;s load the above program into memory, starting at the address <code>0x0000<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-group is-content-justification-left is-nowrap is-layout-flex wp-container-core-group-is-layout-fc9f69e7 wp-block-group-is-layout-flex\">\n<pre class=\"wp-block-code\"><code>0x0000\n0x0001\n0x0002\n0x0003\n0x0004<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code wp-container-content-9cfa9a5a\"><code>0xA9      ;LDA #$01\n0x01\n0xBA      ;TAX\n0xE8      ;INX\n0x00      ;BRK<\/code><\/pre>\n<\/div>\n\n\n\n<p>Let&#8217;s briefly talk about how the CPU would execute this code.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The program counter (PC), starts program execution at address <code>0x0000<\/code>.<\/li>\n\n\n\n<li>The CPU sees <code>0xA9<\/code> and recognizes it as a valid opcode that maps to a 2-byte instruction that tells the CPU to load the next byte of memory into the A register.<\/li>\n\n\n\n<li>The next byte of memory is <code>0x0001<\/code>, where PC is currently located. The value at this address, <code>0x01<\/code> gets loaded into the A register and PC increments to the next address, <code>0x0002<\/code><\/li>\n\n\n\n<li>The CPU recognizes <code>0xBA<\/code> as a valid opcode for TAX, a 1-byte instruction. It transfers the value from register A to register X and increments the program counter to the next address, <code>0x0003<\/code><\/li>\n\n\n\n<li>At <code>0x0003<\/code> we have another 1-byte instruction set, which increments the value in register X and moves the PC to <code>0x0004<\/code><\/li>\n\n\n\n<li>The program sees <code>BRK<\/code> and stops execution<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Where do Opcodes Come From?<\/h3>\n\n\n\n<p>The chip manufacturer designs the instructions and determines which opcode maps to which instruction. Programmers have to use a data sheet\u2014chip manual also provided by the manufacturer\u2014to get relevant chip information. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">More than Just Bits and Bytes<\/h2>\n\n\n\n<p>The 6502 CPU has 56 instructions, all represented by some value between <code>0x00<\/code> and <code>0xFF<\/code>. The &#8220;aha!&#8221; moment came when I realized that at its core, the CPU is just an interpreter. In essence, the process of developing the 6502 emulator has been:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Load an opcode into memory<\/li>\n\n\n\n<li>Implement the instruction for the given opcode<\/li>\n\n\n\n<li>Execute the instruction and test to make sure the registers and memory are updated correctly.<\/li>\n<\/ul>\n\n\n\n<p>Of course, it&#8217;s not the whole picture; I&#8217;m still deep in the weeds of trying to understand how everything works, but the work I&#8217;ve done so far has given me a newfound appreciation for how computers work. It&#8217;s like discovering that the &#8220;magic&#8221; of computers is a sequence operations executed perfectly in sync. <\/p>\n\n\n\n<p>If you&#8217;re curious about NES emulation, here are some of the resources I used to get started:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.masswerk.at\/6502\/6502_instruction_set.html\">Interactive 6502 instruction set<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.nesdev.org\/wiki\/Nesdev_Wiki\">NESdev Wiki<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/Steps to emulate a NES emulator\">Steps to emulate a NES emulator (Reddit Post)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.reddit.com\/r\/EmuDev\/\">r\/EmuDev<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently started an exciting project: building an NES emulator in C++. An emulator allows a computer to mimic the behavior of other hardware\u2014in my case, the Nintendo Entertainment System. It works by loading a copy of an NES game&#8217;s memory, and executing the program in a similar way a real NES would. This means [&hellip;]<\/p>\n","protected":false},"author":14539,"featured_media":7,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[4,3,5],"class_list":["post-5","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-computer-science","tag-6502-cpu","tag-nes-emulation","tag-systems-programming"],"_links":{"self":[{"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/posts\/5","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/users\/14539"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/comments?post=5"}],"version-history":[{"count":5,"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/posts\/5\/revisions"}],"predecessor-version":[{"id":16,"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/posts\/5\/revisions\/16"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/media\/7"}],"wp:attachment":[{"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/media?parent=5"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/categories?post=5"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/gevkob\/wp-json\/wp\/v2\/tags?post=5"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}