Robert M Posted November 18, 2004 Share Posted November 18, 2004 Assembly Language Programming - Lesson 10 - Memory Pages & Hexadecimal Numbers ============================================================================== In this lesson I will explain what is meant by "pages" when used talk about computer memory. I will also teach you how to write numbers in hexidecimal notation, and how to convert numbers between decimal and hexidecimal. Pages in Memory: ---------------- In the prevoius lesson I showed you memory maps and how they map all the devices in a computer system to addresses in the address space of the CPU. To access a device the CPU places its address on the address bus. We have already learned that the address bus is 16-bits wide which is the same as 2 bytes. So it takes 2 bytes for form a complete address. Like this: 15 8 7 0 +--------+--------+ |xxxxxxxx|xxxxxxxx| The structure of a 16-bit address +--------+--------+ High-byte|Low-byte | Page # | byte # One way to look as memory is to divide it into equal chunks with each chunk having 256 bytes. Starting with a 65536 addresses you end up with 256 chunks with 256 bytes each. Let the high-byte of an address be the number of the chunk to be accessed, and let the Low-byte be the byte within the chunk that is being accessed. Another name for a chunk of 256 bytes is a page of memory. So a 650x system has 256 pages of memory. Each page is referred to by its number which is the same as the number in the High-byte of the address. Pages are important to you as a programmer because when the CPU has to cross a page boundary in memory to complete some instructions, those instructions are slowed down and take an extra cycle to complete. That slow down can ruin the timing you planned in your program, and the result is a bad television image. When we discuss instructions in future lessons that are sensitive to page boundaries I will point them out to you. Memory pages are not all bad. Zero page is a special page in a 650X system. The zero page is the first 256 memory addresses from 0 to 255. The high-byte of the address is always zero. Many instructions are 1 clock cycle faster if they are accessing memory in the zero page. The primary image for the 128 bytes of RAM as well as the TIA chip are located in the zero page of the VCS memory map. So when you access these devices in your code you can do so 1 cycle faster. That's all that needs to be said about memory pages for now. The impact of pages on your programming will be a common topic in future lessons. --------------------------------------------------------------------------------- Hexadecimal Notation: --------------------- In lesson 4, you learned how to count in binary with just two digits 0 and 1. You already knew how to count in decimal which has ten digits: 0, 1, 2, 3, 4, 5, 6, 7 ,8 ,9. Well, hexadecimal is counting with 16 digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. Notice that the first 10 digits are the same as for decimal, but for the digits 11 through 15 we use the letters A through F. Hexadecimal numbers are handy for you the programmer because each hex digit is equivalent to exactly four binary digits: Hex Binary Decimal --- ------ ------- $0 = %0000 = 0 $1 = %0001 = 1 $2 = %0010 = 2 $3 = %0011 = 3 $4 = %0100 = 4 $5 = %0101 = 5 $6 = %0110 = 6 $7 = %0111 = 7 $8 = %1000 = 8 $9 = %1001 = 9 $A = %1010 = 10 $B = %1011 = 11 $C = %1100 = 12 $D = %1101 = 13 $E = %1110 = 14 $F = %1111 = 15 You may have noticed that I proceded each of the Hexadecimal numbers with the '$' dollar sign symbol. It is standard practice in assembly languages to indicate a number is in Hexadecimal by preceding it with a dollar sign. This is no different than the use of a '%' percent sign to inidicate a binary number and it is important. The numbers $101, %101, and 101 are not equal! As a VCS programmer you will encounter Hexadecimal numbers in the listing files produced by the DASM tool. All address and symbol values are reported in hexadecimal. The tool is rude though in that it does not preceed the numbers with a dollar sign. :P In these lessons I plan to restrict the number formats that I use to binary and decimal which should do everything we need and increase your understanding of the underlying programming principles rather than making you lose time converting hex numbers. I will avoid using hexadecimal unless the compiler is using it, and the case is one where aping the compiler will make it easier to understand. How to convert between Decimal and Hexidecimal: ----------------------------------------------- Get yourself a scientific calculator. Yes we could slog through dividing decimal numbers by 16 and hexadecimal numbers by 10, but ye gods! why bother? Get a calculator that can convert between the number systems and you are set. I should point out that both Windows and Macintosh OS provided calculators can perform these conversions but you may have to turn on Advanced mode. I don't know what is out there for Linux but I am sure there is something. Exercises: ---------- If you are looking for something to do to drive home these lessons. I recommend that you convert the decimal addresses in VCS memory map below into there Hexadecimal equivalents. VCS Memory map: ************************ Addresses: 0 to 47 = TIA Control Registers Primary Image 48 to 95 = [shadow] TIA Control Registers 96 to 127 = [shadow-partial] TIA Control Registers 128 to 255 = 128 bytes of RAM Primary Image (zero page image allow fast access) 256 to 303 = [shadow] TIA Control Registers 304 to 351 = [shadow] TIA Control Registers 352 to 383 = [shadow-partial] TIA Control Registers 384 to 511 = [shadow] 128 bytes of RAM (The CPU stack uses this image) 512 to 559 = [shadow] TIA Control Registers 560 to 607 = [shadow] TIA Control Registers 608 to 639 = [shadow-partial] TIA Control Registers 640 to 671 = 6532-PIA I/O ports and timer Control Registers Primary image 672 to 703 = [shadow] 6532-PIA Control Registers 704 to 735 = [shadow] 6532-PIA Control Registers 736 to 767 = [shadow] 6532-PIA Control Registers 768 to 815 = [shadow] TIA Control Registers 816 to 863 = [shadow] TIA Control Registers 864 to 895 = [shadow-partial] TIA Control Registers 896 to 927 = [shadow] 6532-PIA Control Registers 928 to 959 = [shadow] 6532-PIA Control Registers 960 to 991 = [shadow] 6532-PIA Control Registers 992 to 1023 = [shadow] 6532-PIA Control Registers 1024 to 2047 = [shadows] Repeat the entire pattern from $0000-03FF 2048 to 3071 = [shadows] Repeat the entire pattern from $0000-03FF 3072 to 4095 = [shadows] Repeat the entire pattern from $0000-03FF 4096 to 6143 = Lower 2K Cartridge ROM (4K carts start here) 6144 to 8191 = Upper 2K Cartridge ROM (2K carts go here) 8192 to 65535 = [shadows] Repeat the entire pattern from $0000-1FFF, seven times. Ha! I just noticed I forgot to change the Hex numbers on the right side of my VCS memory map from hex to decimal in the prevous lesson. Consider that mistake to be a head start for you. Any questions? ********************************************************************************** Quote Link to comment Share on other sites More sharing options...
Rob Mitchell Posted November 24, 2004 Share Posted November 24, 2004 Complete VCS Memory map: ************************ Addresses: $0 to $2F = TIA Control Registers Primary Image 30 to 5F = [shadow] TIA Control Registers 60 to 7F = [shadow-partial] TIA Control Registers 80 to FF = 128 bytes of RAM Primary Image (zero page image allow fast access) 100 to 12F = [shadow] TIA Control Registers 130 to 15F = [shadow] TIA Control Registers 160 to 17F = [shadow-partial] TIA Control Registers 180 to 1FF = [shadow] 128 bytes of RAM (The CPU stack uses this image) 200 to 22F = [shadow] TIA Control Registers 230 to 25F = [shadow] TIA Control Registers 260 to 27F = [shadow-partial] TIA Control Registers 280 to 29F = 6532-PIA I/O ports and timer Control Registers Primary image 2A0 to 2BF = [shadow] 6532-PIA Control Registers 2C0 to 2DF = [shadow] 6532-PIA Control Registers 2E0 to 2FF = [shadow] 6532-PIA Control Registers 300 to 32F = [shadow] TIA Control Registers 330 to 35F = [shadow] TIA Control Registers 360 to 37F = [shadow-partial] TIA Control Registers 380 to 39F = [shadow] 6532-PIA Control Registers 3A0 to 3BF = [shadow] 6532-PIA Control Registers 3C0 to 3DF = [shadow] 6532-PIA Control Registers 3E0 to 3FF = [shadow] 6532-PIA Control Registers 400 to 7FF = [shadows] Repeat the entire pattern from $0000-03FF 800 to BFF = [shadows] Repeat the entire pattern from $0000-03FF C00 to FFF = [shadows] Repeat the entire pattern from $0000-03FF 1000 to 17FF = Lower 2K Cartridge ROM (4K carts start here) 1800 to 1FFF = Upper 2K Cartridge ROM (2K carts go here) 2000 to $FFFF = [shadows] Repeat the entire pattern from $0000-1FFF, seven times. I did it! My HP200LX palmtop has a Hex, Dec, Oct, Bin calculator built-in! Rob Mitchell, Atlanta, GA Quote Link to comment Share on other sites More sharing options...
Robert M Posted November 24, 2004 Author Share Posted November 24, 2004 Complete VCS Memory map: ************************ Addresses: $0 to $2F = TIA Control Registers Primary Image ... snip ... 2000 to $FFFF = [shadows] Repeat the entire pattern from $0000-1FFF, seven times. I did it! My HP200LX palmtop has a Hex, Dec, Oct, Bin calculator built-in! Rob Mitchell, Atlanta, GA Yep! That's it. good work. I am expeecting to post Lesson 11 some day next week. Cheers, Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted November 24, 2004 Share Posted November 24, 2004 $0 to $2F = TIA Control Registers Primary Image 30 to 5F = [shadow] TIA Control Registers Actually there is a difference between those two, because the 2nd one only shadows the read-registers (collisions and input), but not the write-reagisters (e.g. GRPx, WSYNC, COLUPx etc.) This is sometime useful to know, when optimizing code. E.g.: ASL INPT4; shift bit7 into carry for later usage When using $0c for INPT4 here, you automatically change REFP1 too. By using $3c you can avoid that. Quote Link to comment Share on other sites More sharing options...
Robert M Posted November 24, 2004 Author Share Posted November 24, 2004 $0 to $2F = TIA Control Registers Primary Image 30 to 5F = [shadow] TIA Control Registers Actually there is a difference between those two, because the 2nd one only shadows the read-registers (collisions and input), but not the write-reagisters (e.g. GRPx, WSYNC, COLUPx etc.) This is sometime useful to know, when optimizing code. E.g.: ASL INPT4; shift bit7 into carry for later usage When using $0c for INPT4 here, you automatically change REFP1 too. By using $3c you can avoid that. Thanks Thomas, that is a good point you made. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.